Mercurial > hg > orthanc
changeset 5207:e7529e6241d2 db-protobuf
first successful protobuf communication
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 30 Mar 2023 21:31:56 +0200 |
parents | fb3add662286 |
children | 154d37a56500 |
files | OrthancFramework/Resources/CMake/ProtobufConfiguration.cmake OrthancServer/CMakeLists.txt OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.h OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto OrthancServer/Sources/OrthancInitialization.cpp |
diffstat | 7 files changed, 720 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Resources/CMake/ProtobufConfiguration.cmake Thu Mar 30 17:08:13 2023 +0200 +++ b/OrthancFramework/Resources/CMake/ProtobufConfiguration.cmake Thu Mar 30 21:31:56 2023 +0200 @@ -23,7 +23,7 @@ if (ENABLE_PROTOBUF_COMPILER) include(ExternalProject) externalproject_add(ProtobufCompiler - SOURCE_DIR "${CMAKE_SOURCE_DIR}/../OrthancFramework/Resources/ProtocolBuffers" + SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../ProtocolBuffers" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/ProtobufCompiler-build" # this helps triggering build when changing the external project BUILD_ALWAYS 1
--- a/OrthancServer/CMakeLists.txt Thu Mar 30 17:08:13 2023 +0200 +++ b/OrthancServer/CMakeLists.txt Thu Mar 30 21:31:56 2023 +0200 @@ -186,6 +186,7 @@ list(APPEND ORTHANC_SERVER_SOURCES ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPluginDatabase.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPluginDatabaseV3.cpp + ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPluginDatabaseV4.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPlugins.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginsEnumerations.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginsErrorDictionary.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Thu Mar 30 21:31:56 2023 +0200 @@ -0,0 +1,570 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 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 + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../../Sources/PrecompiledHeadersServer.h" +#include "OrthancPluginDatabaseV4.h" + +#if ORTHANC_ENABLE_PLUGINS != 1 +# error The plugin support is disabled +#endif + +#include "../../../OrthancFramework/Sources/Logging.h" +#include "../../../OrthancFramework/Sources/OrthancException.h" +#include "PluginsEnumerations.h" + +#include "OrthancDatabasePlugin.pb.h" + +#include <cassert> + + +namespace Orthanc +{ + class OrthancPluginDatabaseV4::Transaction : public IDatabaseWrapper::ITransaction + { + private: + OrthancPluginDatabaseV4& that_; + IDatabaseListener& listener_; + void* transaction_; + + void CheckSuccess(OrthancPluginErrorCode code) const + { + that_.CheckSuccess(code); + } + + public: + Transaction(OrthancPluginDatabaseV4& that, + IDatabaseListener& listener, + TransactionType type) : + that_(that), + listener_(listener) + { +#if 0 + CheckSuccess(that.database_.startTransaction(that.database_, &transaction_, type)); + if (transaction_ == NULL) + { + throw OrthancException(ErrorCode_DatabasePlugin); + } +#endif + } + + + virtual ~Transaction() + { +#if 0 + OrthancPluginErrorCode code = that_.database_.destructTransaction(transaction_); + if (code != OrthancPluginErrorCode_Success) + { + // Don't throw exception in destructors + that_.errorDictionary_.LogError(code, true); + } +#endif + } + + + virtual void Rollback() ORTHANC_OVERRIDE + { + } + + + virtual void Commit(int64_t fileSizeDelta) ORTHANC_OVERRIDE + { + } + + + virtual void AddAttachment(int64_t id, + const FileInfo& attachment, + int64_t revision) ORTHANC_OVERRIDE + { + } + + + virtual void ClearChanges() ORTHANC_OVERRIDE + { + } + + + virtual void ClearExportedResources() ORTHANC_OVERRIDE + { + } + + + virtual void DeleteAttachment(int64_t id, + FileContentType attachment) ORTHANC_OVERRIDE + { + } + + + virtual void DeleteMetadata(int64_t id, + MetadataType type) ORTHANC_OVERRIDE + { + } + + + virtual void DeleteResource(int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual void GetAllMetadata(std::map<MetadataType, std::string>& target, + int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual void GetAllPublicIds(std::list<std::string>& target, + ResourceType resourceType) ORTHANC_OVERRIDE + { + } + + + virtual void GetAllPublicIds(std::list<std::string>& target, + ResourceType resourceType, + size_t since, + size_t limit) ORTHANC_OVERRIDE + { + } + + + virtual void GetChanges(std::list<ServerIndexChange>& target /*out*/, + bool& done /*out*/, + int64_t since, + uint32_t maxResults) ORTHANC_OVERRIDE + { + } + + + virtual void GetChildrenInternalId(std::list<int64_t>& target, + int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual void GetChildrenPublicId(std::list<std::string>& target, + int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual void GetExportedResources(std::list<ExportedResource>& target /*out*/, + bool& done /*out*/, + int64_t since, + uint32_t maxResults) ORTHANC_OVERRIDE + { + } + + + virtual void GetLastExportedResource(std::list<ExportedResource>& target /*out*/) ORTHANC_OVERRIDE + { + } + + + virtual void GetMainDicomTags(DicomMap& target, + int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual std::string GetPublicId(int64_t resourceId) ORTHANC_OVERRIDE + { + } + + + virtual uint64_t GetResourcesCount(ResourceType resourceType) ORTHANC_OVERRIDE + { + } + + + virtual ResourceType GetResourceType(int64_t resourceId) ORTHANC_OVERRIDE + { + } + + + virtual uint64_t GetTotalCompressedSize() ORTHANC_OVERRIDE + { + } + + + virtual uint64_t GetTotalUncompressedSize() ORTHANC_OVERRIDE + { + } + + + virtual bool IsProtectedPatient(int64_t internalId) ORTHANC_OVERRIDE + { + } + + + virtual void ListAvailableAttachments(std::set<FileContentType>& target, + int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual void LogChange(int64_t internalId, + const ServerIndexChange& change) ORTHANC_OVERRIDE + { + } + + + virtual void LogExportedResource(const ExportedResource& resource) ORTHANC_OVERRIDE + { + } + + + virtual bool LookupAttachment(FileInfo& attachment, + int64_t& revision, + int64_t id, + FileContentType contentType) ORTHANC_OVERRIDE + { + } + + + virtual bool LookupGlobalProperty(std::string& target, + GlobalProperty property, + bool shared) ORTHANC_OVERRIDE + { + } + + + virtual bool LookupMetadata(std::string& target, + int64_t& revision, + int64_t id, + MetadataType type) ORTHANC_OVERRIDE + { + } + + + virtual bool LookupParent(int64_t& parentId, + int64_t resourceId) ORTHANC_OVERRIDE + { + } + + + virtual bool LookupResource(int64_t& id, + ResourceType& type, + const std::string& publicId) ORTHANC_OVERRIDE + { + } + + + virtual bool SelectPatientToRecycle(int64_t& internalId) ORTHANC_OVERRIDE + { + } + + + virtual bool SelectPatientToRecycle(int64_t& internalId, + int64_t patientIdToAvoid) ORTHANC_OVERRIDE + { + } + + + virtual void SetGlobalProperty(GlobalProperty property, + bool shared, + const std::string& value) ORTHANC_OVERRIDE + { + } + + + virtual void ClearMainDicomTags(int64_t id) ORTHANC_OVERRIDE + { + } + + + virtual void SetMetadata(int64_t id, + MetadataType type, + const std::string& value, + int64_t revision) ORTHANC_OVERRIDE + { + } + + + virtual void SetProtectedPatient(int64_t internalId, + bool isProtected) ORTHANC_OVERRIDE + { + } + + + virtual bool IsDiskSizeAbove(uint64_t threshold) ORTHANC_OVERRIDE + { + } + + + virtual void ApplyLookupResources(std::list<std::string>& resourcesId, + std::list<std::string>* instancesId, // Can be NULL if not needed + const std::vector<DatabaseConstraint>& lookup, + ResourceType queryLevel, + size_t limit) ORTHANC_OVERRIDE + { + } + + + virtual bool CreateInstance(CreateInstanceResult& result, /* out */ + int64_t& instanceId, /* out */ + const std::string& patient, + const std::string& study, + const std::string& series, + const std::string& instance) ORTHANC_OVERRIDE + { + } + + + virtual void SetResourcesContent(const ResourcesContent& content) ORTHANC_OVERRIDE + { + } + + + virtual void GetChildrenMetadata(std::list<std::string>& target, + int64_t resourceId, + MetadataType metadata) ORTHANC_OVERRIDE + { + } + + + virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE + { + } + + + virtual bool LookupResourceAndParent(int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId) ORTHANC_OVERRIDE + { + } + }; + + + static void CheckSuccess(PluginsErrorDictionary& errorDictionary, + OrthancPluginErrorCode code) + { + if (code != OrthancPluginErrorCode_Success) + { + errorDictionary.LogError(code, true); + throw OrthancException(static_cast<ErrorCode>(code)); + } + } + + + static void Execute(DatabasePluginMessages::Response& response, + const _OrthancPluginRegisterDatabaseBackendV4& database, + PluginsErrorDictionary& errorDictionary, + const DatabasePluginMessages::Request& request) + { + std::string requestSerialized; + request.SerializeToString(&requestSerialized); + + OrthancPluginMemoryBuffer64 responseSerialized; + CheckSuccess(errorDictionary, database.operations( + &responseSerialized, database.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 _OrthancPluginRegisterDatabaseBackendV4& database, + PluginsErrorDictionary& errorDictionary, + 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, errorDictionary, fullRequest); + + response.CopyFrom(fullResponse.database_response()); + } + + + OrthancPluginDatabaseV4::OrthancPluginDatabaseV4(SharedLibrary& library, + PluginsErrorDictionary& errorDictionary, + const _OrthancPluginRegisterDatabaseBackendV4& database, + const std::string& serverIdentifier) : + library_(library), + errorDictionary_(errorDictionary), + database_(database), + serverIdentifier_(serverIdentifier), + open_(false), + databaseVersion_(0), + hasFlushToDisk_(false), + hasRevisionsSupport_(false) + { + CLOG(INFO, PLUGINS) << "Identifier of this Orthanc server for the global properties " + << "of the custom database: \"" << serverIdentifier << "\""; + + if (database_.backend == NULL || + database_.operations == NULL || + database_.finalize == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + } + + + OrthancPluginDatabaseV4::~OrthancPluginDatabaseV4() + { + database_.finalize(database_.backend); + } + + + void OrthancPluginDatabaseV4::Open() + { + if (open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, database_, errorDictionary_, DatabasePluginMessages::OPERATION_OPEN, request); + } + + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, database_, errorDictionary_, DatabasePluginMessages::OPERATION_GET_SYSTEM_INFORMATION, request); + hasFlushToDisk_ = response.get_system_information().supports_flush_to_disk(); + hasRevisionsSupport_ = response.get_system_information().supports_revisions(); + } + + open_ = true; + } + + + void OrthancPluginDatabaseV4::Close() + { + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, database_, errorDictionary_, DatabasePluginMessages::OPERATION_CLOSE, request); + } + } + + + bool OrthancPluginDatabaseV4::HasFlushToDisk() const + { + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return hasFlushToDisk_; + } + } + + + void OrthancPluginDatabaseV4::FlushToDisk() + { + if (!open_ || + !hasFlushToDisk_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + DatabasePluginMessages::DatabaseRequest request; + DatabasePluginMessages::DatabaseResponse response; + ExecuteDatabase(response, database_, errorDictionary_, DatabasePluginMessages::OPERATION_FLUSH_TO_DISK, request); + } + } + + + IDatabaseWrapper::ITransaction* OrthancPluginDatabaseV4::StartTransaction(TransactionType type, + IDatabaseListener& listener) + { + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + switch (type) + { + case TransactionType_ReadOnly: + + case TransactionType_ReadWrite: + + default: + throw OrthancException(ErrorCode_InternalError); + } + } + + + unsigned int OrthancPluginDatabaseV4::GetDatabaseVersion() + { + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return databaseVersion_; + } + } + + + void OrthancPluginDatabaseV4::Upgrade(unsigned int targetVersion, + IStorageArea& storageArea) + { + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + // TODO + } + } + + + bool OrthancPluginDatabaseV4::HasRevisionsSupport() const + { + if (!open_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + return hasRevisionsSupport_; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.h Thu Mar 30 21:31:56 2023 +0200 @@ -0,0 +1,84 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 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 + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#if ORTHANC_ENABLE_PLUGINS == 1 + +#include "../../../OrthancFramework/Sources/SharedLibrary.h" +#include "../../Sources/Database/IDatabaseWrapper.h" +#include "../Include/orthanc/OrthancCPlugin.h" +#include "PluginsErrorDictionary.h" + +namespace Orthanc +{ + class OrthancPluginDatabaseV4 : public IDatabaseWrapper + { + private: + class Transaction; + + SharedLibrary& library_; + PluginsErrorDictionary& errorDictionary_; + _OrthancPluginRegisterDatabaseBackendV4 database_; + std::string serverIdentifier_; + bool open_; + unsigned int databaseVersion_; + bool hasFlushToDisk_; + bool hasRevisionsSupport_; + + void CheckSuccess(OrthancPluginErrorCode code) const; + + public: + OrthancPluginDatabaseV4(SharedLibrary& library, + PluginsErrorDictionary& errorDictionary, + const _OrthancPluginRegisterDatabaseBackendV4& database, + const std::string& serverIdentifier); + + virtual ~OrthancPluginDatabaseV4(); + + virtual void Open() ORTHANC_OVERRIDE; + + virtual void Close() ORTHANC_OVERRIDE; + + const SharedLibrary& GetSharedLibrary() const + { + return library_; + } + + virtual void FlushToDisk() ORTHANC_OVERRIDE; + + virtual bool HasFlushToDisk() const ORTHANC_OVERRIDE; + + virtual IDatabaseWrapper::ITransaction* StartTransaction(TransactionType type, + IDatabaseListener& listener) + ORTHANC_OVERRIDE; + + virtual unsigned int GetDatabaseVersion() ORTHANC_OVERRIDE; + + virtual void Upgrade(unsigned int targetVersion, + IStorageArea& storageArea) ORTHANC_OVERRIDE; + + virtual bool HasRevisionsSupport() const ORTHANC_OVERRIDE; + }; +} + +#endif
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Mar 30 17:08:13 2023 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Mar 30 21:31:56 2023 +0200 @@ -63,6 +63,7 @@ #include "../../Sources/ServerToolbox.h" #include "OrthancPluginDatabase.h" #include "OrthancPluginDatabaseV3.h" +#include "OrthancPluginDatabaseV4.h" #include "PluginsEnumerations.h" #include "PluginsJob.h" @@ -1544,8 +1545,9 @@ Properties properties_; int argc_; char** argv_; - std::unique_ptr<OrthancPluginDatabase> database_; + std::unique_ptr<OrthancPluginDatabase> database_; std::unique_ptr<OrthancPluginDatabaseV3> databaseV3_; // New in Orthanc 1.9.2 + std::unique_ptr<OrthancPluginDatabaseV4> databaseV4_; // New in Orthanc 1.12.0 PluginsErrorDictionary dictionary_; std::string databaseServerIdentifier_; // New in Orthanc 1.9.2 unsigned int maxDatabaseRetries_; // New in Orthanc 1.9.2 @@ -5487,14 +5489,15 @@ case _OrthancPluginService_RegisterDatabaseBackend: { - LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API"; + LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API (version 1)"; LOG(WARNING) << "The database backend has *no* support for revisions of metadata and attachments"; const _OrthancPluginRegisterDatabaseBackend& p = *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackend*>(parameters); if (pimpl_->database_.get() == NULL && - pimpl_->databaseV3_.get() == NULL) + pimpl_->databaseV3_.get() == NULL && + pimpl_->databaseV4_.get() == NULL) { pimpl_->database_.reset(new OrthancPluginDatabase(plugin, GetErrorDictionary(), *p.backend, NULL, 0, p.payload)); @@ -5511,14 +5514,15 @@ case _OrthancPluginService_RegisterDatabaseBackendV2: { - LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API"; + LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API (version 2)"; LOG(WARNING) << "The database backend has *no* support for revisions of metadata and attachments"; const _OrthancPluginRegisterDatabaseBackendV2& p = *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV2*>(parameters); if (pimpl_->database_.get() == NULL && - pimpl_->databaseV3_.get() == NULL) + pimpl_->databaseV3_.get() == NULL && + pimpl_->databaseV4_.get() == NULL) { pimpl_->database_.reset(new OrthancPluginDatabase(plugin, GetErrorDictionary(), *p.backend, p.extensions, @@ -5536,13 +5540,14 @@ case _OrthancPluginService_RegisterDatabaseBackendV3: { - CLOG(INFO, PLUGINS) << "Plugin has registered a custom database back-end"; + LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API (version 3)"; const _OrthancPluginRegisterDatabaseBackendV3& p = *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV3*>(parameters); if (pimpl_->database_.get() == NULL && - pimpl_->databaseV3_.get() == NULL) + pimpl_->databaseV3_.get() == NULL && + pimpl_->databaseV4_.get() == NULL) { pimpl_->databaseV3_.reset(new OrthancPluginDatabaseV3(plugin, GetErrorDictionary(), p.backend, p.backendSize, p.database, pimpl_->databaseServerIdentifier_)); @@ -5556,6 +5561,28 @@ return true; } + case _OrthancPluginService_RegisterDatabaseBackendV4: + { + CLOG(INFO, PLUGINS) << "Plugin has registered a custom database back-end"; + + const _OrthancPluginRegisterDatabaseBackendV4& p = + *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV4*>(parameters); + + if (pimpl_->database_.get() == NULL && + pimpl_->databaseV3_.get() == NULL && + pimpl_->databaseV4_.get() == NULL) + { + pimpl_->databaseV4_.reset(new OrthancPluginDatabaseV4(plugin, GetErrorDictionary(), p, pimpl_->databaseServerIdentifier_)); + pimpl_->maxDatabaseRetries_ = p.maxDatabaseRetries; + } + else + { + throw OrthancException(ErrorCode_DatabaseBackendAlreadyRegistered); + } + + return true; + } + case _OrthancPluginService_DatabaseAnswer: throw OrthancException(ErrorCode_InternalError); // Implemented before locking (*) @@ -5695,7 +5722,8 @@ { boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); return (pimpl_->database_.get() != NULL || - pimpl_->databaseV3_.get() != NULL); + pimpl_->databaseV3_.get() != NULL || + pimpl_->databaseV4_.get() != NULL); } @@ -5735,6 +5763,10 @@ { return *pimpl_->databaseV3_; } + else if (pimpl_->databaseV4_.get() != NULL) + { + return *pimpl_->databaseV4_; + } else { throw OrthancException(ErrorCode_BadSequenceOfCalls); @@ -5752,6 +5784,10 @@ { return pimpl_->databaseV3_->GetSharedLibrary(); } + else if (pimpl_->databaseV4_.get() != NULL) + { + return pimpl_->databaseV4_->GetSharedLibrary(); + } else { throw OrthancException(ErrorCode_BadSequenceOfCalls);
--- a/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Thu Mar 30 17:08:13 2023 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Thu Mar 30 21:31:56 2023 +0200 @@ -31,6 +31,14 @@ syntax = "proto3"; +/** + * Turn off protobuf reflection to avoid clashes between the Orthanc + * core and the database plugin, otherwise both will try to register + * the same messages in the process-wide descriptor pool, which would + * result in protobuf error "File already exists in database". + **/ +option optimize_for = LITE_RUNTIME; + package Orthanc.DatabasePluginMessages;
--- a/OrthancServer/Sources/OrthancInitialization.cpp Thu Mar 30 17:08:13 2023 +0200 +++ b/OrthancServer/Sources/OrthancInitialization.cpp Thu Mar 30 21:31:56 2023 +0200 @@ -51,6 +51,10 @@ #include <dcmtk/dcmnet/diutil.h> // For DCM_dcmnetLogger +#if ORTHANC_ENABLE_PLUGINS == 1 +# include <google/protobuf/any.h> +#endif + static const char* const STORAGE_DIRECTORY = "StorageDirectory"; static const char* const ORTHANC_STORAGE = "OrthancStorage"; @@ -315,6 +319,10 @@ OrthancConfiguration::WriterLock lock; +#if ORTHANC_ENABLE_PLUGINS == 1 + GOOGLE_PROTOBUF_VERIFY_VERSION; +#endif + InitializeServerEnumerations(); // Read the user-provided configuration @@ -391,6 +399,10 @@ { OrthancConfiguration::WriterLock lock; Orthanc::FinalizeFramework(); + +#if ORTHANC_ENABLE_PLUGINS == 1 + google::protobuf::ShutdownProtobufLibrary(); +#endif }