Mercurial > hg > orthanc-databases
changeset 212:821d4ba83dc3
reorganization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 24 Mar 2021 15:47:14 +0100 |
parents | d74a92ac00ea |
children | c2e4a909de0e |
files | Framework/Plugins/DatabaseBackendAdapterV2.cpp Framework/Plugins/DatabaseBackendAdapterV3.cpp Framework/Plugins/DatabaseBackendAdapterV3.h Resources/CMake/DatabasesPluginConfiguration.cmake SQLite/Plugins/IndexPlugin.cpp |
diffstat | 5 files changed, 1913 insertions(+), 1829 deletions(-) [+] |
line wrap: on
line diff
--- a/Framework/Plugins/DatabaseBackendAdapterV2.cpp Wed Mar 24 15:32:29 2021 +0100 +++ b/Framework/Plugins/DatabaseBackendAdapterV2.cpp Wed Mar 24 15:47:14 2021 +0100 @@ -24,6 +24,10 @@ #include <OrthancException.h> +#include <stdexcept> +#include <list> +#include <string> + #define ORTHANC_PLUGINS_DATABASE_CATCH \ catch (::Orthanc::OrthancException& e) \ @@ -42,11 +46,6 @@ } -#include <stdexcept> -#include <list> -#include <string> - - namespace OrthancDatabases { class DatabaseBackendAdapterV2::Output : public IDatabaseBackendOutput
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Plugins/DatabaseBackendAdapterV3.cpp Wed Mar 24 15:47:14 2021 +0100 @@ -0,0 +1,1842 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2021 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/>. + **/ + + +#include "DatabaseBackendAdapterV3.h" + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) + +#include <OrthancException.h> + +#include <stdexcept> +#include <list> +#include <string> +#include <cassert> + +#include <boost/thread/mutex.hpp> // TODO - REMOVE + + +#define ORTHANC_PLUGINS_DATABASE_CATCH(context) \ + catch (::Orthanc::OrthancException& e) \ + { \ + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); \ + } \ + catch (::std::runtime_error& e) \ + { \ + const std::string message = "Exception in database back-end: " + std::string(e.what()); \ + OrthancPluginLogError(context, message.c_str()); \ + return OrthancPluginErrorCode_DatabasePlugin; \ + } \ + catch (...) \ + { \ + OrthancPluginLogError(context, "Native exception"); \ + return OrthancPluginErrorCode_DatabasePlugin; \ + } + + +namespace OrthancDatabases +{ + class DatabaseBackendAdapterV3::Output : public IDatabaseBackendOutput + { + private: + struct Metadata + { + int32_t metadata; + const char* value; + }; + + _OrthancPluginDatabaseAnswerType answerType_; + std::list<std::string> stringsStore_; + + std::vector<OrthancPluginAttachment> attachments_; + std::vector<OrthancPluginChange> changes_; + std::vector<OrthancPluginDicomTag> tags_; + std::vector<OrthancPluginExportedResource> exported_; + std::vector<OrthancPluginDatabaseEvent> events_; + std::vector<int32_t> integers32_; + std::vector<int64_t> integers64_; + std::vector<OrthancPluginMatchingResource> matches_; + std::vector<Metadata> metadata_; + std::vector<std::string> stringAnswers_; + + const char* StoreString(const std::string& s) + { + stringsStore_.push_back(s); + return stringsStore_.back().c_str(); + } + + void SetupAnswerType(_OrthancPluginDatabaseAnswerType type) + { + if (answerType_ == _OrthancPluginDatabaseAnswerType_None) + { + answerType_ = type; + } + else if (answerType_ != type) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + public: + Output() : + answerType_(_OrthancPluginDatabaseAnswerType_None) + { + } + + void Clear() + { + // We don't systematically clear all the vectors, in order to + // avoid spending unnecessary time + + switch (answerType_) + { + case _OrthancPluginDatabaseAnswerType_None: + break; + + case _OrthancPluginDatabaseAnswerType_Attachment: + attachments_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_Change: + changes_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_DicomTag: + tags_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_ExportedResource: + exported_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_Int32: + integers32_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_Int64: + integers64_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_MatchingResource: + matches_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_Metadata: + metadata_.clear(); + break; + + case _OrthancPluginDatabaseAnswerType_String: + stringAnswers_.clear(); + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + answerType_ = _OrthancPluginDatabaseAnswerType_None; + stringsStore_.clear(); + events_.clear(); + + assert(attachments_.empty()); + assert(changes_.empty()); + assert(tags_.empty()); + assert(exported_.empty()); + assert(events_.empty()); + assert(integers32_.empty()); + assert(integers64_.empty()); + assert(matches_.empty()); + assert(metadata_.empty()); + assert(stringAnswers_.empty()); + } + + + OrthancPluginErrorCode ReadAnswersCount(uint32_t& target) const + { + switch (answerType_) + { + case _OrthancPluginDatabaseAnswerType_None: + target = static_cast<uint32_t>(0); + break; + + case _OrthancPluginDatabaseAnswerType_Attachment: + target = static_cast<uint32_t>(attachments_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_Change: + target = static_cast<uint32_t>(changes_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_DicomTag: + target = static_cast<uint32_t>(tags_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_ExportedResource: + target = static_cast<uint32_t>(exported_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_Int32: + target = static_cast<uint32_t>(integers32_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_Int64: + target = static_cast<uint32_t>(integers64_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_MatchingResource: + target = static_cast<uint32_t>(matches_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_Metadata: + target = static_cast<uint32_t>(metadata_.size()); + break; + + case _OrthancPluginDatabaseAnswerType_String: + target = static_cast<uint32_t>(stringAnswers_.size()); + break; + + default: + return OrthancPluginErrorCode_InternalError; + } + + return OrthancPluginErrorCode_Success; + } + + + OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginAttachment& target /* out */, + uint32_t index) const + { + if (index < attachments_.size()) + { + target = attachments_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerChange(OrthancPluginChange& target /* out */, + uint32_t index) const + { + if (index < changes_.size()) + { + target = changes_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerDicomTag(uint16_t& group, + uint16_t& element, + const char*& value, + uint32_t index) const + { + if (index < tags_.size()) + { + const OrthancPluginDicomTag& tag = tags_[index]; + group = tag.group; + element = tag.element; + value = tag.value; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginExportedResource& target /* out */, + uint32_t index) const + { + if (index < exported_.size()) + { + target = exported_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerInt32(int32_t& target, + uint32_t index) const + { + if (index < integers32_.size()) + { + target = integers32_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerInt64(int64_t& target, + uint32_t index) const + { + if (index < integers64_.size()) + { + target = integers64_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginMatchingResource& target, + uint32_t index) const + { + if (index < matches_.size()) + { + target = matches_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerMetadata(int32_t& metadata, + const char*& value, + uint32_t index) const + { + if (index < metadata_.size()) + { + const Metadata& tmp = metadata_[index]; + metadata = tmp.metadata; + value = tmp.value; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadAnswerString(const char*& target, + uint32_t index) const + { + if (index < stringAnswers_.size()) + { + target = stringAnswers_[index].c_str(); + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + OrthancPluginErrorCode ReadEventsCount(uint32_t& target /* out */) const + { + target = static_cast<uint32_t>(events_.size()); + return OrthancPluginErrorCode_Success; + } + + + OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseEvent& event /* out */, + uint32_t index) const + { + if (index < events_.size()) + { + event = events_[index]; + return OrthancPluginErrorCode_Success; + } + else + { + return OrthancPluginErrorCode_ParameterOutOfRange; + } + } + + + virtual 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) ORTHANC_OVERRIDE + { + OrthancPluginDatabaseEvent event; + event.type = OrthancPluginDatabaseEventType_DeletedAttachment; + event.content.attachment.uuid = StoreString(uuid); + event.content.attachment.contentType = contentType; + event.content.attachment.uncompressedSize = uncompressedSize; + event.content.attachment.uncompressedHash = StoreString(uncompressedHash); + event.content.attachment.compressionType = compressionType; + event.content.attachment.compressedSize = compressedSize; + event.content.attachment.compressedHash = StoreString(compressedHash); + + events_.push_back(event); + } + + + virtual void SignalDeletedResource(const std::string& publicId, + OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE + { + OrthancPluginDatabaseEvent event; + event.type = OrthancPluginDatabaseEventType_DeletedResource; + event.content.resource.level = resourceType; + event.content.resource.publicId = StoreString(publicId); + + events_.push_back(event); + } + + + virtual void SignalRemainingAncestor(const std::string& ancestorId, + OrthancPluginResourceType ancestorType) ORTHANC_OVERRIDE + { + OrthancPluginDatabaseEvent event; + event.type = OrthancPluginDatabaseEventType_RemainingAncestor; + event.content.resource.level = ancestorType; + event.content.resource.publicId = StoreString(ancestorId); + + events_.push_back(event); + } + + + virtual 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) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Attachment); + + OrthancPluginAttachment attachment; + attachment.uuid = StoreString(uuid); + attachment.contentType = contentType; + attachment.uncompressedSize = uncompressedSize; + attachment.uncompressedHash = StoreString(uncompressedHash); + attachment.compressionType = compressionType; + attachment.compressedSize = compressedSize; + attachment.compressedHash = StoreString(compressedHash); + + attachments_.push_back(attachment); + } + + + virtual void AnswerChange(int64_t seq, + int32_t changeType, + OrthancPluginResourceType resourceType, + const std::string& publicId, + const std::string& date) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Change); + + OrthancPluginChange change; + change.seq = seq; + change.changeType = changeType; + change.resourceType = resourceType; + change.publicId = StoreString(publicId); + change.date = StoreString(date); + + changes_.push_back(change); + } + + + virtual void AnswerDicomTag(uint16_t group, + uint16_t element, + const std::string& value) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_DicomTag); + + OrthancPluginDicomTag tag; + tag.group = group; + tag.element = element; + tag.value = StoreString(value); + + tags_.push_back(tag); + } + + + virtual 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) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_ExportedResource); + + OrthancPluginExportedResource exported; + exported.seq = seq; + exported.resourceType = resourceType; + exported.publicId = StoreString(publicId); + exported.modality = StoreString(modality); + exported.date = StoreString(date); + exported.patientId = StoreString(patientId); + exported.studyInstanceUid = StoreString(studyInstanceUid); + exported.seriesInstanceUid = StoreString(seriesInstanceUid); + exported.sopInstanceUid = StoreString(sopInstanceUid); + + exported_.push_back(exported); + } + + + virtual void AnswerMatchingResource(const std::string& resourceId) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_MatchingResource); + + OrthancPluginMatchingResource match; + match.resourceId = StoreString(resourceId); + match.someInstanceId = NULL; + + matches_.push_back(match); + } + + + virtual void AnswerMatchingResource(const std::string& resourceId, + const std::string& someInstanceId) ORTHANC_OVERRIDE + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_MatchingResource); + + OrthancPluginMatchingResource match; + match.resourceId = StoreString(resourceId); + match.someInstanceId = StoreString(someInstanceId); + + matches_.push_back(match); + } + + + void AnswerIntegers32(const std::list<int32_t>& values) + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int32); + + integers32_.reserve(values.size()); + std::copy(std::begin(values), std::end(values), std::back_inserter(integers32_)); + } + + + void AnswerIntegers64(const std::list<int64_t>& values) + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int64); + + integers64_.reserve(values.size()); + std::copy(std::begin(values), std::end(values), std::back_inserter(integers64_)); + } + + + void AnswerInteger64(int64_t value) + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int64); + + integers64_.resize(1); + integers64_[0] = value; + } + + + void AnswerMetadata(int32_t metadata, + const std::string& value) + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_Metadata); + + Metadata tmp; + tmp.metadata = metadata; + tmp.value = StoreString(value); + + metadata_.push_back(tmp); + } + + + void AnswerStrings(const std::list<std::string>& values) + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_String); + + stringAnswers_.reserve(values.size()); + std::copy(std::begin(values), std::end(values), std::back_inserter(stringAnswers_)); + } + + + void AnswerString(const std::string& value) + { + SetupAnswerType(_OrthancPluginDatabaseAnswerType_String); + + if (stringAnswers_.empty()) + { + stringAnswers_.push_back(value); + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + }; + + + IDatabaseBackendOutput* DatabaseBackendAdapterV3::Factory::CreateOutput() + { + return new DatabaseBackendAdapterV3::Output; + } + + + class DatabaseBackendAdapterV3::Transaction : public boost::noncopyable + { + private: + boost::mutex::scoped_lock lock_; // TODO - REMOVE + IndexBackend& backend_; + std::unique_ptr<Output> output_; + + static boost::mutex& GetMutex() // TODO - REMOVE + { + static boost::mutex mutex_; + return mutex_; + } + + public: + Transaction(IndexBackend& backend) : + lock_(GetMutex()), + backend_(backend), + output_(new Output) + { + } + + ~Transaction() + { + } + + IndexBackend& GetBackend() const + { + return backend_; + } + + Output& GetOutput() const + { + return *output_; + } + + OrthancPluginContext* GetContext() const + { + return backend_.GetContext(); + } + }; + + + static OrthancPluginErrorCode ReadAnswersCount(OrthancPluginDatabaseTransaction* transaction, + uint32_t* target /* out */) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswersCount(*target); + } + + + static OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginAttachment* target /* out */, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerAttachment(*target, index); + } + + + static OrthancPluginErrorCode ReadAnswerChange(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginChange* target /* out */, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerChange(*target, index); + } + + + static OrthancPluginErrorCode ReadAnswerDicomTag(OrthancPluginDatabaseTransaction* transaction, + uint16_t* group, + uint16_t* element, + const char** value, + uint32_t index) + { + assert(group != NULL); + assert(element != NULL); + assert(value != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerDicomTag(*group, *element, *value, index); + } + + + static OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginExportedResource* target /* out */, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerExportedResource(*target, index); + } + + + static OrthancPluginErrorCode ReadAnswerInt32(OrthancPluginDatabaseTransaction* transaction, + int32_t* target, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerInt32(*target, index); + } + + + static OrthancPluginErrorCode ReadAnswerInt64(OrthancPluginDatabaseTransaction* transaction, + int64_t* target, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerInt64(*target, index); + } + + + static OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginMatchingResource* target, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerMatchingResource(*target, index); + } + + + static OrthancPluginErrorCode ReadAnswerMetadata(OrthancPluginDatabaseTransaction* transaction, + int32_t* metadata, + const char** value, + uint32_t index) + { + assert(metadata != NULL); + assert(value != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerMetadata(*metadata, *value, index); + } + + + static OrthancPluginErrorCode ReadAnswerString(OrthancPluginDatabaseTransaction* transaction, + const char** target, + uint32_t index) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadAnswerString(*target, index); + } + + + static OrthancPluginErrorCode ReadEventsCount(OrthancPluginDatabaseTransaction* transaction, + uint32_t* target /* out */) + { + assert(target != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadEventsCount(*target); + } + + + static OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginDatabaseEvent* event /* out */, + uint32_t index) + { + assert(event != NULL); + const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction); + return that.GetOutput().ReadEvent(*event, index); + } + + + static OrthancPluginErrorCode Open(void* database) + { + IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); + + try + { + backend->Open(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); + } + + + static OrthancPluginErrorCode Close(void* database) + { + IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); + + try + { + backend->Close(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); + } + + + static OrthancPluginErrorCode DestructDatabase(void* database) + { + // Nothing to delete, as this plugin uses a singleton to store backend + if (database == NULL) + { + return OrthancPluginErrorCode_InternalError; + } + else + { + return OrthancPluginErrorCode_Success; + } + } + + + static OrthancPluginErrorCode GetDatabaseVersion(void* database, + uint32_t* version) + { + IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); + + try + { + *version = backend->GetDatabaseVersion(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); + } + + + static OrthancPluginErrorCode UpgradeDatabase(void* database, + OrthancPluginStorageArea* storageArea, + uint32_t targetVersion) + { + IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); + + try + { + backend->UpgradeDatabase(targetVersion, storageArea); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); + } + + + static OrthancPluginErrorCode StartTransaction(void* database, + OrthancPluginDatabaseTransaction** target /* out */, + OrthancPluginDatabaseTransactionType type) + { + IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); + + try + { + std::unique_ptr<DatabaseBackendAdapterV3::Transaction> transaction(new DatabaseBackendAdapterV3::Transaction(*backend)); + + switch (type) + { + case OrthancPluginDatabaseTransactionType_ReadOnly: + backend->StartTransaction(TransactionType_ReadOnly); + break; + + case OrthancPluginDatabaseTransactionType_ReadWrite: + backend->StartTransaction(TransactionType_ReadWrite); + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + *target = reinterpret_cast<OrthancPluginDatabaseTransaction*>(transaction.release()); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); + } + + + static OrthancPluginErrorCode DestructTransaction(OrthancPluginDatabaseTransaction* transaction) + { + if (transaction == NULL) + { + return OrthancPluginErrorCode_NullPointer; + } + else + { + delete reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + return OrthancPluginErrorCode_Success; + } + } + + + static OrthancPluginErrorCode Rollback(OrthancPluginDatabaseTransaction* transaction) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().RollbackTransaction(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode Commit(OrthancPluginDatabaseTransaction* transaction, + int64_t fileSizeDelta /* TODO - not used? */) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().CommitTransaction(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode AddAttachment(OrthancPluginDatabaseTransaction* transaction, + int64_t id, + const OrthancPluginAttachment* attachment) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().AddAttachment(id, *attachment); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode ClearChanges(OrthancPluginDatabaseTransaction* transaction) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().ClearChanges(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode ClearExportedResources(OrthancPluginDatabaseTransaction* transaction) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().ClearExportedResources(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode ClearMainDicomTags(OrthancPluginDatabaseTransaction* transaction, + int64_t resourceId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().ClearMainDicomTags(resourceId); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode CreateInstance(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginCreateInstanceResult* target /* out */, + const char* hashPatient, + const char* hashStudy, + const char* hashSeries, + const char* hashInstance) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + if (t->GetBackend().HasCreateInstance()) + { + t->GetBackend().CreateInstance(*target, hashPatient, hashStudy, hashSeries, hashInstance); + } + else + { + t->GetBackend().CreateInstanceGeneric(*target, hashPatient, hashStudy, hashSeries, hashInstance); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode DeleteAttachment(OrthancPluginDatabaseTransaction* transaction, + int64_t id, + int32_t contentType) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().DeleteAttachment(t->GetOutput(), id, contentType); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode DeleteMetadata(OrthancPluginDatabaseTransaction* transaction, + int64_t id, + int32_t metadataType) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().DeleteMetadata(id, metadataType); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode DeleteResource(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().DeleteResource(t->GetOutput(), id); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::map<int32_t, std::string> values; + t->GetBackend().GetAllMetadata(values, id); + + for (std::map<int32_t, std::string>::const_iterator it = values.begin(); it != values.end(); ++it) + { + t->GetOutput().AnswerMetadata(it->first, it->second); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetAllPublicIds(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginResourceType resourceType) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::list<std::string> values; + t->GetBackend().GetAllPublicIds(values, resourceType); + t->GetOutput().AnswerStrings(values); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetAllPublicIdsWithLimit(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginResourceType resourceType, + uint64_t since, + uint64_t limit) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::list<std::string> values; + t->GetBackend().GetAllPublicIds(values, resourceType, since, limit); + t->GetOutput().AnswerStrings(values); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetChanges(OrthancPluginDatabaseTransaction* transaction, + uint8_t* targetDone /* out */, + int64_t since, + uint32_t maxResults) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + bool done; + t->GetBackend().GetChanges(t->GetOutput(), done, since, maxResults); + *targetDone = (done ? 1 : 0); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetChildrenInternalId(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::list<int64_t> values; + t->GetBackend().GetChildrenInternalId(values, id); + t->GetOutput().AnswerIntegers64(values); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetChildrenMetadata(OrthancPluginDatabaseTransaction* transaction, + int64_t resourceId, + int32_t metadata) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::list<std::string> values; + t->GetBackend().GetChildrenMetadata(values, resourceId, metadata); + t->GetOutput().AnswerStrings(values); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetChildrenPublicId(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::list<std::string> values; + t->GetBackend().GetChildrenPublicId(values, id); + t->GetOutput().AnswerStrings(values); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetExportedResources(OrthancPluginDatabaseTransaction* transaction, + uint8_t* targetDone /* out */, + int64_t since, + uint32_t maxResults) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + bool done; + t->GetBackend().GetExportedResources(t->GetOutput(), done, since, maxResults); + *targetDone = (done ? 1 : 0); + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetLastChange(OrthancPluginDatabaseTransaction* transaction) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().GetLastChange(t->GetOutput()); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetLastChangeIndex(OrthancPluginDatabaseTransaction* transaction, + int64_t* target) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + *target = t->GetBackend().GetLastChangeIndex(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetLastExportedResource(OrthancPluginDatabaseTransaction* transaction) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().GetLastExportedResource(t->GetOutput()); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetMainDicomTags(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().GetMainDicomTags(t->GetOutput(), id); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetPublicId(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetOutput().AnswerString(t->GetBackend().GetPublicId(id)); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetResourcesCount(OrthancPluginDatabaseTransaction* transaction, + uint64_t* target /* out */, + OrthancPluginResourceType resourceType) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + *target = t->GetBackend().GetResourcesCount(resourceType); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetResourceType(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginResourceType* target /* out */, + uint64_t resourceId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + *target = t->GetBackend().GetResourceType(resourceId); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetTotalCompressedSize(OrthancPluginDatabaseTransaction* transaction, + uint64_t* target /* out */) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + *target = t->GetBackend().GetTotalCompressedSize(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode GetTotalUncompressedSize(OrthancPluginDatabaseTransaction* transaction, + uint64_t* target /* out */) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + *target = t->GetBackend().GetTotalUncompressedSize(); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode IsDiskSizeAbove(OrthancPluginDatabaseTransaction* transaction, + uint8_t* target, + uint64_t threshold) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + bool above = (t->GetBackend().GetTotalCompressedSize() >= threshold); + *target = (above ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode IsExistingResource(OrthancPluginDatabaseTransaction* transaction, + uint8_t* target, + int64_t resourceId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + bool exists = t->GetBackend().IsExistingResource(resourceId); + *target = (exists ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode IsProtectedPatient(OrthancPluginDatabaseTransaction* transaction, + uint8_t* target, + int64_t resourceId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + bool isProtected = t->GetBackend().IsProtectedPatient(resourceId); + *target = (isProtected ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode ListAvailableAttachments(OrthancPluginDatabaseTransaction* transaction, + int64_t resourceId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::list<int32_t> values; + t->GetBackend().ListAvailableAttachments(values, resourceId); + t->GetOutput().AnswerIntegers32(values); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LogChange(OrthancPluginDatabaseTransaction* transaction, + int32_t changeType, + int64_t resourceId, + OrthancPluginResourceType resourceType, + const char* date) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().LogChange(changeType, resourceId, resourceType, date); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LogExportedResource(OrthancPluginDatabaseTransaction* transaction, + OrthancPluginResourceType resourceType, + const char* publicId, + const char* modality, + const char* date, + const char* patientId, + const char* studyInstanceUid, + const char* seriesInstanceUid, + const char* sopInstanceUid) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + OrthancPluginExportedResource exported; + exported.seq = 0; + exported.resourceType = resourceType; + exported.publicId = publicId; + exported.modality = modality; + exported.date = date; + exported.patientId = patientId; + exported.studyInstanceUid = studyInstanceUid; + exported.seriesInstanceUid = seriesInstanceUid; + exported.sopInstanceUid = sopInstanceUid; + + t->GetOutput().Clear(); + t->GetBackend().LogExportedResource(exported); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupAttachment(OrthancPluginDatabaseTransaction* transaction, + int64_t resourceId, + int32_t contentType) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().LookupAttachment(t->GetOutput(), resourceId, contentType); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupGlobalProperty(OrthancPluginDatabaseTransaction* transaction, + int32_t property) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::string s; + if (t->GetBackend().LookupGlobalProperty(s, property)) + { + t->GetOutput().AnswerString(s); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseTransaction* transaction, + int64_t id, + int32_t metadata) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::string s; + if (t->GetBackend().LookupMetadata(s, id, metadata)) + { + t->GetOutput().AnswerString(s); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupParent(OrthancPluginDatabaseTransaction* transaction, + int64_t id) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + int64_t parentId; + if (t->GetBackend().LookupParent(parentId, id)) + { + t->GetOutput().AnswerInteger64(parentId); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupResource(OrthancPluginDatabaseTransaction* transaction, + uint8_t* isExisting /* out */, + int64_t* id /* out */, + OrthancPluginResourceType* type /* out */, + const char* publicId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + if (t->GetBackend().LookupResource(*id, *type, publicId)) + { + *isExisting = 1; + } + else + { + *isExisting = 0; + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupResources(OrthancPluginDatabaseTransaction* transaction, + uint32_t constraintsCount, + const OrthancPluginDatabaseConstraint* constraints, + OrthancPluginResourceType queryLevel, + uint32_t limit, + uint8_t requestSomeInstanceId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::vector<Orthanc::DatabaseConstraint> lookup; + lookup.reserve(constraintsCount); + + for (uint32_t i = 0; i < constraintsCount; i++) + { + lookup.push_back(Orthanc::DatabaseConstraint(constraints[i])); + } + + t->GetBackend().LookupResources(t->GetOutput(), lookup, queryLevel, limit, (requestSomeInstanceId != 0)); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseTransaction* transaction, + uint8_t* isExisting /* out */, + int64_t* id /* out */, + OrthancPluginResourceType* type /* out */, + const char* publicId) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + std::string parent; + if (t->GetBackend().LookupResourceAndParent(*id, *type, parent, publicId)) + { + *isExisting = 1; + + if (!parent.empty()) + { + t->GetOutput().AnswerString(parent); + } + } + else + { + *isExisting = 0; + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode SelectPatientToRecycle(OrthancPluginDatabaseTransaction* transaction) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + int64_t id; + if (t->GetBackend().SelectPatientToRecycle(id)) + { + t->GetOutput().AnswerInteger64(id); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode SelectPatientToRecycle2(OrthancPluginDatabaseTransaction* transaction, + int64_t patientIdToAvoid) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + + int64_t id; + if (t->GetBackend().SelectPatientToRecycle(id, patientIdToAvoid)) + { + t->GetOutput().AnswerInteger64(id); + } + + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode SetGlobalProperty(OrthancPluginDatabaseTransaction* transaction, + int32_t property, + const char* value) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().SetGlobalProperty(property, value); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode SetMetadata(OrthancPluginDatabaseTransaction* transaction, + int64_t id, + int32_t metadata, + const char* value) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().SetMetadata(id, metadata, value); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode SetProtectedPatient(OrthancPluginDatabaseTransaction* transaction, + int64_t id, + uint8_t isProtected) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().SetProtectedPatient(id, (isProtected != 0)); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + static OrthancPluginErrorCode SetResourcesContent(OrthancPluginDatabaseTransaction* transaction, + uint32_t countIdentifierTags, + const OrthancPluginResourcesContentTags* identifierTags, + uint32_t countMainDicomTags, + const OrthancPluginResourcesContentTags* mainDicomTags, + uint32_t countMetadata, + const OrthancPluginResourcesContentMetadata* metadata) + { + DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction); + + try + { + t->GetOutput().Clear(); + t->GetBackend().SetResourcesContent(countIdentifierTags, identifierTags, + countMainDicomTags, mainDicomTags, + countMetadata, metadata); + return OrthancPluginErrorCode_Success; + } + ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); + } + + + void DatabaseBackendAdapterV3::Register(IndexBackend& database) + { + OrthancPluginDatabaseBackendV3 params; + memset(¶ms, 0, sizeof(params)); + + params.readAnswersCount = ReadAnswersCount; + params.readAnswerAttachment = ReadAnswerAttachment; + params.readAnswerChange = ReadAnswerChange; + params.readAnswerDicomTag = ReadAnswerDicomTag; + params.readAnswerExportedResource = ReadAnswerExportedResource; + params.readAnswerInt32 = ReadAnswerInt32; + params.readAnswerInt64 = ReadAnswerInt64; + params.readAnswerMatchingResource = ReadAnswerMatchingResource; + params.readAnswerMetadata = ReadAnswerMetadata; + params.readAnswerString = ReadAnswerString; + + params.readEventsCount = ReadEventsCount; + params.readEvent = ReadEvent; + + params.open = Open; + params.close = Close; + params.destructDatabase = DestructDatabase; + params.getDatabaseVersion = GetDatabaseVersion; + params.upgradeDatabase = UpgradeDatabase; + params.startTransaction = StartTransaction; + params.destructTransaction = DestructTransaction; + params.rollback = Rollback; + params.commit = Commit; + + params.addAttachment = AddAttachment; + params.clearChanges = ClearChanges; + params.clearExportedResources = ClearExportedResources; + params.clearMainDicomTags = ClearMainDicomTags; + params.createInstance = CreateInstance; + params.deleteAttachment = DeleteAttachment; + params.deleteMetadata = DeleteMetadata; + params.deleteResource = DeleteResource; + params.getAllMetadata = GetAllMetadata; + params.getAllPublicIds = GetAllPublicIds; + params.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit; + params.getChanges = GetChanges; + params.getChildrenInternalId = GetChildrenInternalId; + params.getChildrenMetadata = GetChildrenMetadata; + params.getChildrenPublicId = GetChildrenPublicId; + params.getExportedResources = GetExportedResources; + params.getLastChange = GetLastChange; + params.getLastChangeIndex = GetLastChangeIndex; + params.getLastExportedResource = GetLastExportedResource; + params.getMainDicomTags = GetMainDicomTags; + params.getPublicId = GetPublicId; + params.getResourcesCount = GetResourcesCount; + params.getResourceType = GetResourceType; + params.getTotalCompressedSize = GetTotalCompressedSize; + params.getTotalUncompressedSize = GetTotalUncompressedSize; + params.isDiskSizeAbove = IsDiskSizeAbove; + params.isExistingResource = IsExistingResource; + params.isProtectedPatient = IsProtectedPatient; + params.listAvailableAttachments = ListAvailableAttachments; + params.logChange = LogChange; + params.logExportedResource = LogExportedResource; + params.lookupAttachment = LookupAttachment; + params.lookupGlobalProperty = LookupGlobalProperty; + params.lookupMetadata = LookupMetadata; + params.lookupParent = LookupParent; + params.lookupResource = LookupResource; + params.lookupResources = LookupResources; + params.lookupResourceAndParent = LookupResourceAndParent; + params.selectPatientToRecycle = SelectPatientToRecycle; + params.selectPatientToRecycle2 = SelectPatientToRecycle2; + params.setGlobalProperty = SetGlobalProperty; + params.setMetadata = SetMetadata; + params.setProtectedPatient = SetProtectedPatient; + params.setResourcesContent = SetResourcesContent; + + OrthancPluginContext* context = database.GetContext(); + + if (OrthancPluginRegisterDatabaseBackendV3(context, ¶ms, sizeof(params), &database) != OrthancPluginErrorCode_Success) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend"); + } + + database.SetOutputFactory(new Factory); + } +} + +# endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Plugins/DatabaseBackendAdapterV3.h Wed Mar 24 15:47:14 2021 +0100 @@ -0,0 +1,64 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2021 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/>. + **/ + + + +#pragma once + +#include "IndexBackend.h" + + +#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 +# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) + +namespace OrthancDatabases +{ + /** + * @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, for Orthanc >= 1.9.2. + **/ + class DatabaseBackendAdapterV3 + { + private: + class Output; + + // This class cannot be instantiated + DatabaseBackendAdapterV3() + { + } + + public: + class Transaction; + + class Factory : public IDatabaseBackendOutput::IFactory + { + public: + virtual IDatabaseBackendOutput* CreateOutput() ORTHANC_OVERRIDE; + }; + + static void Register(IndexBackend& backend); + }; +} + +# endif +#endif
--- a/Resources/CMake/DatabasesPluginConfiguration.cmake Wed Mar 24 15:32:29 2021 +0100 +++ b/Resources/CMake/DatabasesPluginConfiguration.cmake Wed Mar 24 15:47:14 2021 +0100 @@ -76,6 +76,7 @@ list(APPEND DATABASES_SOURCES ${ORTHANC_CORE_SOURCES} ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/DatabaseBackendAdapterV2.cpp + ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/DatabaseBackendAdapterV3.cpp ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/GlobalProperties.cpp ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/IndexBackend.cpp ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/StorageAreaBuffer.cpp
--- a/SQLite/Plugins/IndexPlugin.cpp Wed Mar 24 15:32:29 2021 +0100 +++ b/SQLite/Plugins/IndexPlugin.cpp Wed Mar 24 15:47:14 2021 +0100 @@ -20,6 +20,7 @@ #include "SQLiteIndex.h" +#include "../../Framework/Plugins/DatabaseBackendAdapterV3.h" #include "../../Framework/Plugins/PluginInitialization.h" #include <Compatibility.h> // For std::unique_ptr<> @@ -28,1829 +29,6 @@ static std::unique_ptr<OrthancDatabases::SQLiteIndex> backend_; - -#if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 -# if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) - - -#define ORTHANC_PLUGINS_DATABASE_CATCH(context) \ - catch (::Orthanc::OrthancException& e) \ - { \ - return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); \ - } \ - catch (::std::runtime_error& e) \ - { \ - const std::string message = "Exception in database back-end: " + std::string(e.what()); \ - OrthancPluginLogError(context, message.c_str()); \ - return OrthancPluginErrorCode_DatabasePlugin; \ - } \ - catch (...) \ - { \ - OrthancPluginLogError(context, "Native exception"); \ - return OrthancPluginErrorCode_DatabasePlugin; \ - } - - - -namespace OrthancDatabases -{ - class Output : public IDatabaseBackendOutput - { - private: - struct Metadata - { - int32_t metadata; - const char* value; - }; - - _OrthancPluginDatabaseAnswerType answerType_; - std::list<std::string> stringsStore_; - - std::vector<OrthancPluginAttachment> attachments_; - std::vector<OrthancPluginChange> changes_; - std::vector<OrthancPluginDicomTag> tags_; - std::vector<OrthancPluginExportedResource> exported_; - std::vector<OrthancPluginDatabaseEvent> events_; - std::vector<int32_t> integers32_; - std::vector<int64_t> integers64_; - std::vector<OrthancPluginMatchingResource> matches_; - std::vector<Metadata> metadata_; - std::vector<std::string> stringAnswers_; - - const char* StoreString(const std::string& s) - { - stringsStore_.push_back(s); - return stringsStore_.back().c_str(); - } - - void SetupAnswerType(_OrthancPluginDatabaseAnswerType type) - { - if (answerType_ == _OrthancPluginDatabaseAnswerType_None) - { - answerType_ = type; - } - else if (answerType_ != type) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - public: - Output() : - answerType_(_OrthancPluginDatabaseAnswerType_None) - { - } - - void Clear() - { - // We don't systematically clear all the vectors, in order to - // avoid spending unnecessary time - - switch (answerType_) - { - case _OrthancPluginDatabaseAnswerType_None: - break; - - case _OrthancPluginDatabaseAnswerType_Attachment: - attachments_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_Change: - changes_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_DicomTag: - tags_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_ExportedResource: - exported_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_Int32: - integers32_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_Int64: - integers64_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_MatchingResource: - matches_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_Metadata: - metadata_.clear(); - break; - - case _OrthancPluginDatabaseAnswerType_String: - stringAnswers_.clear(); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - answerType_ = _OrthancPluginDatabaseAnswerType_None; - stringsStore_.clear(); - events_.clear(); - - assert(attachments_.empty()); - assert(changes_.empty()); - assert(tags_.empty()); - assert(exported_.empty()); - assert(events_.empty()); - assert(integers32_.empty()); - assert(integers64_.empty()); - assert(matches_.empty()); - assert(metadata_.empty()); - assert(stringAnswers_.empty()); - } - - - OrthancPluginErrorCode ReadAnswersCount(uint32_t& target) const - { - switch (answerType_) - { - case _OrthancPluginDatabaseAnswerType_None: - target = static_cast<uint32_t>(0); - break; - - case _OrthancPluginDatabaseAnswerType_Attachment: - target = static_cast<uint32_t>(attachments_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_Change: - target = static_cast<uint32_t>(changes_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_DicomTag: - target = static_cast<uint32_t>(tags_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_ExportedResource: - target = static_cast<uint32_t>(exported_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_Int32: - target = static_cast<uint32_t>(integers32_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_Int64: - target = static_cast<uint32_t>(integers64_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_MatchingResource: - target = static_cast<uint32_t>(matches_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_Metadata: - target = static_cast<uint32_t>(metadata_.size()); - break; - - case _OrthancPluginDatabaseAnswerType_String: - target = static_cast<uint32_t>(stringAnswers_.size()); - break; - - default: - return OrthancPluginErrorCode_InternalError; - } - - return OrthancPluginErrorCode_Success; - } - - - OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginAttachment& target /* out */, - uint32_t index) const - { - if (index < attachments_.size()) - { - target = attachments_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerChange(OrthancPluginChange& target /* out */, - uint32_t index) const - { - if (index < changes_.size()) - { - target = changes_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerDicomTag(uint16_t& group, - uint16_t& element, - const char*& value, - uint32_t index) const - { - if (index < tags_.size()) - { - const OrthancPluginDicomTag& tag = tags_[index]; - group = tag.group; - element = tag.element; - value = tag.value; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginExportedResource& target /* out */, - uint32_t index) const - { - if (index < exported_.size()) - { - target = exported_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerInt32(int32_t& target, - uint32_t index) const - { - if (index < integers32_.size()) - { - target = integers32_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerInt64(int64_t& target, - uint32_t index) const - { - if (index < integers64_.size()) - { - target = integers64_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginMatchingResource& target, - uint32_t index) const - { - if (index < matches_.size()) - { - target = matches_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerMetadata(int32_t& metadata, - const char*& value, - uint32_t index) const - { - if (index < metadata_.size()) - { - const Metadata& tmp = metadata_[index]; - metadata = tmp.metadata; - value = tmp.value; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadAnswerString(const char*& target, - uint32_t index) const - { - if (index < stringAnswers_.size()) - { - target = stringAnswers_[index].c_str(); - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - OrthancPluginErrorCode ReadEventsCount(uint32_t& target /* out */) const - { - target = static_cast<uint32_t>(events_.size()); - return OrthancPluginErrorCode_Success; - } - - - OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseEvent& event /* out */, - uint32_t index) const - { - if (index < events_.size()) - { - event = events_[index]; - return OrthancPluginErrorCode_Success; - } - else - { - return OrthancPluginErrorCode_ParameterOutOfRange; - } - } - - - virtual 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) ORTHANC_OVERRIDE - { - OrthancPluginDatabaseEvent event; - event.type = OrthancPluginDatabaseEventType_DeletedAttachment; - event.content.attachment.uuid = StoreString(uuid); - event.content.attachment.contentType = contentType; - event.content.attachment.uncompressedSize = uncompressedSize; - event.content.attachment.uncompressedHash = StoreString(uncompressedHash); - event.content.attachment.compressionType = compressionType; - event.content.attachment.compressedSize = compressedSize; - event.content.attachment.compressedHash = StoreString(compressedHash); - - events_.push_back(event); - } - - - virtual void SignalDeletedResource(const std::string& publicId, - OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE - { - OrthancPluginDatabaseEvent event; - event.type = OrthancPluginDatabaseEventType_DeletedResource; - event.content.resource.level = resourceType; - event.content.resource.publicId = StoreString(publicId); - - events_.push_back(event); - } - - - virtual void SignalRemainingAncestor(const std::string& ancestorId, - OrthancPluginResourceType ancestorType) ORTHANC_OVERRIDE - { - OrthancPluginDatabaseEvent event; - event.type = OrthancPluginDatabaseEventType_RemainingAncestor; - event.content.resource.level = ancestorType; - event.content.resource.publicId = StoreString(ancestorId); - - events_.push_back(event); - } - - - virtual 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) ORTHANC_OVERRIDE - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_Attachment); - - OrthancPluginAttachment attachment; - attachment.uuid = StoreString(uuid); - attachment.contentType = contentType; - attachment.uncompressedSize = uncompressedSize; - attachment.uncompressedHash = StoreString(uncompressedHash); - attachment.compressionType = compressionType; - attachment.compressedSize = compressedSize; - attachment.compressedHash = StoreString(compressedHash); - - attachments_.push_back(attachment); - } - - - virtual void AnswerChange(int64_t seq, - int32_t changeType, - OrthancPluginResourceType resourceType, - const std::string& publicId, - const std::string& date) ORTHANC_OVERRIDE - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_Change); - - OrthancPluginChange change; - change.seq = seq; - change.changeType = changeType; - change.resourceType = resourceType; - change.publicId = StoreString(publicId); - change.date = StoreString(date); - - changes_.push_back(change); - } - - - virtual void AnswerDicomTag(uint16_t group, - uint16_t element, - const std::string& value) ORTHANC_OVERRIDE - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_DicomTag); - - OrthancPluginDicomTag tag; - tag.group = group; - tag.element = element; - tag.value = StoreString(value); - - tags_.push_back(tag); - } - - - virtual 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) ORTHANC_OVERRIDE - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_ExportedResource); - - OrthancPluginExportedResource exported; - exported.seq = seq; - exported.resourceType = resourceType; - exported.publicId = StoreString(publicId); - exported.modality = StoreString(modality); - exported.date = StoreString(date); - exported.patientId = StoreString(patientId); - exported.studyInstanceUid = StoreString(studyInstanceUid); - exported.seriesInstanceUid = StoreString(seriesInstanceUid); - exported.sopInstanceUid = StoreString(sopInstanceUid); - - exported_.push_back(exported); - } - - - virtual void AnswerMatchingResource(const std::string& resourceId) ORTHANC_OVERRIDE - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_MatchingResource); - - OrthancPluginMatchingResource match; - match.resourceId = StoreString(resourceId); - match.someInstanceId = NULL; - - matches_.push_back(match); - } - - - virtual void AnswerMatchingResource(const std::string& resourceId, - const std::string& someInstanceId) ORTHANC_OVERRIDE - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_MatchingResource); - - OrthancPluginMatchingResource match; - match.resourceId = StoreString(resourceId); - match.someInstanceId = StoreString(someInstanceId); - - matches_.push_back(match); - } - - - void AnswerIntegers32(const std::list<int32_t>& values) - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int32); - - integers32_.reserve(values.size()); - std::copy(std::begin(values), std::end(values), std::back_inserter(integers32_)); - } - - - void AnswerIntegers64(const std::list<int64_t>& values) - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int64); - - integers64_.reserve(values.size()); - std::copy(std::begin(values), std::end(values), std::back_inserter(integers64_)); - } - - - void AnswerInteger64(int64_t value) - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int64); - - integers64_.resize(1); - integers64_[0] = value; - } - - - void AnswerMetadata(int32_t metadata, - const std::string& value) - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_Metadata); - - Metadata tmp; - tmp.metadata = metadata; - tmp.value = StoreString(value); - - metadata_.push_back(tmp); - } - - - void AnswerStrings(const std::list<std::string>& values) - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_String); - - stringAnswers_.reserve(values.size()); - std::copy(std::begin(values), std::end(values), std::back_inserter(stringAnswers_)); - } - - - void AnswerString(const std::string& value) - { - SetupAnswerType(_OrthancPluginDatabaseAnswerType_String); - - if (stringAnswers_.empty()) - { - stringAnswers_.push_back(value); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - }; - - - class Factory : public IDatabaseBackendOutput::IFactory - { - public: - Factory() - { - } - - virtual IDatabaseBackendOutput* CreateOutput() - { - return new Output; - } - }; - - - class Transaction : public boost::noncopyable - { - private: - boost::mutex::scoped_lock lock_; // TODO - REMOVE - IndexBackend& backend_; - std::unique_ptr<Output> output_; - - static boost::mutex& GetMutex() // TODO - REMOVE - { - static boost::mutex mutex_; - return mutex_; - } - - public: - Transaction(IndexBackend& backend) : - lock_(GetMutex()), - backend_(backend), - output_(new Output) - { - } - - ~Transaction() - { - } - - IndexBackend& GetBackend() const - { - return backend_; - } - - Output& GetOutput() const - { - return *output_; - } - - OrthancPluginContext* GetContext() const - { - return backend_.GetContext(); - } - }; - - - static OrthancPluginErrorCode ReadAnswersCount(OrthancPluginDatabaseTransaction* transaction, - uint32_t* target /* out */) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswersCount(*target); - } - - - static OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginAttachment* target /* out */, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerAttachment(*target, index); - } - - - static OrthancPluginErrorCode ReadAnswerChange(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginChange* target /* out */, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerChange(*target, index); - } - - - static OrthancPluginErrorCode ReadAnswerDicomTag(OrthancPluginDatabaseTransaction* transaction, - uint16_t* group, - uint16_t* element, - const char** value, - uint32_t index) - { - assert(group != NULL); - assert(element != NULL); - assert(value != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerDicomTag(*group, *element, *value, index); - } - - - static OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginExportedResource* target /* out */, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerExportedResource(*target, index); - } - - - static OrthancPluginErrorCode ReadAnswerInt32(OrthancPluginDatabaseTransaction* transaction, - int32_t* target, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerInt32(*target, index); - } - - - static OrthancPluginErrorCode ReadAnswerInt64(OrthancPluginDatabaseTransaction* transaction, - int64_t* target, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerInt64(*target, index); - } - - - static OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginMatchingResource* target, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerMatchingResource(*target, index); - } - - - static OrthancPluginErrorCode ReadAnswerMetadata(OrthancPluginDatabaseTransaction* transaction, - int32_t* metadata, - const char** value, - uint32_t index) - { - assert(metadata != NULL); - assert(value != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerMetadata(*metadata, *value, index); - } - - - static OrthancPluginErrorCode ReadAnswerString(OrthancPluginDatabaseTransaction* transaction, - const char** target, - uint32_t index) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadAnswerString(*target, index); - } - - - static OrthancPluginErrorCode ReadEventsCount(OrthancPluginDatabaseTransaction* transaction, - uint32_t* target /* out */) - { - assert(target != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadEventsCount(*target); - } - - - static OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginDatabaseEvent* event /* out */, - uint32_t index) - { - assert(event != NULL); - const Transaction& that = *reinterpret_cast<const Transaction*>(transaction); - return that.GetOutput().ReadEvent(*event, index); - } - - - static OrthancPluginErrorCode Open(void* database) - { - IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); - - try - { - backend->Open(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); - } - - - static OrthancPluginErrorCode Close(void* database) - { - IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); - - try - { - backend->Close(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); - } - - - static OrthancPluginErrorCode DestructDatabase(void* database) - { - // Nothing to delete, as this plugin uses a singleton to store backend - if (database == NULL) - { - return OrthancPluginErrorCode_InternalError; - } - else - { - return OrthancPluginErrorCode_Success; - } - } - - - static OrthancPluginErrorCode GetDatabaseVersion(void* database, - uint32_t* version) - { - IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); - - try - { - *version = backend->GetDatabaseVersion(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); - } - - - static OrthancPluginErrorCode UpgradeDatabase(void* database, - OrthancPluginStorageArea* storageArea, - uint32_t targetVersion) - { - IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); - - try - { - backend->UpgradeDatabase(targetVersion, storageArea); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); - } - - - static OrthancPluginErrorCode StartTransaction(void* database, - OrthancPluginDatabaseTransaction** target /* out */, - OrthancPluginDatabaseTransactionType type) - { - IndexBackend* backend = reinterpret_cast<IndexBackend*>(database); - - try - { - std::unique_ptr<Transaction> transaction(new Transaction(*backend)); - - switch (type) - { - case OrthancPluginDatabaseTransactionType_ReadOnly: - backend->StartTransaction(TransactionType_ReadOnly); - break; - - case OrthancPluginDatabaseTransactionType_ReadWrite: - backend->StartTransaction(TransactionType_ReadWrite); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - *target = reinterpret_cast<OrthancPluginDatabaseTransaction*>(transaction.release()); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext()); - } - - - static OrthancPluginErrorCode DestructTransaction(OrthancPluginDatabaseTransaction* transaction) - { - if (transaction == NULL) - { - return OrthancPluginErrorCode_NullPointer; - } - else - { - delete reinterpret_cast<Transaction*>(transaction); - return OrthancPluginErrorCode_Success; - } - } - - - static OrthancPluginErrorCode Rollback(OrthancPluginDatabaseTransaction* transaction) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().RollbackTransaction(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode Commit(OrthancPluginDatabaseTransaction* transaction, - int64_t fileSizeDelta /* TODO - not used? */) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().CommitTransaction(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode AddAttachment(OrthancPluginDatabaseTransaction* transaction, - int64_t id, - const OrthancPluginAttachment* attachment) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().AddAttachment(id, *attachment); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode ClearChanges(OrthancPluginDatabaseTransaction* transaction) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().ClearChanges(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode ClearExportedResources(OrthancPluginDatabaseTransaction* transaction) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().ClearExportedResources(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode ClearMainDicomTags(OrthancPluginDatabaseTransaction* transaction, - int64_t resourceId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().ClearMainDicomTags(resourceId); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode CreateInstance(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginCreateInstanceResult* target /* out */, - const char* hashPatient, - const char* hashStudy, - const char* hashSeries, - const char* hashInstance) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - if (t->GetBackend().HasCreateInstance()) - { - t->GetBackend().CreateInstance(*target, hashPatient, hashStudy, hashSeries, hashInstance); - } - else - { - t->GetBackend().CreateInstanceGeneric(*target, hashPatient, hashStudy, hashSeries, hashInstance); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode DeleteAttachment(OrthancPluginDatabaseTransaction* transaction, - int64_t id, - int32_t contentType) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().DeleteAttachment(t->GetOutput(), id, contentType); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode DeleteMetadata(OrthancPluginDatabaseTransaction* transaction, - int64_t id, - int32_t metadataType) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().DeleteMetadata(id, metadataType); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode DeleteResource(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().DeleteResource(t->GetOutput(), id); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::map<int32_t, std::string> values; - t->GetBackend().GetAllMetadata(values, id); - - for (std::map<int32_t, std::string>::const_iterator it = values.begin(); it != values.end(); ++it) - { - t->GetOutput().AnswerMetadata(it->first, it->second); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetAllPublicIds(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginResourceType resourceType) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::list<std::string> values; - t->GetBackend().GetAllPublicIds(values, resourceType); - t->GetOutput().AnswerStrings(values); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetAllPublicIdsWithLimit(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginResourceType resourceType, - uint64_t since, - uint64_t limit) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::list<std::string> values; - t->GetBackend().GetAllPublicIds(values, resourceType, since, limit); - t->GetOutput().AnswerStrings(values); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetChanges(OrthancPluginDatabaseTransaction* transaction, - uint8_t* targetDone /* out */, - int64_t since, - uint32_t maxResults) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - bool done; - t->GetBackend().GetChanges(t->GetOutput(), done, since, maxResults); - *targetDone = (done ? 1 : 0); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetChildrenInternalId(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::list<int64_t> values; - t->GetBackend().GetChildrenInternalId(values, id); - t->GetOutput().AnswerIntegers64(values); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetChildrenMetadata(OrthancPluginDatabaseTransaction* transaction, - int64_t resourceId, - int32_t metadata) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::list<std::string> values; - t->GetBackend().GetChildrenMetadata(values, resourceId, metadata); - t->GetOutput().AnswerStrings(values); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetChildrenPublicId(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::list<std::string> values; - t->GetBackend().GetChildrenPublicId(values, id); - t->GetOutput().AnswerStrings(values); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetExportedResources(OrthancPluginDatabaseTransaction* transaction, - uint8_t* targetDone /* out */, - int64_t since, - uint32_t maxResults) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - bool done; - t->GetBackend().GetExportedResources(t->GetOutput(), done, since, maxResults); - *targetDone = (done ? 1 : 0); - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetLastChange(OrthancPluginDatabaseTransaction* transaction) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().GetLastChange(t->GetOutput()); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetLastChangeIndex(OrthancPluginDatabaseTransaction* transaction, - int64_t* target) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - *target = t->GetBackend().GetLastChangeIndex(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetLastExportedResource(OrthancPluginDatabaseTransaction* transaction) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().GetLastExportedResource(t->GetOutput()); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetMainDicomTags(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().GetMainDicomTags(t->GetOutput(), id); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetPublicId(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetOutput().AnswerString(t->GetBackend().GetPublicId(id)); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetResourcesCount(OrthancPluginDatabaseTransaction* transaction, - uint64_t* target /* out */, - OrthancPluginResourceType resourceType) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - *target = t->GetBackend().GetResourcesCount(resourceType); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetResourceType(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginResourceType* target /* out */, - uint64_t resourceId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - *target = t->GetBackend().GetResourceType(resourceId); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetTotalCompressedSize(OrthancPluginDatabaseTransaction* transaction, - uint64_t* target /* out */) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - *target = t->GetBackend().GetTotalCompressedSize(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode GetTotalUncompressedSize(OrthancPluginDatabaseTransaction* transaction, - uint64_t* target /* out */) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - *target = t->GetBackend().GetTotalUncompressedSize(); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode IsDiskSizeAbove(OrthancPluginDatabaseTransaction* transaction, - uint8_t* target, - uint64_t threshold) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - bool above = (t->GetBackend().GetTotalCompressedSize() >= threshold); - *target = (above ? 1 : 0); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode IsExistingResource(OrthancPluginDatabaseTransaction* transaction, - uint8_t* target, - int64_t resourceId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - bool exists = t->GetBackend().IsExistingResource(resourceId); - *target = (exists ? 1 : 0); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode IsProtectedPatient(OrthancPluginDatabaseTransaction* transaction, - uint8_t* target, - int64_t resourceId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - bool isProtected = t->GetBackend().IsProtectedPatient(resourceId); - *target = (isProtected ? 1 : 0); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode ListAvailableAttachments(OrthancPluginDatabaseTransaction* transaction, - int64_t resourceId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::list<int32_t> values; - t->GetBackend().ListAvailableAttachments(values, resourceId); - t->GetOutput().AnswerIntegers32(values); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LogChange(OrthancPluginDatabaseTransaction* transaction, - int32_t changeType, - int64_t resourceId, - OrthancPluginResourceType resourceType, - const char* date) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().LogChange(changeType, resourceId, resourceType, date); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LogExportedResource(OrthancPluginDatabaseTransaction* transaction, - OrthancPluginResourceType resourceType, - const char* publicId, - const char* modality, - const char* date, - const char* patientId, - const char* studyInstanceUid, - const char* seriesInstanceUid, - const char* sopInstanceUid) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - OrthancPluginExportedResource exported; - exported.seq = 0; - exported.resourceType = resourceType; - exported.publicId = publicId; - exported.modality = modality; - exported.date = date; - exported.patientId = patientId; - exported.studyInstanceUid = studyInstanceUid; - exported.seriesInstanceUid = seriesInstanceUid; - exported.sopInstanceUid = sopInstanceUid; - - t->GetOutput().Clear(); - t->GetBackend().LogExportedResource(exported); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupAttachment(OrthancPluginDatabaseTransaction* transaction, - int64_t resourceId, - int32_t contentType) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().LookupAttachment(t->GetOutput(), resourceId, contentType); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupGlobalProperty(OrthancPluginDatabaseTransaction* transaction, - int32_t property) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::string s; - if (t->GetBackend().LookupGlobalProperty(s, property)) - { - t->GetOutput().AnswerString(s); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseTransaction* transaction, - int64_t id, - int32_t metadata) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::string s; - if (t->GetBackend().LookupMetadata(s, id, metadata)) - { - t->GetOutput().AnswerString(s); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupParent(OrthancPluginDatabaseTransaction* transaction, - int64_t id) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - int64_t parentId; - if (t->GetBackend().LookupParent(parentId, id)) - { - t->GetOutput().AnswerInteger64(parentId); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupResource(OrthancPluginDatabaseTransaction* transaction, - uint8_t* isExisting /* out */, - int64_t* id /* out */, - OrthancPluginResourceType* type /* out */, - const char* publicId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - if (t->GetBackend().LookupResource(*id, *type, publicId)) - { - *isExisting = 1; - } - else - { - *isExisting = 0; - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupResources(OrthancPluginDatabaseTransaction* transaction, - uint32_t constraintsCount, - const OrthancPluginDatabaseConstraint* constraints, - OrthancPluginResourceType queryLevel, - uint32_t limit, - uint8_t requestSomeInstanceId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::vector<Orthanc::DatabaseConstraint> lookup; - lookup.reserve(constraintsCount); - - for (uint32_t i = 0; i < constraintsCount; i++) - { - lookup.push_back(Orthanc::DatabaseConstraint(constraints[i])); - } - - t->GetBackend().LookupResources(t->GetOutput(), lookup, queryLevel, limit, (requestSomeInstanceId != 0)); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseTransaction* transaction, - uint8_t* isExisting /* out */, - int64_t* id /* out */, - OrthancPluginResourceType* type /* out */, - const char* publicId) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - std::string parent; - if (t->GetBackend().LookupResourceAndParent(*id, *type, parent, publicId)) - { - *isExisting = 1; - - if (!parent.empty()) - { - t->GetOutput().AnswerString(parent); - } - } - else - { - *isExisting = 0; - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode SelectPatientToRecycle(OrthancPluginDatabaseTransaction* transaction) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - int64_t id; - if (t->GetBackend().SelectPatientToRecycle(id)) - { - t->GetOutput().AnswerInteger64(id); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode SelectPatientToRecycle2(OrthancPluginDatabaseTransaction* transaction, - int64_t patientIdToAvoid) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - - int64_t id; - if (t->GetBackend().SelectPatientToRecycle(id, patientIdToAvoid)) - { - t->GetOutput().AnswerInteger64(id); - } - - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode SetGlobalProperty(OrthancPluginDatabaseTransaction* transaction, - int32_t property, - const char* value) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().SetGlobalProperty(property, value); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode SetMetadata(OrthancPluginDatabaseTransaction* transaction, - int64_t id, - int32_t metadata, - const char* value) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().SetMetadata(id, metadata, value); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode SetProtectedPatient(OrthancPluginDatabaseTransaction* transaction, - int64_t id, - uint8_t isProtected) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().SetProtectedPatient(id, (isProtected != 0)); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static OrthancPluginErrorCode SetResourcesContent(OrthancPluginDatabaseTransaction* transaction, - uint32_t countIdentifierTags, - const OrthancPluginResourcesContentTags* identifierTags, - uint32_t countMainDicomTags, - const OrthancPluginResourcesContentTags* mainDicomTags, - uint32_t countMetadata, - const OrthancPluginResourcesContentMetadata* metadata) - { - Transaction* t = reinterpret_cast<Transaction*>(transaction); - - try - { - t->GetOutput().Clear(); - t->GetBackend().SetResourcesContent(countIdentifierTags, identifierTags, - countMainDicomTags, mainDicomTags, - countMetadata, metadata); - return OrthancPluginErrorCode_Success; - } - ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext()); - } - - - static void RegisterV3(IndexBackend& database) - { - OrthancPluginDatabaseBackendV3 params; - memset(¶ms, 0, sizeof(params)); - - params.readAnswersCount = ReadAnswersCount; - params.readAnswerAttachment = ReadAnswerAttachment; - params.readAnswerChange = ReadAnswerChange; - params.readAnswerDicomTag = ReadAnswerDicomTag; - params.readAnswerExportedResource = ReadAnswerExportedResource; - params.readAnswerInt32 = ReadAnswerInt32; - params.readAnswerInt64 = ReadAnswerInt64; - params.readAnswerMatchingResource = ReadAnswerMatchingResource; - params.readAnswerMetadata = ReadAnswerMetadata; - params.readAnswerString = ReadAnswerString; - - params.readEventsCount = ReadEventsCount; - params.readEvent = ReadEvent; - - params.open = Open; - params.close = Close; - params.destructDatabase = DestructDatabase; - params.getDatabaseVersion = GetDatabaseVersion; - params.upgradeDatabase = UpgradeDatabase; - params.startTransaction = StartTransaction; - params.destructTransaction = DestructTransaction; - params.rollback = Rollback; - params.commit = Commit; - - params.addAttachment = AddAttachment; - params.clearChanges = ClearChanges; - params.clearExportedResources = ClearExportedResources; - params.clearMainDicomTags = ClearMainDicomTags; - params.createInstance = CreateInstance; - params.deleteAttachment = DeleteAttachment; - params.deleteMetadata = DeleteMetadata; - params.deleteResource = DeleteResource; - params.getAllMetadata = GetAllMetadata; - params.getAllPublicIds = GetAllPublicIds; - params.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit; - params.getChanges = GetChanges; - params.getChildrenInternalId = GetChildrenInternalId; - params.getChildrenMetadata = GetChildrenMetadata; - params.getChildrenPublicId = GetChildrenPublicId; - params.getExportedResources = GetExportedResources; - params.getLastChange = GetLastChange; - params.getLastChangeIndex = GetLastChangeIndex; - params.getLastExportedResource = GetLastExportedResource; - params.getMainDicomTags = GetMainDicomTags; - params.getPublicId = GetPublicId; - params.getResourcesCount = GetResourcesCount; - params.getResourceType = GetResourceType; - params.getTotalCompressedSize = GetTotalCompressedSize; - params.getTotalUncompressedSize = GetTotalUncompressedSize; - params.isDiskSizeAbove = IsDiskSizeAbove; - params.isExistingResource = IsExistingResource; - params.isProtectedPatient = IsProtectedPatient; - params.listAvailableAttachments = ListAvailableAttachments; - params.logChange = LogChange; - params.logExportedResource = LogExportedResource; - params.lookupAttachment = LookupAttachment; - params.lookupGlobalProperty = LookupGlobalProperty; - params.lookupMetadata = LookupMetadata; - params.lookupParent = LookupParent; - params.lookupResource = LookupResource; - params.lookupResources = LookupResources; - params.lookupResourceAndParent = LookupResourceAndParent; - params.selectPatientToRecycle = SelectPatientToRecycle; - params.selectPatientToRecycle2 = SelectPatientToRecycle2; - params.setGlobalProperty = SetGlobalProperty; - params.setMetadata = SetMetadata; - params.setProtectedPatient = SetProtectedPatient; - params.setResourcesContent = SetResourcesContent; - - OrthancPluginContext* context = database.GetContext(); - - if (OrthancPluginRegisterDatabaseBackendV3(context, ¶ms, sizeof(params), &database) != OrthancPluginErrorCode_Success) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend"); - } - - database.SetOutputFactory(new Factory); - } -} - -# endif -#endif - - - extern "C" { ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) @@ -1895,7 +73,7 @@ # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) if (OrthancPluginCheckVersionAdvanced(context, 1, 9, 2) == 1) { - RegisterV3(*backend_); + OrthancDatabases::DatabaseBackendAdapterV3::Register(*backend_); hasLoadedV3 = true; } # endif