Mercurial > hg > orthanc-databases
view Framework/Plugins/OrthancCppDatabasePlugin.h @ 161:2ccde9c7311b optimized-routes
added new optimized REST routes. this is a temporary work to try to speed up some routes (used by LRO). This way, we avoid another app to access the Orthanc DB and we skip the plugin SDK update for a very specific route
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Fri, 10 Jul 2020 13:26:47 +0200 |
parents | 063aa53b5917 |
children | 3236894320d6 |
line wrap: on
line source
/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2020 Osimis S.A., Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ /** * NOTE: Until Orthanc 1.4.0, this file was part of the Orthanc source * distribution. This file is now part of "orthanc-databases", in * order to uncouple its evolution from the Orthanc core. **/ #pragma once #if HAS_ORTHANC_EXCEPTION != 1 # error HAS_ORTHANC_EXCEPTION must be set to 1 #endif #if ORTHANC_ENABLE_PLUGINS != 1 # error ORTHANC_ENABLE_PLUGINS must be set to 1 #endif #include "../../Resources/Orthanc/Databases/DatabaseConstraint.h" #include <OrthancException.h> #define ORTHANC_PLUGINS_DATABASE_CATCH \ catch (::Orthanc::OrthancException& e) \ { \ return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); \ } \ catch (::std::runtime_error& e) \ { \ LogError(backend, e); \ return OrthancPluginErrorCode_DatabasePlugin; \ } \ catch (...) \ { \ backend->GetOutput().LogError("Native exception"); \ return OrthancPluginErrorCode_DatabasePlugin; \ } #include <stdexcept> #include <list> #include <string> namespace OrthancPlugins { /** * @ingroup Callbacks **/ class DatabaseBackendOutput : public boost::noncopyable { friend class DatabaseBackendAdapter; private: enum AllowedAnswers { AllowedAnswers_All, AllowedAnswers_None, AllowedAnswers_Attachment, AllowedAnswers_Change, AllowedAnswers_DicomTag, AllowedAnswers_ExportedResource, AllowedAnswers_MatchingResource, AllowedAnswers_String, AllowedAnswers_Metadata }; OrthancPluginContext* context_; OrthancPluginDatabaseContext* database_; AllowedAnswers allowedAnswers_; void SetAllowedAnswers(AllowedAnswers allowed) { allowedAnswers_ = allowed; } public: DatabaseBackendOutput(OrthancPluginContext* context, OrthancPluginDatabaseContext* database) : context_(context), database_(database), allowedAnswers_(AllowedAnswers_All /* for unit tests */) { } OrthancPluginContext* GetContext() { return context_; } void LogError(const std::string& message) { OrthancPluginLogError(context_, message.c_str()); } void LogWarning(const std::string& message) { OrthancPluginLogWarning(context_, message.c_str()); } void LogInfo(const std::string& message) { OrthancPluginLogInfo(context_, message.c_str()); } void SignalDeletedAttachment(const std::string& uuid, int32_t contentType, uint64_t uncompressedSize, const std::string& uncompressedHash, int32_t compressionType, uint64_t compressedSize, const std::string& compressedHash) { OrthancPluginAttachment attachment; attachment.uuid = uuid.c_str(); attachment.contentType = contentType; attachment.uncompressedSize = uncompressedSize; attachment.uncompressedHash = uncompressedHash.c_str(); attachment.compressionType = compressionType; attachment.compressedSize = compressedSize; attachment.compressedHash = compressedHash.c_str(); OrthancPluginDatabaseSignalDeletedAttachment(context_, database_, &attachment); } void SignalDeletedResource(const std::string& publicId, OrthancPluginResourceType resourceType) { OrthancPluginDatabaseSignalDeletedResource(context_, database_, publicId.c_str(), resourceType); } void SignalRemainingAncestor(const std::string& ancestorId, OrthancPluginResourceType ancestorType) { OrthancPluginDatabaseSignalRemainingAncestor(context_, database_, ancestorId.c_str(), ancestorType); } void AnswerAttachment(const std::string& uuid, int32_t contentType, uint64_t uncompressedSize, const std::string& uncompressedHash, int32_t compressionType, uint64_t compressedSize, const std::string& compressedHash) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_Attachment) { throw std::runtime_error("Cannot answer with an attachment in the current state"); } OrthancPluginAttachment attachment; attachment.uuid = uuid.c_str(); attachment.contentType = contentType; attachment.uncompressedSize = uncompressedSize; attachment.uncompressedHash = uncompressedHash.c_str(); attachment.compressionType = compressionType; attachment.compressedSize = compressedSize; attachment.compressedHash = compressedHash.c_str(); OrthancPluginDatabaseAnswerAttachment(context_, database_, &attachment); } void AnswerChange(int64_t seq, int32_t changeType, OrthancPluginResourceType resourceType, const std::string& publicId, const std::string& date) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_Change) { throw std::runtime_error("Cannot answer with a change in the current state"); } OrthancPluginChange change; change.seq = seq; change.changeType = changeType; change.resourceType = resourceType; change.publicId = publicId.c_str(); change.date = date.c_str(); OrthancPluginDatabaseAnswerChange(context_, database_, &change); } void AnswerDicomTag(uint16_t group, uint16_t element, const std::string& value) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_DicomTag) { throw std::runtime_error("Cannot answer with a DICOM tag in the current state"); } OrthancPluginDicomTag tag; tag.group = group; tag.element = element; tag.value = value.c_str(); OrthancPluginDatabaseAnswerDicomTag(context_, database_, &tag); } void AnswerExportedResource(int64_t seq, OrthancPluginResourceType resourceType, const std::string& publicId, const std::string& modality, const std::string& date, const std::string& patientId, const std::string& studyInstanceUid, const std::string& seriesInstanceUid, const std::string& sopInstanceUid) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_ExportedResource) { throw std::runtime_error("Cannot answer with an exported resource in the current state"); } OrthancPluginExportedResource exported; exported.seq = seq; exported.resourceType = resourceType; exported.publicId = publicId.c_str(); exported.modality = modality.c_str(); exported.date = date.c_str(); exported.patientId = patientId.c_str(); exported.studyInstanceUid = studyInstanceUid.c_str(); exported.seriesInstanceUid = seriesInstanceUid.c_str(); exported.sopInstanceUid = sopInstanceUid.c_str(); OrthancPluginDatabaseAnswerExportedResource(context_, database_, &exported); } #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 void AnswerMatchingResource(const std::string& resourceId) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_MatchingResource) { throw std::runtime_error("Cannot answer with an exported resource in the current state"); } OrthancPluginMatchingResource match; match.resourceId = resourceId.c_str(); match.someInstanceId = NULL; OrthancPluginDatabaseAnswerMatchingResource(context_, database_, &match); } #endif #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 void AnswerMatchingResource(const std::string& resourceId, const std::string& someInstanceId) { if (allowedAnswers_ != AllowedAnswers_All && allowedAnswers_ != AllowedAnswers_MatchingResource) { throw std::runtime_error("Cannot answer with an exported resource in the current state"); } OrthancPluginMatchingResource match; match.resourceId = resourceId.c_str(); match.someInstanceId = someInstanceId.c_str(); OrthancPluginDatabaseAnswerMatchingResource(context_, database_, &match); } #endif }; /** * @ingroup Callbacks **/ class IDatabaseBackend : public boost::noncopyable { friend class DatabaseBackendAdapter; private: DatabaseBackendOutput* output_; void Finalize() { if (output_ != NULL) { delete output_; output_ = NULL; } } protected: DatabaseBackendOutput& GetOutput() { return *output_; } public: IDatabaseBackend() : output_(NULL) { } virtual ~IDatabaseBackend() { Finalize(); } // This takes the ownership void RegisterOutput(DatabaseBackendOutput* output) { Finalize(); output_ = output; } virtual void Open() = 0; virtual void Close() = 0; virtual void AddAttachment(int64_t id, const OrthancPluginAttachment& attachment) = 0; virtual void AttachChild(int64_t parent, int64_t child) = 0; virtual void ClearChanges() = 0; virtual void ClearExportedResources() = 0; virtual int64_t CreateResource(const char* publicId, OrthancPluginResourceType type) = 0; virtual void DeleteAttachment(int64_t id, int32_t attachment) = 0; virtual void DeleteMetadata(int64_t id, int32_t metadataType) = 0; virtual void DeleteResource(int64_t id) = 0; virtual void GetAllInternalIds(std::list<int64_t>& target, OrthancPluginResourceType resourceType) = 0; virtual void GetAllPublicIds(std::list<std::string>& target, OrthancPluginResourceType resourceType) = 0; virtual void GetAllPublicIds(std::list<std::string>& target, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit) = 0; /* Use GetOutput().AnswerChange() */ virtual void GetChanges(bool& done /*out*/, int64_t since, uint32_t maxResults) = 0; virtual void GetChildrenInternalId(std::list<int64_t>& target /*out*/, int64_t id) = 0; virtual void GetChildrenPublicId(std::list<std::string>& target /*out*/, int64_t id) = 0; /* Use GetOutput().AnswerExportedResource() */ virtual void GetExportedResources(bool& done /*out*/, int64_t since, uint32_t maxResults) = 0; /* Use GetOutput().AnswerChange() */ virtual void GetLastChange() = 0; /* Use GetOutput().AnswerExportedResource() */ virtual void GetLastExportedResource() = 0; /* Use GetOutput().AnswerDicomTag() */ virtual void GetMainDicomTags(int64_t id) = 0; virtual std::string GetPublicId(int64_t resourceId) = 0; virtual uint64_t GetResourceCount(OrthancPluginResourceType resourceType) = 0; virtual OrthancPluginResourceType GetResourceType(int64_t resourceId) = 0; virtual uint64_t GetTotalCompressedSize() = 0; virtual uint64_t GetTotalUncompressedSize() = 0; virtual bool IsExistingResource(int64_t internalId) = 0; virtual bool IsProtectedPatient(int64_t internalId) = 0; virtual void ListAvailableMetadata(std::list<int32_t>& target /*out*/, int64_t id) = 0; virtual void ListAvailableAttachments(std::list<int32_t>& target /*out*/, int64_t id) = 0; virtual void LogChange(const OrthancPluginChange& change) = 0; virtual void LogExportedResource(const OrthancPluginExportedResource& resource) = 0; /* Use GetOutput().AnswerAttachment() */ virtual bool LookupAttachment(int64_t id, int32_t contentType) = 0; virtual bool LookupGlobalProperty(std::string& target /*out*/, int32_t property) = 0; virtual void LookupIdentifier(std::list<int64_t>& target /*out*/, OrthancPluginResourceType resourceType, uint16_t group, uint16_t element, OrthancPluginIdentifierConstraint constraint, const char* value) = 0; virtual void LookupIdentifierRange(std::list<int64_t>& target /*out*/, OrthancPluginResourceType resourceType, uint16_t group, uint16_t element, const char* start, const char* end) = 0; virtual bool LookupMetadata(std::string& target /*out*/, int64_t id, int32_t metadataType) = 0; virtual bool LookupParent(int64_t& parentId /*out*/, int64_t resourceId) = 0; virtual bool LookupResource(int64_t& id /*out*/, OrthancPluginResourceType& type /*out*/, const char* publicId) = 0; virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/) = 0; virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/, int64_t patientIdToAvoid) = 0; virtual void SetGlobalProperty(int32_t property, const char* value) = 0; virtual void SetMainDicomTag(int64_t id, uint16_t group, uint16_t element, const char* value) = 0; virtual void SetIdentifierTag(int64_t id, uint16_t group, uint16_t element, const char* value) = 0; virtual void SetMetadata(int64_t id, int32_t metadataType, const char* value) = 0; virtual void SetProtectedPatient(int64_t internalId, bool isProtected) = 0; virtual void StartTransaction() = 0; virtual void RollbackTransaction() = 0; virtual void CommitTransaction() = 0; virtual uint32_t GetDatabaseVersion() = 0; /** * Upgrade the database to the specified version of the database * schema. The upgrade script is allowed to make calls to * OrthancPluginReconstructMainDicomTags(). **/ virtual void UpgradeDatabase(uint32_t targetVersion, OrthancPluginStorageArea* storageArea) = 0; virtual void ClearMainDicomTags(int64_t internalId) = 0; virtual bool HasCreateInstance() const { return false; } #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 virtual void LookupResources(const std::vector<Orthanc::DatabaseConstraint>& lookup, OrthancPluginResourceType queryLevel, uint32_t limit, bool requestSomeInstance) = 0; #endif #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 virtual void CreateInstance(OrthancPluginCreateInstanceResult& result, const char* hashPatient, const char* hashStudy, const char* hashSeries, const char* hashInstance) { throw std::runtime_error("Not implemented"); } #endif #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 virtual void SetResourcesContent( uint32_t countIdentifierTags, const OrthancPluginResourcesContentTags* identifierTags, uint32_t countMainDicomTags, const OrthancPluginResourcesContentTags* mainDicomTags, uint32_t countMetadata, const OrthancPluginResourcesContentMetadata* metadata) = 0; #endif virtual void GetChildrenMetadata(std::list<std::string>& target, int64_t resourceId, int32_t metadata) = 0; virtual int64_t GetLastChangeIndex() = 0; virtual void TagMostRecentPatient(int64_t patientId) = 0; #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) // NB: "parentPublicId" must be cleared if the resource has no parent virtual bool LookupResourceAndParent(int64_t& id, OrthancPluginResourceType& type, std::string& parentPublicId, const char* publicId) = 0; # endif #endif #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) virtual void GetAllMetadata(std::map<int32_t, std::string>& result, int64_t id) = 0; # endif #endif }; /** * @brief Bridge between C and C++ database engines. * * Class creating the bridge between the C low-level primitives for * custom database engines, and the high-level IDatabaseBackend C++ * interface. * * @ingroup Callbacks **/ class DatabaseBackendAdapter { private: // This class cannot be instantiated DatabaseBackendAdapter() { } static void LogError(IDatabaseBackend* backend, const std::runtime_error& e) { backend->GetOutput().LogError("Exception in database back-end: " + std::string(e.what())); } static OrthancPluginErrorCode AddAttachment(void* payload, int64_t id, const OrthancPluginAttachment* attachment) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->AddAttachment(id, *attachment); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode AttachChild(void* payload, int64_t parent, int64_t child) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->AttachChild(parent, child); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode ClearChanges(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->ClearChanges(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode ClearExportedResources(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->ClearExportedResources(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode CreateResource(int64_t* id, void* payload, const char* publicId, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *id = backend->CreateResource(publicId, resourceType); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode DeleteAttachment(void* payload, int64_t id, int32_t contentType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->DeleteAttachment(id, contentType); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode DeleteMetadata(void* payload, int64_t id, int32_t metadataType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->DeleteMetadata(id, metadataType); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode DeleteResource(void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->DeleteResource(id); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetAllInternalIds(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<int64_t> target; backend->GetAllInternalIds(target, resourceType); for (std::list<int64_t>::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetAllPublicIds(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<std::string> ids; backend->GetAllPublicIds(ids, resourceType); for (std::list<std::string>::const_iterator it = ids.begin(); it != ids.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetAllPublicIdsWithLimit(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType, uint64_t since, uint64_t limit) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<std::string> ids; backend->GetAllPublicIds(ids, resourceType, since, limit); for (std::list<std::string>::const_iterator it = ids.begin(); it != ids.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetChanges(OrthancPluginDatabaseContext* context, void* payload, int64_t since, uint32_t maxResult) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Change); try { bool done; backend->GetChanges(done, since, maxResult); if (done) { OrthancPluginDatabaseAnswerChangesDone(backend->GetOutput().context_, backend->GetOutput().database_); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetChildrenInternalId(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<int64_t> target; backend->GetChildrenInternalId(target, id); for (std::list<int64_t>::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetChildrenPublicId(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<std::string> ids; backend->GetChildrenPublicId(ids, id); for (std::list<std::string>::const_iterator it = ids.begin(); it != ids.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetExportedResources(OrthancPluginDatabaseContext* context, void* payload, int64_t since, uint32_t maxResult) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_ExportedResource); try { bool done; backend->GetExportedResources(done, since, maxResult); if (done) { OrthancPluginDatabaseAnswerExportedResourcesDone(backend->GetOutput().context_, backend->GetOutput().database_); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetLastChange(OrthancPluginDatabaseContext* context, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Change); try { backend->GetLastChange(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetLastExportedResource(OrthancPluginDatabaseContext* context, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_ExportedResource); try { backend->GetLastExportedResource(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetMainDicomTags(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_DicomTag); try { backend->GetMainDicomTags(id); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetPublicId(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::string s = backend->GetPublicId(id); OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, s.c_str()); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetResourceCount(uint64_t* target, void* payload, OrthancPluginResourceType resourceType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *target = backend->GetResourceCount(resourceType); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetResourceType(OrthancPluginResourceType* resourceType, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *resourceType = backend->GetResourceType(id); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetTotalCompressedSize(uint64_t* target, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *target = backend->GetTotalCompressedSize(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetTotalUncompressedSize(uint64_t* target, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *target = backend->GetTotalUncompressedSize(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode IsExistingResource(int32_t* existing, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *existing = backend->IsExistingResource(id); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode IsProtectedPatient(int32_t* isProtected, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *isProtected = backend->IsProtectedPatient(id); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode ListAvailableMetadata(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<int32_t> target; backend->ListAvailableMetadata(target, id); for (std::list<int32_t>::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt32(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode ListAvailableAttachments(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<int32_t> target; backend->ListAvailableAttachments(target, id); for (std::list<int32_t>::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt32(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LogChange(void* payload, const OrthancPluginChange* change) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->LogChange(*change); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LogExportedResource(void* payload, const OrthancPluginExportedResource* exported) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->LogExportedResource(*exported); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupAttachment(OrthancPluginDatabaseContext* context, void* payload, int64_t id, int32_t contentType) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Attachment); try { backend->LookupAttachment(id, contentType); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupGlobalProperty(OrthancPluginDatabaseContext* context, void* payload, int32_t property) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::string s; if (backend->LookupGlobalProperty(s, property)) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, s.c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupIdentifier3(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType, const OrthancPluginDicomTag* tag, OrthancPluginIdentifierConstraint constraint) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<int64_t> target; backend->LookupIdentifier(target, resourceType, tag->group, tag->element, constraint, tag->value); for (std::list<int64_t>::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupIdentifierRange(OrthancPluginDatabaseContext* context, void* payload, OrthancPluginResourceType resourceType, uint16_t group, uint16_t element, const char* start, const char* end) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<int64_t> target; backend->LookupIdentifierRange(target, resourceType, group, element, start, end); for (std::list<int64_t>::const_iterator it = target.begin(); it != target.end(); ++it) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, *it); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseContext* context, void* payload, int64_t id, int32_t metadata) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::string s; if (backend->LookupMetadata(s, id, metadata)) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, s.c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupParent(OrthancPluginDatabaseContext* context, void* payload, int64_t id) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t parent; if (backend->LookupParent(parent, id)) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, parent); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode LookupResource(OrthancPluginDatabaseContext* context, void* payload, const char* publicId) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t id; OrthancPluginResourceType type; if (backend->LookupResource(id, type, publicId)) { OrthancPluginDatabaseAnswerResource(backend->GetOutput().context_, backend->GetOutput().database_, id, type); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SelectPatientToRecycle(OrthancPluginDatabaseContext* context, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t id; if (backend->SelectPatientToRecycle(id)) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, id); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SelectPatientToRecycle2(OrthancPluginDatabaseContext* context, void* payload, int64_t patientIdToAvoid) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { int64_t id; if (backend->SelectPatientToRecycle(id, patientIdToAvoid)) { OrthancPluginDatabaseAnswerInt64(backend->GetOutput().context_, backend->GetOutput().database_, id); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SetGlobalProperty(void* payload, int32_t property, const char* value) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetGlobalProperty(property, value); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SetMainDicomTag(void* payload, int64_t id, const OrthancPluginDicomTag* tag) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetMainDicomTag(id, tag->group, tag->element, tag->value); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SetIdentifierTag(void* payload, int64_t id, const OrthancPluginDicomTag* tag) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetIdentifierTag(id, tag->group, tag->element, tag->value); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SetMetadata(void* payload, int64_t id, int32_t metadata, const char* value) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetMetadata(id, metadata, value); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode SetProtectedPatient(void* payload, int64_t id, int32_t isProtected) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetProtectedPatient(id, (isProtected != 0)); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode StartTransaction(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->StartTransaction(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode RollbackTransaction(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->RollbackTransaction(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode CommitTransaction(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->CommitTransaction(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode Open(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->Open(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode Close(void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->Close(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode GetDatabaseVersion(uint32_t* version, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *version = backend->GetDatabaseVersion(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode UpgradeDatabase(void* payload, uint32_t targetVersion, OrthancPluginStorageArea* storageArea) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->UpgradeDatabase(targetVersion, storageArea); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } static OrthancPluginErrorCode ClearMainDicomTags(void* payload, int64_t internalId) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->ClearMainDicomTags(internalId); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 /* Use GetOutput().AnswerResource() */ static OrthancPluginErrorCode LookupResources( OrthancPluginDatabaseContext* context, void* payload, uint32_t constraintsCount, const OrthancPluginDatabaseConstraint* constraints, OrthancPluginResourceType queryLevel, uint32_t limit, uint8_t requestSomeInstance) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_MatchingResource); try { std::vector<Orthanc::DatabaseConstraint> lookup; lookup.reserve(constraintsCount); for (uint32_t i = 0; i < constraintsCount; i++) { lookup.push_back(Orthanc::DatabaseConstraint(constraints[i])); } backend->LookupResources(lookup, queryLevel, limit, (requestSomeInstance != 0)); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } #endif #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 static OrthancPluginErrorCode CreateInstance(OrthancPluginCreateInstanceResult* output, void* payload, const char* hashPatient, const char* hashStudy, const char* hashSeries, const char* hashInstance) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->CreateInstance(*output, hashPatient, hashStudy, hashSeries, hashInstance); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } #endif #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 static OrthancPluginErrorCode SetResourcesContent( void* payload, uint32_t countIdentifierTags, const OrthancPluginResourcesContentTags* identifierTags, uint32_t countMainDicomTags, const OrthancPluginResourcesContentTags* mainDicomTags, uint32_t countMetadata, const OrthancPluginResourcesContentMetadata* metadata) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->SetResourcesContent(countIdentifierTags, identifierTags, countMainDicomTags, mainDicomTags, countMetadata, metadata); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } #endif // New primitive since Orthanc 1.5.2 static OrthancPluginErrorCode GetChildrenMetadata(OrthancPluginDatabaseContext* context, void* payload, int64_t resourceId, int32_t metadata) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { std::list<std::string> values; backend->GetChildrenMetadata(values, resourceId, metadata); for (std::list<std::string>::const_iterator it = values.begin(); it != values.end(); ++it) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, it->c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } // New primitive since Orthanc 1.5.2 static OrthancPluginErrorCode GetLastChangeIndex(int64_t* result, void* payload) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { *result = backend->GetLastChangeIndex(); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } // New primitive since Orthanc 1.5.2 static OrthancPluginErrorCode TagMostRecentPatient(void* payload, int64_t patientId) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None); try { backend->TagMostRecentPatient(patientId); return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) // New primitive since Orthanc 1.5.4 static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseContext* context, void* payload, int64_t resourceId) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_Metadata); try { std::map<int32_t, std::string> result; backend->GetAllMetadata(result, resourceId); for (std::map<int32_t, std::string>::const_iterator it = result.begin(); it != result.end(); ++it) { OrthancPluginDatabaseAnswerMetadata(backend->GetOutput().context_, backend->GetOutput().database_, resourceId, it->first, it->second.c_str()); } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } # endif #endif #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) // New primitive since Orthanc 1.5.4 static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseContext* context, uint8_t* isExisting, int64_t* id, OrthancPluginResourceType* type, void* payload, const char* publicId) { IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload); backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_String); try { std::string parent; if (backend->LookupResourceAndParent(*id, *type, parent, publicId)) { *isExisting = 1; if (!parent.empty()) { OrthancPluginDatabaseAnswerString(backend->GetOutput().context_, backend->GetOutput().database_, parent.c_str()); } } else { *isExisting = 0; } return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH } # endif #endif public: /** * Register a custom database back-end written in C++. * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param backend Your custom database engine. **/ static void Register(OrthancPluginContext* context, IDatabaseBackend& backend) { OrthancPluginDatabaseBackend params; memset(¶ms, 0, sizeof(params)); OrthancPluginDatabaseExtensions extensions; memset(&extensions, 0, sizeof(extensions)); params.addAttachment = AddAttachment; params.attachChild = AttachChild; params.clearChanges = ClearChanges; params.clearExportedResources = ClearExportedResources; params.createResource = CreateResource; params.deleteAttachment = DeleteAttachment; params.deleteMetadata = DeleteMetadata; params.deleteResource = DeleteResource; params.getAllPublicIds = GetAllPublicIds; params.getChanges = GetChanges; params.getChildrenInternalId = GetChildrenInternalId; params.getChildrenPublicId = GetChildrenPublicId; params.getExportedResources = GetExportedResources; params.getLastChange = GetLastChange; params.getLastExportedResource = GetLastExportedResource; params.getMainDicomTags = GetMainDicomTags; params.getPublicId = GetPublicId; params.getResourceCount = GetResourceCount; params.getResourceType = GetResourceType; params.getTotalCompressedSize = GetTotalCompressedSize; params.getTotalUncompressedSize = GetTotalUncompressedSize; params.isExistingResource = IsExistingResource; params.isProtectedPatient = IsProtectedPatient; params.listAvailableMetadata = ListAvailableMetadata; params.listAvailableAttachments = ListAvailableAttachments; params.logChange = LogChange; params.logExportedResource = LogExportedResource; params.lookupAttachment = LookupAttachment; params.lookupGlobalProperty = LookupGlobalProperty; params.lookupIdentifier = NULL; // Unused starting with Orthanc 0.9.5 (db v6) params.lookupIdentifier2 = NULL; // Unused starting with Orthanc 0.9.5 (db v6) params.lookupMetadata = LookupMetadata; params.lookupParent = LookupParent; params.lookupResource = LookupResource; params.selectPatientToRecycle = SelectPatientToRecycle; params.selectPatientToRecycle2 = SelectPatientToRecycle2; params.setGlobalProperty = SetGlobalProperty; params.setMainDicomTag = SetMainDicomTag; params.setIdentifierTag = SetIdentifierTag; params.setMetadata = SetMetadata; params.setProtectedPatient = SetProtectedPatient; params.startTransaction = StartTransaction; params.rollbackTransaction = RollbackTransaction; params.commitTransaction = CommitTransaction; params.open = Open; params.close = Close; extensions.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit; extensions.getDatabaseVersion = GetDatabaseVersion; extensions.upgradeDatabase = UpgradeDatabase; extensions.clearMainDicomTags = ClearMainDicomTags; extensions.getAllInternalIds = GetAllInternalIds; // New in Orthanc 0.9.5 (db v6) extensions.lookupIdentifier3 = LookupIdentifier3; // New in Orthanc 0.9.5 (db v6) bool performanceWarning = true; #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 4, 0) extensions.lookupIdentifierRange = LookupIdentifierRange; // New in Orthanc 1.4.0 # endif #endif #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 // Optimizations brought by Orthanc 1.5.2 extensions.lookupResources = LookupResources; // Fast lookup extensions.setResourcesContent = SetResourcesContent; // Fast setting tags/metadata extensions.getChildrenMetadata = GetChildrenMetadata; extensions.getLastChangeIndex = GetLastChangeIndex; extensions.tagMostRecentPatient = TagMostRecentPatient; if (backend.HasCreateInstance()) { extensions.createInstance = CreateInstance; // Fast creation of resources } #endif #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in 1.3.1 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4) // Optimizations brought by Orthanc 1.5.4 extensions.lookupResourceAndParent = LookupResourceAndParent; extensions.getAllMetadata = GetAllMetadata; performanceWarning = false; # endif #endif if (performanceWarning) { char info[1024]; sprintf(info, "Performance warning: The database index plugin was compiled " "against an old version of the Orthanc SDK (%d.%d.%d): " "Consider upgrading to version %d.%d.%d of the Orthanc SDK", ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER, ORTHANC_OPTIMAL_VERSION_MAJOR, ORTHANC_OPTIMAL_VERSION_MINOR, ORTHANC_OPTIMAL_VERSION_REVISION); OrthancPluginLogWarning(context, info); } OrthancPluginDatabaseContext* database = OrthancPluginRegisterDatabaseBackendV2(context, ¶ms, &extensions, &backend); if (!context) { throw std::runtime_error("Unable to register the database backend"); } backend.RegisterOutput(new DatabaseBackendOutput(context, database)); } }; }