Mercurial > hg > orthanc
diff OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp @ 5807:8279eaab0d1d attach-custom-data
merged default -> attach-custom-data
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Tue, 24 Sep 2024 11:39:52 +0200 |
parents | 75e949689c08 68fc5af30c03 |
children | 023a99146dd0 |
line wrap: on
line diff
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Thu Sep 15 18:13:17 2022 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Tue Sep 24 11:39:52 2024 +0200 @@ -2,8 +2,9 @@ * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -27,282 +28,303 @@ # error The plugin support is disabled #endif +#include "../../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h" #include "../../../OrthancFramework/Sources/Logging.h" #include "../../../OrthancFramework/Sources/OrthancException.h" #include "../../Sources/Database/ResourcesContent.h" #include "../../Sources/Database/VoidDatabaseListener.h" +#include "../../Sources/ServerToolbox.h" #include "PluginsEnumerations.h" +#include "OrthancDatabasePlugin.pb.h" // Auto-generated file + #include <cassert> -#define CHECK_FUNCTION_EXISTS(backend, func) \ - if (backend.func == NULL) \ - { \ - throw OrthancException( \ - ErrorCode_DatabasePlugin, "Missing primitive: " #func "()"); \ +namespace Orthanc +{ + static void CheckSuccess(PluginsErrorDictionary& errorDictionary, + OrthancPluginErrorCode code) + { + if (code != OrthancPluginErrorCode_Success) + { + errorDictionary.LogError(code, true); + throw OrthancException(static_cast<ErrorCode>(code)); + } + } + + + static ResourceType Convert(DatabasePluginMessages::ResourceType type) + { + switch (type) + { + case DatabasePluginMessages::RESOURCE_PATIENT: + return ResourceType_Patient; + + case DatabasePluginMessages::RESOURCE_STUDY: + return ResourceType_Study; + + case DatabasePluginMessages::RESOURCE_SERIES: + return ResourceType_Series; + + case DatabasePluginMessages::RESOURCE_INSTANCE: + return ResourceType_Instance; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + static DatabasePluginMessages::ResourceType Convert(ResourceType type) + { + switch (type) + { + case ResourceType_Patient: + return DatabasePluginMessages::RESOURCE_PATIENT; + + case ResourceType_Study: + return DatabasePluginMessages::RESOURCE_STUDY; + + case ResourceType_Series: + return DatabasePluginMessages::RESOURCE_SERIES; + + case ResourceType_Instance: + return DatabasePluginMessages::RESOURCE_INSTANCE; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + static FileInfo Convert(const DatabasePluginMessages::FileInfo& source) + { + return FileInfo(source.uuid(), + static_cast<FileContentType>(source.content_type()), + source.uncompressed_size(), + source.uncompressed_hash(), + static_cast<CompressionType>(source.compression_type()), + source.compressed_size(), + source.compressed_hash(), + source.custom_data()); } -namespace Orthanc -{ + + static ServerIndexChange Convert(const DatabasePluginMessages::ServerIndexChange& source) + { + return ServerIndexChange(source.seq(), + static_cast<ChangeType>(source.change_type()), + Convert(source.resource_type()), + source.public_id(), + source.date()); + } + + + static ExportedResource Convert(const DatabasePluginMessages::ExportedResource& source) + { + return ExportedResource(source.seq(), + Convert(source.resource_type()), + source.public_id(), + source.modality(), + source.date(), + source.patient_id(), + source.study_instance_uid(), + source.series_instance_uid(), + source.sop_instance_uid()); + } + + + static void Execute(DatabasePluginMessages::Response& response, + const OrthancPluginDatabaseV4& database, + const DatabasePluginMessages::Request& request) + { + std::string requestSerialized; + request.SerializeToString(&requestSerialized); + + OrthancPluginMemoryBuffer64 responseSerialized; + CheckSuccess(database.GetErrorDictionary(), database.GetDefinition().operations( + &responseSerialized, database.GetDefinition().backend, + requestSerialized.empty() ? NULL : requestSerialized.c_str(), + requestSerialized.size())); + + bool success = response.ParseFromArray(responseSerialized.data, responseSerialized.size); + + if (responseSerialized.size > 0) + { + free(responseSerialized.data); + } + + if (!success) + { + throw OrthancException(ErrorCode_DatabasePlugin, "Cannot unserialize protobuf originating from the database plugin"); + } + } + + + static void ExecuteDatabase(DatabasePluginMessages::DatabaseResponse& response, + const OrthancPluginDatabaseV4& database, + DatabasePluginMessages::DatabaseOperation operation, + const DatabasePluginMessages::DatabaseRequest& request) + { + DatabasePluginMessages::Request fullRequest; + fullRequest.set_type(DatabasePluginMessages::REQUEST_DATABASE); + fullRequest.mutable_database_request()->CopyFrom(request); + fullRequest.mutable_database_request()->set_operation(operation); + + DatabasePluginMessages::Response fullResponse; + Execute(fullResponse, database, fullRequest); + + response.CopyFrom(fullResponse.database_response()); + } + + class OrthancPluginDatabaseV4::Transaction : public IDatabaseWrapper::ITransaction { private: - OrthancPluginDatabaseV4& that_; - IDatabaseListener& listener_; - OrthancPluginDatabaseTransaction* transaction_; + OrthancPluginDatabaseV4& database_; + IDatabaseListener& listener_; + void* transaction_; + + void ExecuteTransaction(DatabasePluginMessages::TransactionResponse& response, + DatabasePluginMessages::TransactionOperation operation, + const DatabasePluginMessages::TransactionRequest& request) + { + DatabasePluginMessages::Request fullRequest; + fullRequest.set_type(DatabasePluginMessages::REQUEST_TRANSACTION); + fullRequest.mutable_transaction_request()->CopyFrom(request); + fullRequest.mutable_transaction_request()->set_transaction(reinterpret_cast<intptr_t>(transaction_)); + fullRequest.mutable_transaction_request()->set_operation(operation); + DatabasePluginMessages::Response fullResponse; + Execute(fullResponse, database_, fullRequest); - void CheckSuccess(OrthancPluginErrorCode code) const - { - that_.CheckSuccess(code); + response.CopyFrom(fullResponse.transaction_response()); } - - static FileInfo Convert(const OrthancPluginAttachment& attachment) - { - std::string customData; - return FileInfo(attachment.uuid, - static_cast<FileContentType>(attachment.contentType), - attachment.uncompressedSize, - attachment.uncompressedHash, - static_cast<CompressionType>(attachment.compressionType), - attachment.compressedSize, - attachment.compressedHash, - customData); - } - - static FileInfo Convert(const OrthancPluginAttachment2& attachment) + + void ExecuteTransaction(DatabasePluginMessages::TransactionResponse& response, + DatabasePluginMessages::TransactionOperation operation) { - return FileInfo(attachment.uuid, - static_cast<FileContentType>(attachment.contentType), - attachment.uncompressedSize, - attachment.uncompressedHash, - static_cast<CompressionType>(attachment.compressionType), - attachment.compressedSize, - attachment.compressedHash, - attachment.customData); + DatabasePluginMessages::TransactionRequest request; // Ignored + ExecuteTransaction(response, operation, request); } - - void ReadStringAnswers(std::list<std::string>& target) + + + void ExecuteTransaction(DatabasePluginMessages::TransactionOperation operation, + const DatabasePluginMessages::TransactionRequest& request) { - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - - target.clear(); - for (uint32_t i = 0; i < count; i++) - { - const char* value = NULL; - CheckSuccess(that_.backend_.readAnswerString(transaction_, &value, i)); - if (value == NULL) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - target.push_back(value); - } - } + DatabasePluginMessages::TransactionResponse response; // Ignored + ExecuteTransaction(response, operation, request); + } + + + void ExecuteTransaction(DatabasePluginMessages::TransactionOperation operation) + { + DatabasePluginMessages::TransactionResponse response; // Ignored + DatabasePluginMessages::TransactionRequest request; // Ignored + ExecuteTransaction(response, operation, request); } - bool ReadSingleStringAnswer(std::string& target) + void ListLabelsInternal(std::set<std::string>& target, + bool isSingleResource, + int64_t resource) { - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - - if (count == 0) - { - return false; - } - else if (count == 1) + if (database_.GetDatabaseCapabilities().HasLabelsSupport()) { - const char* value = NULL; - CheckSuccess(that_.backend_.readAnswerString(transaction_, &value, 0)); - if (value == NULL) + DatabasePluginMessages::TransactionRequest request; + request.mutable_list_labels()->set_single_resource(isSingleResource); + request.mutable_list_labels()->set_id(resource); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LIST_LABELS, request); + + target.clear(); + for (int i = 0; i < response.list_labels().labels().size(); i++) { - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - target.assign(value); - return true; + target.insert(response.list_labels().labels(i)); } } else { - throw OrthancException(ErrorCode_DatabasePlugin); - } - } - - - bool ReadSingleInt64Answer(int64_t& target) - { - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - - if (count == 0) - { - return false; - } - else if (count == 1) - { - CheckSuccess(that_.backend_.readAnswerInt64(transaction_, &target, 0)); - return true; - } - else - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - } - - - ExportedResource ReadAnswerExportedResource(uint32_t answerIndex) - { - OrthancPluginExportedResource exported; - CheckSuccess(that_.backend_.readAnswerExportedResource(transaction_, &exported, answerIndex)); - - if (exported.publicId == NULL || - exported.modality == NULL || - exported.date == NULL || - exported.patientId == NULL || - exported.studyInstanceUid == NULL || - exported.seriesInstanceUid == NULL || - exported.sopInstanceUid == NULL) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - return ExportedResource(exported.seq, - Plugins::Convert(exported.resourceType), - exported.publicId, - exported.modality, - exported.date, - exported.patientId, - exported.studyInstanceUid, - exported.seriesInstanceUid, - exported.sopInstanceUid); + // This method shouldn't have been called + throw OrthancException(ErrorCode_InternalError); } } - ServerIndexChange ReadAnswerChange(uint32_t answerIndex) + public: + Transaction(OrthancPluginDatabaseV4& database, + IDatabaseListener& listener, + TransactionType type) : + database_(database), + listener_(listener), + transaction_(NULL) { - OrthancPluginChange change; - CheckSuccess(that_.backend_.readAnswerChange(transaction_, &change, answerIndex)); - - if (change.publicId == NULL || - change.date == NULL) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - return ServerIndexChange(change.seq, - static_cast<ChangeType>(change.changeType), - Plugins::Convert(change.resourceType), - change.publicId, - change.date); - } - } - - - void CheckNoEvent() - { - uint32_t count; - CheckSuccess(that_.backend_.readEventsCount(transaction_, &count)); - if (count != 0) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - } - - - void ProcessEvents(bool isDeletingAttachment) - { - uint32_t count; - CheckSuccess(that_.backend_.readEventsCount(transaction_, &count)); - - for (uint32_t i = 0; i < count; i++) - { - OrthancPluginDatabaseEvent2 event; - CheckSuccess(that_.backend_.readEvent2(transaction_, &event, i)); + DatabasePluginMessages::DatabaseRequest request; - switch (event.type) - { - case OrthancPluginDatabaseEventType_DeletedAttachment: - listener_.SignalAttachmentDeleted(Convert(event.content.attachment)); - break; - - case OrthancPluginDatabaseEventType_DeletedResource: - if (isDeletingAttachment) - { - // This event should only be triggered by "DeleteResource()" - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - listener_.SignalResourceDeleted(Plugins::Convert(event.content.resource.level), event.content.resource.publicId); - } - break; - - case OrthancPluginDatabaseEventType_RemainingAncestor: - if (isDeletingAttachment) - { - // This event should only triggered by "DeleteResource()" - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - listener_.SignalRemainingAncestor(Plugins::Convert(event.content.resource.level), event.content.resource.publicId); - } - break; + switch (type) + { + case TransactionType_ReadOnly: + request.mutable_start_transaction()->set_type(DatabasePluginMessages::TRANSACTION_READ_ONLY); + break; + + case TransactionType_ReadWrite: + request.mutable_start_transaction()->set_type(DatabasePluginMessages::TRANSACTION_READ_WRITE); + break; - default: - break; // Unhandled event - } + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); } - } - - public: - Transaction(OrthancPluginDatabaseV4& that, - IDatabaseListener& listener, - OrthancPluginDatabaseTransactionType type) : - that_(that), - listener_(listener) - { - CheckSuccess(that.backend_.startTransaction(that.database_, &transaction_, type)); + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, database, DatabasePluginMessages::OPERATION_START_TRANSACTION, request); + + transaction_ = reinterpret_cast<void*>(response.start_transaction().transaction()); + if (transaction_ == NULL) { - throw OrthancException(ErrorCode_DatabasePlugin); + throw OrthancException(ErrorCode_NullPointer); } } virtual ~Transaction() { - OrthancPluginErrorCode code = that_.backend_.destructTransaction(transaction_); - if (code != OrthancPluginErrorCode_Success) + try { - // Don't throw exception in destructors - that_.errorDictionary_.LogError(code, true); + DatabasePluginMessages::DatabaseRequest request; + request.mutable_finalize_transaction()->set_transaction(reinterpret_cast<intptr_t>(transaction_)); + + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, database_, DatabasePluginMessages::OPERATION_FINALIZE_TRANSACTION, request); } + catch (OrthancException& e) + { + // Destructors must not throw exceptions + LOG(ERROR) << "Cannot finalize the database engine: " << e.What(); + } + } + + void* GetTransactionObject() + { + return transaction_; } virtual void Rollback() ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.rollback(transaction_)); - CheckNoEvent(); + ExecuteTransaction(DatabasePluginMessages::OPERATION_ROLLBACK); } virtual void Commit(int64_t fileSizeDelta) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.commit(transaction_, fileSizeDelta)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_commit()->set_file_size_delta(fileSizeDelta); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_COMMIT, request); } @@ -310,81 +332,106 @@ const FileInfo& attachment, int64_t revision) ORTHANC_OVERRIDE { - OrthancPluginAttachment2 tmp; - tmp.uuid = attachment.GetUuid().c_str(); - tmp.contentType = static_cast<int32_t>(attachment.GetContentType()); - tmp.uncompressedSize = attachment.GetUncompressedSize(); - tmp.uncompressedHash = attachment.GetUncompressedMD5().c_str(); - tmp.compressionType = static_cast<int32_t>(attachment.GetCompressionType()); - tmp.compressedSize = attachment.GetCompressedSize(); - tmp.compressedHash = attachment.GetCompressedMD5().c_str(); - tmp.customData = attachment.GetCustomData().c_str(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_add_attachment()->set_id(id); + request.mutable_add_attachment()->mutable_attachment()->set_uuid(attachment.GetUuid()); + request.mutable_add_attachment()->mutable_attachment()->set_content_type(attachment.GetContentType()); + request.mutable_add_attachment()->mutable_attachment()->set_uncompressed_size(attachment.GetUncompressedSize()); + request.mutable_add_attachment()->mutable_attachment()->set_uncompressed_hash(attachment.GetUncompressedMD5()); + request.mutable_add_attachment()->mutable_attachment()->set_compression_type(attachment.GetCompressionType()); + request.mutable_add_attachment()->mutable_attachment()->set_compressed_size(attachment.GetCompressedSize()); + request.mutable_add_attachment()->mutable_attachment()->set_compressed_hash(attachment.GetCompressedMD5()); + request.mutable_add_attachment()->set_revision(revision); - CheckSuccess(that_.backend_.addAttachment2(transaction_, id, &tmp, revision)); - CheckNoEvent(); + ExecuteTransaction(DatabasePluginMessages::OPERATION_ADD_ATTACHMENT, request); } virtual void ClearChanges() ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.clearChanges(transaction_)); - CheckNoEvent(); + ExecuteTransaction(DatabasePluginMessages::OPERATION_CLEAR_CHANGES); } virtual void ClearExportedResources() ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.clearExportedResources(transaction_)); - CheckNoEvent(); + ExecuteTransaction(DatabasePluginMessages::OPERATION_CLEAR_EXPORTED_RESOURCES); } - + virtual void DeleteAttachment(int64_t id, FileContentType attachment) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.deleteAttachment(transaction_, id, static_cast<int32_t>(attachment))); - ProcessEvents(true); + DatabasePluginMessages::TransactionRequest request; + request.mutable_delete_attachment()->set_id(id); + request.mutable_delete_attachment()->set_type(attachment); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_DELETE_ATTACHMENT, request); + + listener_.SignalAttachmentDeleted(Convert(response.delete_attachment().deleted_attachment())); } virtual void DeleteMetadata(int64_t id, MetadataType type) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.deleteMetadata(transaction_, id, static_cast<int32_t>(type))); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_delete_metadata()->set_id(id); + request.mutable_delete_metadata()->set_type(type); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_DELETE_METADATA, request); } virtual void DeleteResource(int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.deleteResource(transaction_, id)); - ProcessEvents(false); + DatabasePluginMessages::TransactionRequest request; + request.mutable_delete_resource()->set_id(id); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_DELETE_RESOURCE, request); + + for (int i = 0; i < response.delete_resource().deleted_attachments().size(); i++) + { + listener_.SignalAttachmentDeleted(Convert(response.delete_resource().deleted_attachments(i))); + } + + for (int i = 0; i < response.delete_resource().deleted_resources().size(); i++) + { + listener_.SignalResourceDeleted(Convert(response.delete_resource().deleted_resources(i).level()), + response.delete_resource().deleted_resources(i).public_id()); + } + + if (response.delete_resource().is_remaining_ancestor()) + { + listener_.SignalRemainingAncestor(Convert(response.delete_resource().remaining_ancestor().level()), + response.delete_resource().remaining_ancestor().public_id()); + } } virtual void GetAllMetadata(std::map<MetadataType, std::string>& target, int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getAllMetadata(transaction_, id)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_all_metadata()->set_id(id); - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_ALL_METADATA, request); + target.clear(); - for (uint32_t i = 0; i < count; i++) + for (int i = 0; i < response.get_all_metadata().metadata().size(); i++) { - int32_t metadata; - const char* value = NULL; - CheckSuccess(that_.backend_.readAnswerMetadata(transaction_, &metadata, &value, i)); - - if (value == NULL) + MetadataType key = static_cast<MetadataType>(response.get_all_metadata().metadata(i).type()); + + if (target.find(key) == target.end()) { - throw OrthancException(ErrorCode_DatabasePlugin); + target[key] = response.get_all_metadata().metadata(i).value(); } else { - target[static_cast<MetadataType>(metadata)] = value; + throw OrthancException(ErrorCode_DatabasePlugin); } } } @@ -393,45 +440,59 @@ virtual void GetAllPublicIds(std::list<std::string>& target, ResourceType resourceType) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getAllPublicIds(transaction_, Plugins::Convert(resourceType))); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_all_public_ids()->set_resource_type(Convert(resourceType)); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_ALL_PUBLIC_IDS, request); - ReadStringAnswers(target); + target.clear(); + for (int i = 0; i < response.get_all_public_ids().ids().size(); i++) + { + target.push_back(response.get_all_public_ids().ids(i)); + } } virtual void GetAllPublicIds(std::list<std::string>& target, ResourceType resourceType, - size_t since, - size_t limit) ORTHANC_OVERRIDE + int64_t since, + uint32_t limit) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getAllPublicIdsWithLimit( - transaction_, Plugins::Convert(resourceType), - static_cast<uint64_t>(since), static_cast<uint64_t>(limit))); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_all_public_ids_with_limits()->set_resource_type(Convert(resourceType)); + request.mutable_get_all_public_ids_with_limits()->set_since(since); + request.mutable_get_all_public_ids_with_limits()->set_limit(limit); - ReadStringAnswers(target); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_ALL_PUBLIC_IDS_WITH_LIMITS, request); + + target.clear(); + for (int i = 0; i < response.get_all_public_ids_with_limits().ids().size(); i++) + { + target.push_back(response.get_all_public_ids_with_limits().ids(i)); + } } virtual void GetChanges(std::list<ServerIndexChange>& target /*out*/, bool& done /*out*/, int64_t since, - uint32_t maxResults) ORTHANC_OVERRIDE + uint32_t limit) ORTHANC_OVERRIDE { - uint8_t tmpDone = true; - CheckSuccess(that_.backend_.getChanges(transaction_, &tmpDone, since, maxResults)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_changes()->set_since(since); + request.mutable_get_changes()->set_limit(limit); - done = (tmpDone != 0); - - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_CHANGES, request); + + done = response.get_changes().done(); + target.clear(); - for (uint32_t i = 0; i < count; i++) + for (int i = 0; i < response.get_changes().changes().size(); i++) { - target.push_back(ReadAnswerChange(i)); + target.push_back(Convert(response.get_changes().changes(i))); } } @@ -439,18 +500,16 @@ virtual void GetChildrenInternalId(std::list<int64_t>& target, int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getChildrenInternalId(transaction_, id)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_children_internal_id()->set_id(id); - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_CHILDREN_INTERNAL_ID, request); + target.clear(); - for (uint32_t i = 0; i < count; i++) + for (int i = 0; i < response.get_children_internal_id().ids().size(); i++) { - int64_t value; - CheckSuccess(that_.backend_.readAnswerInt64(transaction_, &value, i)); - target.push_back(value); + target.push_back(response.get_children_internal_id().ids(i)); } } @@ -458,71 +517,64 @@ virtual void GetChildrenPublicId(std::list<std::string>& target, int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getChildrenPublicId(transaction_, id)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_children_public_id()->set_id(id); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_CHILDREN_PUBLIC_ID, request); - ReadStringAnswers(target); + target.clear(); + for (int i = 0; i < response.get_children_public_id().ids().size(); i++) + { + target.push_back(response.get_children_public_id().ids(i)); + } } virtual void GetExportedResources(std::list<ExportedResource>& target /*out*/, bool& done /*out*/, int64_t since, - uint32_t maxResults) ORTHANC_OVERRIDE + uint32_t limit) ORTHANC_OVERRIDE { - uint8_t tmpDone = true; - CheckSuccess(that_.backend_.getExportedResources(transaction_, &tmpDone, since, maxResults)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_exported_resources()->set_since(since); + request.mutable_get_exported_resources()->set_limit(limit); - done = (tmpDone != 0); - - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_EXPORTED_RESOURCES, request); + + done = response.get_exported_resources().done(); + target.clear(); - for (uint32_t i = 0; i < count; i++) + for (int i = 0; i < response.get_exported_resources().resources().size(); i++) { - target.push_back(ReadAnswerExportedResource(i)); + target.push_back(Convert(response.get_exported_resources().resources(i))); } } - + virtual void GetLastChange(std::list<ServerIndexChange>& target /*out*/) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getLastChange(transaction_)); - CheckNoEvent(); - - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_LAST_CHANGE); target.clear(); - if (count == 1) + if (response.get_last_change().found()) { - target.push_back(ReadAnswerChange(0)); - } - else if (count > 1) - { - throw OrthancException(ErrorCode_DatabasePlugin); + target.push_back(Convert(response.get_last_change().change())); } } - + virtual void GetLastExportedResource(std::list<ExportedResource>& target /*out*/) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getLastExportedResource(transaction_)); - CheckNoEvent(); - - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_LAST_EXPORTED_RESOURCE); target.clear(); - if (count == 1) + if (response.get_last_exported_resource().found()) { - target.push_back(ReadAnswerExportedResource(0)); - } - else if (count > 1) - { - throw OrthancException(ErrorCode_DatabasePlugin); + target.push_back(Convert(response.get_last_exported_resource().resource())); } } @@ -530,26 +582,25 @@ virtual void GetMainDicomTags(DicomMap& target, int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getMainDicomTags(transaction_, id)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_main_dicom_tags()->set_id(id); - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_MAIN_DICOM_TAGS, request); target.Clear(); - for (uint32_t i = 0; i < count; i++) + + for (int i = 0; i < response.get_main_dicom_tags().tags().size(); i++) { - uint16_t group, element; - const char* value = NULL; - CheckSuccess(that_.backend_.readAnswerDicomTag(transaction_, &group, &element, &value, i)); - - if (value == NULL) + const DatabasePluginMessages::GetMainDicomTags_Response_Tag& tag = response.get_main_dicom_tags().tags(i); + if (tag.group() > 0xffffu || + tag.element() > 0xffffu) { - throw OrthancException(ErrorCode_DatabasePlugin); + throw OrthancException(ErrorCode_ParameterOutOfRange); } else { - target.SetValue(group, element, std::string(value), false); + target.SetValue(tag.group(), tag.element(), tag.value(), false); } } } @@ -557,115 +608,121 @@ virtual std::string GetPublicId(int64_t resourceId) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getPublicId(transaction_, resourceId)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_public_id()->set_id(resourceId); - std::string s; - if (ReadSingleStringAnswer(s)) - { - return s; - } - else - { - throw OrthancException(ErrorCode_InexistentItem); - } + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_PUBLIC_ID, request); + return response.get_public_id().id(); } virtual uint64_t GetResourcesCount(ResourceType resourceType) ORTHANC_OVERRIDE { - uint64_t value; - CheckSuccess(that_.backend_.getResourcesCount(transaction_, &value, Plugins::Convert(resourceType))); - CheckNoEvent(); - return value; + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_resources_count()->set_type(Convert(resourceType)); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_RESOURCES_COUNT, request); + return response.get_resources_count().count(); } virtual ResourceType GetResourceType(int64_t resourceId) ORTHANC_OVERRIDE { - OrthancPluginResourceType type; - CheckSuccess(that_.backend_.getResourceType(transaction_, &type, resourceId)); - CheckNoEvent(); - return Plugins::Convert(type); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_resource_type()->set_id(resourceId); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_RESOURCE_TYPE, request); + return Convert(response.get_resource_type().type()); } virtual uint64_t GetTotalCompressedSize() ORTHANC_OVERRIDE { - uint64_t s; - CheckSuccess(that_.backend_.getTotalCompressedSize(transaction_, &s)); - CheckNoEvent(); - return s; + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_TOTAL_COMPRESSED_SIZE); + return response.get_total_compressed_size().size(); } virtual uint64_t GetTotalUncompressedSize() ORTHANC_OVERRIDE { - uint64_t s; - CheckSuccess(that_.backend_.getTotalUncompressedSize(transaction_, &s)); - CheckNoEvent(); - return s; - } - - - virtual bool IsExistingResource(int64_t internalId) ORTHANC_OVERRIDE - { - uint8_t b; - CheckSuccess(that_.backend_.isExistingResource(transaction_, &b, internalId)); - CheckNoEvent(); - return (b != 0); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_TOTAL_UNCOMPRESSED_SIZE); + return response.get_total_uncompressed_size().size(); } virtual bool IsProtectedPatient(int64_t internalId) ORTHANC_OVERRIDE { - uint8_t b; - CheckSuccess(that_.backend_.isProtectedPatient(transaction_, &b, internalId)); - CheckNoEvent(); - return (b != 0); + DatabasePluginMessages::TransactionRequest request; + request.mutable_is_protected_patient()->set_patient_id(internalId); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_IS_PROTECTED_PATIENT, request); + return response.is_protected_patient().protected_patient(); } virtual void ListAvailableAttachments(std::set<FileContentType>& target, int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.listAvailableAttachments(transaction_, id)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_list_available_attachments()->set_id(id); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LIST_AVAILABLE_ATTACHMENTS, request); - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - target.clear(); - for (uint32_t i = 0; i < count; i++) + for (int i = 0; i < response.list_available_attachments().attachments().size(); i++) { - int32_t value; - CheckSuccess(that_.backend_.readAnswerInt32(transaction_, &value, i)); - target.insert(static_cast<FileContentType>(value)); + FileContentType attachment = static_cast<FileContentType>(response.list_available_attachments().attachments(i)); + + if (target.find(attachment) == target.end()) + { + target.insert(attachment); + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } } } - virtual void LogChange(int64_t internalId, - const ServerIndexChange& change) ORTHANC_OVERRIDE + virtual void LogChange(ChangeType changeType, + ResourceType resourceType, + int64_t internalId, + const std::string& /* publicId - unused */, + const std::string& date) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.logChange(transaction_, static_cast<int32_t>(change.GetChangeType()), - internalId, Plugins::Convert(change.GetResourceType()), - change.GetDate().c_str())); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_log_change()->set_change_type(changeType); + request.mutable_log_change()->set_resource_type(Convert(resourceType)); + request.mutable_log_change()->set_resource_id(internalId); + request.mutable_log_change()->set_date(date); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_LOG_CHANGE, request); } virtual void LogExportedResource(const ExportedResource& resource) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.logExportedResource(transaction_, Plugins::Convert(resource.GetResourceType()), - resource.GetPublicId().c_str(), - resource.GetModality().c_str(), - resource.GetDate().c_str(), - resource.GetPatientId().c_str(), - resource.GetStudyInstanceUid().c_str(), - resource.GetSeriesInstanceUid().c_str(), - resource.GetSopInstanceUid().c_str())); - CheckNoEvent(); + // TODO: "seq" is ignored, could be simplified in "ExportedResource" + + DatabasePluginMessages::TransactionRequest request; + request.mutable_log_exported_resource()->set_resource_type(Convert(resource.GetResourceType())); + request.mutable_log_exported_resource()->set_public_id(resource.GetPublicId()); + request.mutable_log_exported_resource()->set_modality(resource.GetModality()); + request.mutable_log_exported_resource()->set_date(resource.GetDate()); + request.mutable_log_exported_resource()->set_patient_id(resource.GetPatientId()); + request.mutable_log_exported_resource()->set_study_instance_uid(resource.GetStudyInstanceUid()); + request.mutable_log_exported_resource()->set_series_instance_uid(resource.GetSeriesInstanceUid()); + request.mutable_log_exported_resource()->set_sop_instance_uid(resource.GetSopInstanceUid()); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_LOG_EXPORTED_RESOURCE, request); } @@ -674,26 +731,22 @@ int64_t id, FileContentType contentType) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.lookupAttachment(transaction_, &revision, id, static_cast<int32_t>(contentType))); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_attachment()->set_id(id); + request.mutable_lookup_attachment()->set_content_type(contentType); - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_ATTACHMENT, request); - if (count == 0) + if (response.lookup_attachment().found()) { - return false; - } - else if (count == 1) - { - OrthancPluginAttachment2 tmp; - CheckSuccess(that_.backend_.readAnswerAttachment2(transaction_, &tmp, 0)); - attachment = Convert(tmp); + attachment = Convert(response.lookup_attachment().attachment()); + revision = response.lookup_attachment().revision(); return true; } else { - throw OrthancException(ErrorCode_DatabasePlugin); + return false; } } @@ -702,32 +755,101 @@ GlobalProperty property, bool shared) ORTHANC_OVERRIDE { - const char* id = (shared ? "" : that_.serverIdentifier_.c_str()); - - CheckSuccess(that_.backend_.lookupGlobalProperty(transaction_, id, static_cast<int32_t>(property))); - CheckNoEvent(); - return ReadSingleStringAnswer(target); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_global_property()->set_server_id(shared ? "" : database_.GetServerIdentifier()); + request.mutable_lookup_global_property()->set_property(property); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_GLOBAL_PROPERTY, request); + + if (response.lookup_global_property().found()) + { + target = response.lookup_global_property().value(); + return true; + } + else + { + return false; + } } - + + virtual int64_t IncrementGlobalProperty(GlobalProperty property, + int64_t increment, + bool shared) ORTHANC_OVERRIDE + { + DatabasePluginMessages::TransactionRequest request; + request.mutable_increment_global_property()->set_server_id(shared ? "" : database_.GetServerIdentifier()); + request.mutable_increment_global_property()->set_property(property); + request.mutable_increment_global_property()->set_increment(increment); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_INCREMENT_GLOBAL_PROPERTY, request); + + 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, MetadataType type) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.lookupMetadata(transaction_, &revision, id, static_cast<int32_t>(type))); - CheckNoEvent(); - return ReadSingleStringAnswer(target); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_metadata()->set_id(id); + request.mutable_lookup_metadata()->set_metadata_type(type); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_METADATA, request); + + if (response.lookup_metadata().found()) + { + target = response.lookup_metadata().value(); + revision = response.lookup_metadata().revision(); + return true; + } + else + { + return false; + } } virtual bool LookupParent(int64_t& parentId, int64_t resourceId) ORTHANC_OVERRIDE { - uint8_t existing; - CheckSuccess(that_.backend_.lookupParent(transaction_, &existing, &parentId, resourceId)); - CheckNoEvent(); - return (existing != 0); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_parent()->set_id(resourceId); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_PARENT, request); + + if (response.lookup_parent().found()) + { + parentId = response.lookup_parent().parent(); + return true; + } + else + { + return false; + } } @@ -735,39 +857,60 @@ ResourceType& type, const std::string& publicId) ORTHANC_OVERRIDE { - uint8_t existing; - OrthancPluginResourceType t; - CheckSuccess(that_.backend_.lookupResource(transaction_, &existing, &id, &t, publicId.c_str())); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_resource()->set_public_id(publicId); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_RESOURCE, request); - if (existing == 0) + if (response.lookup_resource().found()) { - return false; + id = response.lookup_resource().internal_id(); + type = Convert(response.lookup_resource().type()); + return true; } else { - type = Plugins::Convert(t); - return true; + return false; } } virtual bool SelectPatientToRecycle(int64_t& internalId) ORTHANC_OVERRIDE { - uint8_t available; - CheckSuccess(that_.backend_.selectPatientToRecycle(transaction_, &available, &internalId)); - CheckNoEvent(); - return (available != 0); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_SELECT_PATIENT_TO_RECYCLE); + + if (response.select_patient_to_recycle().found()) + { + internalId = response.select_patient_to_recycle().patient_id(); + return true; + } + else + { + return false; + } } virtual bool SelectPatientToRecycle(int64_t& internalId, int64_t patientIdToAvoid) ORTHANC_OVERRIDE { - uint8_t available; - CheckSuccess(that_.backend_.selectPatientToRecycle2(transaction_, &available, &internalId, patientIdToAvoid)); - CheckNoEvent(); - return (available != 0); + DatabasePluginMessages::TransactionRequest request; + request.mutable_select_patient_to_recycle_with_avoid()->set_patient_id_to_avoid(patientIdToAvoid); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_SELECT_PATIENT_TO_RECYCLE_WITH_AVOID, request); + + if (response.select_patient_to_recycle_with_avoid().found()) + { + internalId = response.select_patient_to_recycle_with_avoid().patient_id(); + return true; + } + else + { + return false; + } } @@ -775,17 +918,21 @@ bool shared, const std::string& value) ORTHANC_OVERRIDE { - const char* id = (shared ? "" : that_.serverIdentifier_.c_str()); - - CheckSuccess(that_.backend_.setGlobalProperty(transaction_, id, static_cast<int32_t>(property), value.c_str())); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_set_global_property()->set_server_id(shared ? "" : database_.GetServerIdentifier()); + request.mutable_set_global_property()->set_property(property); + request.mutable_set_global_property()->set_value(value); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_SET_GLOBAL_PROPERTY, request); } virtual void ClearMainDicomTags(int64_t id) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.clearMainDicomTags(transaction_, id)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_clear_main_dicom_tags()->set_id(id); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_CLEAR_MAIN_DICOM_TAGS, request); } @@ -794,82 +941,147 @@ const std::string& value, int64_t revision) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.setMetadata(transaction_, id, static_cast<int32_t>(type), value.c_str(), revision)); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_set_metadata()->set_id(id); + request.mutable_set_metadata()->set_metadata_type(type); + request.mutable_set_metadata()->set_value(value); + request.mutable_set_metadata()->set_revision(revision); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_SET_METADATA, request); } virtual void SetProtectedPatient(int64_t internalId, bool isProtected) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.setProtectedPatient(transaction_, internalId, (isProtected ? 1 : 0))); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_set_protected_patient()->set_patient_id(internalId); + request.mutable_set_protected_patient()->set_protected_patient(isProtected); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_SET_PROTECTED_PATIENT, request); } virtual bool IsDiskSizeAbove(uint64_t threshold) ORTHANC_OVERRIDE { - uint8_t tmp; - CheckSuccess(that_.backend_.isDiskSizeAbove(transaction_, &tmp, threshold)); - CheckNoEvent(); - return (tmp != 0); + DatabasePluginMessages::TransactionRequest request; + request.mutable_is_disk_size_above()->set_threshold(threshold); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_IS_DISK_SIZE_ABOVE, request); + + return response.is_disk_size_above().result(); } virtual void ApplyLookupResources(std::list<std::string>& resourcesId, std::list<std::string>* instancesId, // Can be NULL if not needed - const std::vector<DatabaseConstraint>& lookup, + const DatabaseConstraints& lookup, ResourceType queryLevel, - size_t limit) ORTHANC_OVERRIDE + const std::set<std::string>& labels, + LabelsConstraint labelsConstraint, + uint32_t limit) ORTHANC_OVERRIDE { - std::vector<OrthancPluginDatabaseConstraint> constraints; - std::vector< std::vector<const char*> > constraintsValues; - - constraints.resize(lookup.size()); - constraintsValues.resize(lookup.size()); - - for (size_t i = 0; i < lookup.size(); i++) + if (!database_.GetDatabaseCapabilities().HasLabelsSupport() && + !labels.empty()) { - lookup[i].EncodeForPlugins(constraints[i], constraintsValues[i]); + throw OrthancException(ErrorCode_InternalError); } - CheckSuccess(that_.backend_.lookupResources(transaction_, lookup.size(), - (lookup.empty() ? NULL : &constraints[0]), - Plugins::Convert(queryLevel), - limit, (instancesId == NULL ? 0 : 1))); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_resources()->set_query_level(Convert(queryLevel)); + request.mutable_lookup_resources()->set_limit(limit); + request.mutable_lookup_resources()->set_retrieve_instances_ids(instancesId != NULL); + + request.mutable_lookup_resources()->mutable_lookup()->Reserve(lookup.GetSize()); + + for (size_t i = 0; i < lookup.GetSize(); i++) + { + const DatabaseConstraint& source = lookup.GetConstraint(i); + + DatabasePluginMessages::DatabaseConstraint* target = request.mutable_lookup_resources()->add_lookup(); + target->set_level(Convert(source.GetLevel())); + target->set_tag_group(source.GetTag().GetGroup()); + target->set_tag_element(source.GetTag().GetElement()); + target->set_is_identifier_tag(source.IsIdentifier()); + target->set_is_case_sensitive(source.IsCaseSensitive()); + target->set_is_mandatory(source.IsMandatory()); + + target->mutable_values()->Reserve(source.GetValuesCount()); + for (size_t j = 0; j < source.GetValuesCount(); j++) + { + target->add_values(source.GetValue(j)); + } - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); + switch (source.GetConstraintType()) + { + case ConstraintType_Equal: + target->set_type(DatabasePluginMessages::CONSTRAINT_EQUAL); + break; + + case ConstraintType_SmallerOrEqual: + target->set_type(DatabasePluginMessages::CONSTRAINT_SMALLER_OR_EQUAL); + break; + + case ConstraintType_GreaterOrEqual: + target->set_type(DatabasePluginMessages::CONSTRAINT_GREATER_OR_EQUAL); + break; + + case ConstraintType_Wildcard: + target->set_type(DatabasePluginMessages::CONSTRAINT_WILDCARD); + break; + + case ConstraintType_List: + target->set_type(DatabasePluginMessages::CONSTRAINT_LIST); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + for (std::set<std::string>::const_iterator it = labels.begin(); it != labels.end(); ++it) + { + request.mutable_lookup_resources()->add_labels(*it); + } + + switch (labelsConstraint) + { + case LabelsConstraint_All: + request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_ALL); + break; + + case LabelsConstraint_Any: + request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_ANY); + break; + + case LabelsConstraint_None: + request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_NONE); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } - resourcesId.clear(); + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_RESOURCES, request); + for (int i = 0; i < response.lookup_resources().resources_ids().size(); i++) + { + resourcesId.push_back(response.lookup_resources().resources_ids(i)); + } + if (instancesId != NULL) { - instancesId->clear(); - } - - for (uint32_t i = 0; i < count; i++) - { - OrthancPluginMatchingResource resource; - CheckSuccess(that_.backend_.readAnswerMatchingResource(transaction_, &resource, i)); - - if (resource.resourceId == NULL) + if (response.lookup_resources().resources_ids().size() != response.lookup_resources().instances_ids().size()) { throw OrthancException(ErrorCode_DatabasePlugin); } - - resourcesId.push_back(resource.resourceId); - - if (instancesId != NULL) + else { - if (resource.someInstanceId == NULL) + for (int i = 0; i < response.lookup_resources().instances_ids().size(); i++) { - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - instancesId->push_back(resource.someInstanceId); + instancesId->push_back(response.lookup_resources().instances_ids(i)); } } } @@ -883,83 +1095,61 @@ const std::string& series, const std::string& instance) ORTHANC_OVERRIDE { - OrthancPluginCreateInstanceResult output; - memset(&output, 0, sizeof(output)); - - CheckSuccess(that_.backend_.createInstance(transaction_, &output, patient.c_str(), - study.c_str(), series.c_str(), instance.c_str())); - CheckNoEvent(); - - instanceId = output.instanceId; + // TODO: "CreateInstanceResult" => constructor and getters - if (output.isNewInstance) + DatabasePluginMessages::TransactionRequest request; + request.mutable_create_instance()->set_patient(patient); + request.mutable_create_instance()->set_study(study); + request.mutable_create_instance()->set_series(series); + request.mutable_create_instance()->set_instance(instance); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_CREATE_INSTANCE, request); + + instanceId = response.create_instance().instance_id(); + + if (response.create_instance().is_new_instance()) { - result.isNewPatient_ = output.isNewPatient; - result.isNewStudy_ = output.isNewStudy; - result.isNewSeries_ = output.isNewSeries; - result.patientId_ = output.patientId; - result.studyId_ = output.studyId; - result.seriesId_ = output.seriesId; + result.isNewPatient_ = response.create_instance().is_new_patient(); + result.isNewStudy_ = response.create_instance().is_new_study(); + result.isNewSeries_ = response.create_instance().is_new_series(); + result.patientId_ = response.create_instance().patient_id(); + result.studyId_ = response.create_instance().study_id(); + result.seriesId_ = response.create_instance().series_id(); return true; } else { return false; } - } virtual void SetResourcesContent(const ResourcesContent& content) ORTHANC_OVERRIDE { - std::vector<OrthancPluginResourcesContentTags> identifierTags; - std::vector<OrthancPluginResourcesContentTags> mainDicomTags; - std::vector<OrthancPluginResourcesContentMetadata> metadata; + DatabasePluginMessages::TransactionRequest request; - identifierTags.reserve(content.GetListTags().size()); - mainDicomTags.reserve(content.GetListTags().size()); - metadata.reserve(content.GetListMetadata().size()); - - for (ResourcesContent::ListTags::const_iterator - it = content.GetListTags().begin(); it != content.GetListTags().end(); ++it) + request.mutable_set_resources_content()->mutable_tags()->Reserve(content.GetListTags().size()); + for (ResourcesContent::ListTags::const_iterator it = content.GetListTags().begin(); it != content.GetListTags().end(); ++it) { - OrthancPluginResourcesContentTags tmp; - tmp.resource = it->resourceId_; - tmp.group = it->tag_.GetGroup(); - tmp.element = it->tag_.GetElement(); - tmp.value = it->value_.c_str(); - - if (it->isIdentifier_) - { - identifierTags.push_back(tmp); - } - else - { - mainDicomTags.push_back(tmp); - } + DatabasePluginMessages::SetResourcesContent_Request_Tag* tag = request.mutable_set_resources_content()->add_tags(); + tag->set_resource_id(it->GetResourceId()); + tag->set_is_identifier(it->IsIdentifier()); + tag->set_group(it->GetTag().GetGroup()); + tag->set_element(it->GetTag().GetElement()); + tag->set_value(it->GetValue()); + } + + request.mutable_set_resources_content()->mutable_metadata()->Reserve(content.GetListMetadata().size()); + for (ResourcesContent::ListMetadata::const_iterator it = content.GetListMetadata().begin(); it != content.GetListMetadata().end(); ++it) + { + DatabasePluginMessages::SetResourcesContent_Request_Metadata* metadata = request.mutable_set_resources_content()->add_metadata(); + metadata->set_resource_id(it->GetResourceId()); + metadata->set_metadata(it->GetType()); + metadata->set_value(it->GetValue()); } - for (ResourcesContent::ListMetadata::const_iterator - it = content.GetListMetadata().begin(); it != content.GetListMetadata().end(); ++it) - { - OrthancPluginResourcesContentMetadata tmp; - tmp.resource = it->resourceId_; - tmp.metadata = it->metadata_; - tmp.value = it->value_.c_str(); - metadata.push_back(tmp); - } - - assert(identifierTags.size() + mainDicomTags.size() == content.GetListTags().size() && - metadata.size() == content.GetListMetadata().size()); - - CheckSuccess(that_.backend_.setResourcesContent(transaction_, - identifierTags.size(), - (identifierTags.empty() ? NULL : &identifierTags[0]), - mainDicomTags.size(), - (mainDicomTags.empty() ? NULL : &mainDicomTags[0]), - metadata.size(), - (metadata.empty() ? NULL : &metadata[0]))); - CheckNoEvent(); + ExecuteTransaction(DatabasePluginMessages::OPERATION_SET_RESOURCES_CONTENT, request); } @@ -967,18 +1157,25 @@ int64_t resourceId, MetadataType metadata) ORTHANC_OVERRIDE { - CheckSuccess(that_.backend_.getChildrenMetadata(transaction_, resourceId, static_cast<int32_t>(metadata))); - CheckNoEvent(); - ReadStringAnswers(target); + DatabasePluginMessages::TransactionRequest request; + request.mutable_get_children_metadata()->set_id(resourceId); + request.mutable_get_children_metadata()->set_metadata(metadata); + + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_CHILDREN_METADATA, request); + + for (int i = 0; i < response.get_children_metadata().values().size(); i++) + { + target.push_back(response.get_children_metadata().values(i)); + } } virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE { - int64_t tmp; - CheckSuccess(that_.backend_.getLastChangeIndex(transaction_, &tmp)); - CheckNoEvent(); - return tmp; + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_GET_LAST_CHANGE_INDEX); + return response.get_last_change_index().result(); } @@ -987,57 +1184,41 @@ std::string& parentPublicId, const std::string& publicId) ORTHANC_OVERRIDE { - uint8_t isExisting; - OrthancPluginResourceType tmpType; - CheckSuccess(that_.backend_.lookupResourceAndParent(transaction_, &isExisting, &id, &tmpType, publicId.c_str())); - CheckNoEvent(); + DatabasePluginMessages::TransactionRequest request; + request.mutable_lookup_resource_and_parent()->set_public_id(publicId); - if (isExisting) + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_RESOURCE_AND_PARENT, request); + + if (response.lookup_resource_and_parent().found()) { - type = Plugins::Convert(tmpType); - - uint32_t count; - CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); - - if (count > 1) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } + id = response.lookup_resource_and_parent().id(); + type = Convert(response.lookup_resource_and_parent().type()); switch (type) { case ResourceType_Patient: - // A patient has no parent - if (count == 1) + if (!response.lookup_resource_and_parent().parent_public_id().empty()) { throw OrthancException(ErrorCode_DatabasePlugin); } break; - + case ResourceType_Study: case ResourceType_Series: case ResourceType_Instance: - if (count == 0) + if (response.lookup_resource_and_parent().parent_public_id().empty()) { throw OrthancException(ErrorCode_DatabasePlugin); } else { - const char* value = NULL; - CheckSuccess(that_.backend_.readAnswerString(transaction_, &value, 0)); - if (value == NULL) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - else - { - parentPublicId.assign(value); - } + parentPublicId = response.lookup_resource_and_parent().parent_public_id(); } break; - + default: - throw OrthancException(ErrorCode_DatabasePlugin); + throw OrthancException(ErrorCode_ParameterOutOfRange); } return true; @@ -1047,210 +1228,269 @@ return false; } } - }; + + + virtual void AddLabel(int64_t resource, + const std::string& label) ORTHANC_OVERRIDE + { + if (database_.GetDatabaseCapabilities().HasLabelsSupport()) + { + DatabasePluginMessages::TransactionRequest request; + request.mutable_add_label()->set_id(resource); + request.mutable_add_label()->set_label(label); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_ADD_LABEL, request); + } + else + { + // This method shouldn't have been called + throw OrthancException(ErrorCode_InternalError); + } + } + - - void OrthancPluginDatabaseV4::CheckSuccess(OrthancPluginErrorCode code) const - { - if (code != OrthancPluginErrorCode_Success) + virtual void RemoveLabel(int64_t resource, + const std::string& label) ORTHANC_OVERRIDE { - errorDictionary_.LogError(code, true); - throw OrthancException(static_cast<ErrorCode>(code)); + if (database_.GetDatabaseCapabilities().HasLabelsSupport()) + { + DatabasePluginMessages::TransactionRequest request; + request.mutable_remove_label()->set_id(resource); + request.mutable_remove_label()->set_label(label); + + ExecuteTransaction(DatabasePluginMessages::OPERATION_REMOVE_LABEL, request); + } + else + { + // This method shouldn't have been called + throw OrthancException(ErrorCode_InternalError); + } } - } + + + virtual void ListLabels(std::set<std::string>& target, + int64_t resource) ORTHANC_OVERRIDE + { + ListLabelsInternal(target, true, resource); + } + + + virtual void ListAllLabels(std::set<std::string>& target) ORTHANC_OVERRIDE + { + ListLabelsInternal(target, false, -1); + } + }; OrthancPluginDatabaseV4::OrthancPluginDatabaseV4(SharedLibrary& library, PluginsErrorDictionary& errorDictionary, - const OrthancPluginDatabaseBackendV4* backend, - size_t backendSize, - void* database, + const _OrthancPluginRegisterDatabaseBackendV4& database, const std::string& serverIdentifier) : library_(library), errorDictionary_(errorDictionary), - database_(database), - serverIdentifier_(serverIdentifier) + definition_(database), + serverIdentifier_(serverIdentifier), + open_(false), + databaseVersion_(0) { CLOG(INFO, PLUGINS) << "Identifier of this Orthanc server for the global properties " << "of the custom database: \"" << serverIdentifier << "\""; - - if (backendSize >= sizeof(backend_)) + + if (definition_.backend == NULL || + definition_.operations == NULL || + definition_.finalize == NULL) { - memcpy(&backend_, backend, sizeof(backend_)); - } - else - { - // Not all the primitives are implemented by the plugin - memset(&backend_, 0, sizeof(backend_)); - memcpy(&backend_, backend, backendSize); + throw OrthancException(ErrorCode_NullPointer); } - - // Sanity checks - CHECK_FUNCTION_EXISTS(backend_, readAnswersCount); - CHECK_FUNCTION_EXISTS(backend_, readAnswerAttachment2); - CHECK_FUNCTION_EXISTS(backend_, readAnswerChange); - CHECK_FUNCTION_EXISTS(backend_, readAnswerDicomTag); - CHECK_FUNCTION_EXISTS(backend_, readAnswerExportedResource); - CHECK_FUNCTION_EXISTS(backend_, readAnswerInt32); - CHECK_FUNCTION_EXISTS(backend_, readAnswerInt64); - CHECK_FUNCTION_EXISTS(backend_, readAnswerMatchingResource); - CHECK_FUNCTION_EXISTS(backend_, readAnswerMetadata); - CHECK_FUNCTION_EXISTS(backend_, readAnswerString); - - CHECK_FUNCTION_EXISTS(backend_, readEventsCount); - CHECK_FUNCTION_EXISTS(backend_, readEvent2); - - CHECK_FUNCTION_EXISTS(backend_, open); - CHECK_FUNCTION_EXISTS(backend_, close); - CHECK_FUNCTION_EXISTS(backend_, destructDatabase); - CHECK_FUNCTION_EXISTS(backend_, getDatabaseVersion); - CHECK_FUNCTION_EXISTS(backend_, upgradeDatabase); - CHECK_FUNCTION_EXISTS(backend_, startTransaction); - CHECK_FUNCTION_EXISTS(backend_, destructTransaction); - CHECK_FUNCTION_EXISTS(backend_, hasRevisionsSupport); - CHECK_FUNCTION_EXISTS(backend_, hasAttachmentCustomDataSupport); // new in v4 - - CHECK_FUNCTION_EXISTS(backend_, rollback); - CHECK_FUNCTION_EXISTS(backend_, commit); - - CHECK_FUNCTION_EXISTS(backend_, addAttachment2); - CHECK_FUNCTION_EXISTS(backend_, clearChanges); - CHECK_FUNCTION_EXISTS(backend_, clearExportedResources); - CHECK_FUNCTION_EXISTS(backend_, clearMainDicomTags); - CHECK_FUNCTION_EXISTS(backend_, createInstance); - CHECK_FUNCTION_EXISTS(backend_, deleteAttachment); - CHECK_FUNCTION_EXISTS(backend_, deleteMetadata); - CHECK_FUNCTION_EXISTS(backend_, deleteResource); - CHECK_FUNCTION_EXISTS(backend_, getAllMetadata); - CHECK_FUNCTION_EXISTS(backend_, getAllPublicIds); - CHECK_FUNCTION_EXISTS(backend_, getAllPublicIdsWithLimit); - CHECK_FUNCTION_EXISTS(backend_, getChanges); - CHECK_FUNCTION_EXISTS(backend_, getChildrenInternalId); - CHECK_FUNCTION_EXISTS(backend_, getChildrenMetadata); - CHECK_FUNCTION_EXISTS(backend_, getChildrenPublicId); - CHECK_FUNCTION_EXISTS(backend_, getExportedResources); - CHECK_FUNCTION_EXISTS(backend_, getLastChange); - CHECK_FUNCTION_EXISTS(backend_, getLastChangeIndex); - CHECK_FUNCTION_EXISTS(backend_, getLastExportedResource); - CHECK_FUNCTION_EXISTS(backend_, getMainDicomTags); - CHECK_FUNCTION_EXISTS(backend_, getPublicId); - CHECK_FUNCTION_EXISTS(backend_, getResourceType); - CHECK_FUNCTION_EXISTS(backend_, getResourcesCount); - CHECK_FUNCTION_EXISTS(backend_, getTotalCompressedSize); - CHECK_FUNCTION_EXISTS(backend_, getTotalUncompressedSize); - CHECK_FUNCTION_EXISTS(backend_, isDiskSizeAbove); - CHECK_FUNCTION_EXISTS(backend_, isExistingResource); - CHECK_FUNCTION_EXISTS(backend_, isProtectedPatient); - CHECK_FUNCTION_EXISTS(backend_, listAvailableAttachments); - CHECK_FUNCTION_EXISTS(backend_, logChange); - CHECK_FUNCTION_EXISTS(backend_, logExportedResource); - CHECK_FUNCTION_EXISTS(backend_, lookupAttachment); - CHECK_FUNCTION_EXISTS(backend_, lookupGlobalProperty); - CHECK_FUNCTION_EXISTS(backend_, lookupMetadata); - CHECK_FUNCTION_EXISTS(backend_, lookupParent); - CHECK_FUNCTION_EXISTS(backend_, lookupResource); - CHECK_FUNCTION_EXISTS(backend_, lookupResourceAndParent); - CHECK_FUNCTION_EXISTS(backend_, lookupResources); - CHECK_FUNCTION_EXISTS(backend_, selectPatientToRecycle); - CHECK_FUNCTION_EXISTS(backend_, selectPatientToRecycle2); - CHECK_FUNCTION_EXISTS(backend_, setGlobalProperty); - CHECK_FUNCTION_EXISTS(backend_, setMetadata); - CHECK_FUNCTION_EXISTS(backend_, setProtectedPatient); - CHECK_FUNCTION_EXISTS(backend_, setResourcesContent); } OrthancPluginDatabaseV4::~OrthancPluginDatabaseV4() { - if (database_ != NULL) + definition_.finalize(definition_.backend); + } + + + static void AddIdentifierTags(DatabasePluginMessages::Open::Request& request, + ResourceType level) + { + const DicomTag* tags = NULL; + size_t size; + + ServerToolbox::LoadIdentifiers(tags, size, level); + + if (tags == NULL || + size == 0) { - OrthancPluginErrorCode code = backend_.destructDatabase(database_); - if (code != OrthancPluginErrorCode_Success) - { - // Don't throw exception in destructors - errorDictionary_.LogError(code, true); - } + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + for (size_t i = 0; i < size; i++) + { + DatabasePluginMessages::Open_Request_IdentifierTag* tag = request.add_identifier_tags(); + tag->set_level(Convert(level)); + tag->set_group(tags[i].GetGroup()); + tag->set_element(tags[i].GetElement()); + tag->set_name(FromDcmtkBridge::GetTagName(tags[i], "")); } } void OrthancPluginDatabaseV4::Open() { - CheckSuccess(backend_.open(database_)); + if (open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + { + DatabasePluginMessages::DatabaseRequest request; + AddIdentifierTags(*request.mutable_open(), ResourceType_Patient); + AddIdentifierTags(*request.mutable_open(), ResourceType_Study); + AddIdentifierTags(*request.mutable_open(), ResourceType_Series); + AddIdentifierTags(*request.mutable_open(), ResourceType_Instance); + + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, *this, DatabasePluginMessages::OPERATION_OPEN, request); + } + + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, *this, DatabasePluginMessages::OPERATION_GET_SYSTEM_INFORMATION, request); + + const ::Orthanc::DatabasePluginMessages::GetSystemInformation_Response& systemInfo = response.get_system_information(); + databaseVersion_ = systemInfo.database_version(); + dbCapabilities_.SetFlushToDisk(systemInfo.supports_flush_to_disk()); + dbCapabilities_.SetRevisionsSupport(systemInfo.supports_revisions()); + dbCapabilities_.SetLabelsSupport(systemInfo.supports_labels()); + dbCapabilities_.SetAtomicIncrementGlobalProperty(systemInfo.supports_increment_global_property()); + dbCapabilities_.SetUpdateAndGetStatistics(systemInfo.has_update_and_get_statistics()); + dbCapabilities_.SetMeasureLatency(systemInfo.has_measure_latency()); + } + + open_ = true; } void OrthancPluginDatabaseV4::Close() { - CheckSuccess(backend_.close(database_)); + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, *this, DatabasePluginMessages::OPERATION_CLOSE, request); + } + } + + + + void OrthancPluginDatabaseV4::FlushToDisk() + { + if (!open_ || + !GetDatabaseCapabilities().HasFlushToDisk()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, *this, DatabasePluginMessages::OPERATION_FLUSH_TO_DISK, request); + } } IDatabaseWrapper::ITransaction* OrthancPluginDatabaseV4::StartTransaction(TransactionType type, IDatabaseListener& listener) { - switch (type) + if (!open_) { - case TransactionType_ReadOnly: - return new Transaction(*this, listener, OrthancPluginDatabaseTransactionType_ReadOnly); - - case TransactionType_ReadWrite: - return new Transaction(*this, listener, OrthancPluginDatabaseTransactionType_ReadWrite); - - default: - throw OrthancException(ErrorCode_InternalError); + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return new Transaction(*this, listener, type); } } unsigned int OrthancPluginDatabaseV4::GetDatabaseVersion() { - uint32_t version = 0; - CheckSuccess(backend_.getDatabaseVersion(database_, &version)); - return version; + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return databaseVersion_; + } } void OrthancPluginDatabaseV4::Upgrade(unsigned int targetVersion, IStorageArea& storageArea) { - VoidDatabaseListener listener; - - if (backend_.upgradeDatabase != NULL) + if (!open_) { - Transaction transaction(*this, listener, OrthancPluginDatabaseTransactionType_ReadWrite); + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + VoidDatabaseListener listener; + Transaction transaction(*this, listener, TransactionType_ReadWrite); - OrthancPluginErrorCode code = backend_.upgradeDatabase( - database_, reinterpret_cast<OrthancPluginStorageArea*>(&storageArea), - static_cast<uint32_t>(targetVersion)); + try + { + DatabasePluginMessages::DatabaseRequest request; + request.mutable_upgrade()->set_target_version(targetVersion); + request.mutable_upgrade()->set_storage_area(reinterpret_cast<intptr_t>(&storageArea)); + request.mutable_upgrade()->set_transaction(reinterpret_cast<intptr_t>(transaction.GetTransactionObject())); + + DatabasePluginMessages::DatabaseResponse response; - if (code == OrthancPluginErrorCode_Success) - { + ExecuteDatabase(response, *this, DatabasePluginMessages::OPERATION_UPGRADE, request); transaction.Commit(0); } - else + catch (OrthancException& e) { transaction.Rollback(); - errorDictionary_.LogError(code, true); - throw OrthancException(static_cast<ErrorCode>(code)); + throw; } } } - - bool OrthancPluginDatabaseV4::HasRevisionsSupport() const + + uint64_t OrthancPluginDatabaseV4::MeasureLatency() { - // WARNING: This method requires "Open()" to have been called - uint8_t hasRevisions; - CheckSuccess(backend_.hasRevisionsSupport(database_, &hasRevisions)); - return (hasRevisions != 0); + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + + ExecuteDatabase(response, *this, DatabasePluginMessages::OPERATION_MEASURE_LATENCY, request); + return response.measure_latency().latency_us(); + } } - bool OrthancPluginDatabaseV4::HasAttachmentCustomDataSupport() const + + const IDatabaseWrapper::Capabilities OrthancPluginDatabaseV4::GetDatabaseCapabilities() const { - // WARNING: This method requires "Open()" to have been called - uint8_t hasAttachmentCustomDataSupport; - CheckSuccess(backend_.hasAttachmentCustomDataSupport(database_, &hasAttachmentCustomDataSupport)); - return (hasAttachmentCustomDataSupport != 0); + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return dbCapabilities_; + } } }