Mercurial > hg > orthanc
view Plugins/Engine/OrthancPluginDatabase.cpp @ 1664:0c58f189782d db-changes
prepare migration to db v6
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 30 Sep 2015 13:43:20 +0200 |
parents | 2e692c83e2f3 |
children | de1413733c97 |
line wrap: on
line source
/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * In addition, as a special exception, the copyright holders of this * program give permission to link the code of its release with the * OpenSSL project's "OpenSSL" library (or with modified versions of it * that use the same license as the "OpenSSL" library), and distribute * the linked executables. You must obey the GNU General Public License * in all respects for all of the code used other than "OpenSSL". If you * modify file(s) with this exception, you may extend this exception to * your version of the file(s), but you are not obligated to do so. If * you do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source files * in the program, then also delete it here. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ #include "../../OrthancServer/PrecompiledHeadersServer.h" #include "OrthancPluginDatabase.h" #if ORTHANC_PLUGINS_ENABLED != 1 #error The plugin support is disabled #endif #include "../../Core/OrthancException.h" #include "../../Core/Logging.h" #include "PluginsEnumerations.h" #include <cassert> namespace Orthanc { static OrthancPluginResourceType Convert(ResourceType type) { switch (type) { case ResourceType_Patient: return OrthancPluginResourceType_Patient; case ResourceType_Study: return OrthancPluginResourceType_Study; case ResourceType_Series: return OrthancPluginResourceType_Series; case ResourceType_Instance: return OrthancPluginResourceType_Instance; default: throw OrthancException(ErrorCode_InternalError); } } static ResourceType Convert(OrthancPluginResourceType type) { switch (type) { case OrthancPluginResourceType_Patient: return ResourceType_Patient; case OrthancPluginResourceType_Study: return ResourceType_Study; case OrthancPluginResourceType_Series: return ResourceType_Series; case OrthancPluginResourceType_Instance: return ResourceType_Instance; default: throw OrthancException(ErrorCode_InternalError); } } static FileInfo Convert(const OrthancPluginAttachment& attachment) { return FileInfo(attachment.uuid, static_cast<FileContentType>(attachment.contentType), attachment.uncompressedSize, attachment.uncompressedHash, static_cast<CompressionType>(attachment.compressionType), attachment.compressedSize, attachment.compressedHash); } void OrthancPluginDatabase::ResetAnswers() { type_ = _OrthancPluginDatabaseAnswerType_None; answerDicomMap_ = NULL; answerChanges_ = NULL; answerExportedResources_ = NULL; answerDone_ = NULL; } void OrthancPluginDatabase::ForwardAnswers(std::list<int64_t>& target) { if (type_ != _OrthancPluginDatabaseAnswerType_None && type_ != _OrthancPluginDatabaseAnswerType_Int64) { throw OrthancException(ErrorCode_DatabasePlugin); } target.clear(); if (type_ == _OrthancPluginDatabaseAnswerType_Int64) { for (std::list<int64_t>::const_iterator it = answerInt64_.begin(); it != answerInt64_.end(); ++it) { target.push_back(*it); } } } void OrthancPluginDatabase::ForwardAnswers(std::list<std::string>& target) { if (type_ != _OrthancPluginDatabaseAnswerType_None && type_ != _OrthancPluginDatabaseAnswerType_String) { throw OrthancException(ErrorCode_DatabasePlugin); } target.clear(); if (type_ == _OrthancPluginDatabaseAnswerType_String) { for (std::list<std::string>::const_iterator it = answerStrings_.begin(); it != answerStrings_.end(); ++it) { target.push_back(*it); } } } bool OrthancPluginDatabase::ForwardSingleAnswer(std::string& target) { if (type_ == _OrthancPluginDatabaseAnswerType_None) { return false; } else if (type_ == _OrthancPluginDatabaseAnswerType_String && answerStrings_.size() == 1) { target = answerStrings_.front(); return true; } else { throw OrthancException(ErrorCode_DatabasePlugin); } } bool OrthancPluginDatabase::ForwardSingleAnswer(int64_t& target) { if (type_ == _OrthancPluginDatabaseAnswerType_None) { return false; } else if (type_ == _OrthancPluginDatabaseAnswerType_Int64 && answerInt64_.size() == 1) { target = answerInt64_.front(); return true; } else { throw OrthancException(ErrorCode_DatabasePlugin); } } OrthancPluginDatabase::OrthancPluginDatabase(SharedLibrary& library, PluginsErrorDictionary& errorDictionary, const OrthancPluginDatabaseBackend& backend, const OrthancPluginDatabaseExtensions* extensions, size_t extensionsSize, void *payload) : library_(library), errorDictionary_(errorDictionary), type_(_OrthancPluginDatabaseAnswerType_None), backend_(backend), payload_(payload), listener_(NULL), answerDicomMap_(NULL), answerChanges_(NULL), answerExportedResources_(NULL), answerDone_(NULL) { memset(&extensions_, 0, sizeof(extensions_)); size_t size = sizeof(extensions_); if (extensionsSize < size) { size = extensionsSize; // Not all the extensions are available } memcpy(&extensions_, extensions, size); } void OrthancPluginDatabase::AddAttachment(int64_t id, const FileInfo& attachment) { OrthancPluginAttachment tmp; tmp.uuid = attachment.GetUuid().c_str(); tmp.contentType = static_cast<int32_t>(attachment.GetContentType()); tmp.uncompressedSize = attachment.GetUncompressedSize(); tmp.uncompressedHash = attachment.GetUncompressedMD5().c_str(); tmp.compressionType = static_cast<int32_t>(attachment.GetCompressionType()); tmp.compressedSize = attachment.GetCompressedSize(); tmp.compressedHash = attachment.GetCompressedMD5().c_str(); OrthancPluginErrorCode error = backend_.addAttachment(payload_, id, &tmp); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::AttachChild(int64_t parent, int64_t child) { OrthancPluginErrorCode error = backend_.attachChild(payload_, parent, child); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::ClearChanges() { OrthancPluginErrorCode error = backend_.clearChanges(payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::ClearExportedResources() { OrthancPluginErrorCode error = backend_.clearExportedResources(payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } int64_t OrthancPluginDatabase::CreateResource(const std::string& publicId, ResourceType type) { int64_t id; OrthancPluginErrorCode error = backend_.createResource(&id, payload_, publicId.c_str(), Convert(type)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return id; } void OrthancPluginDatabase::DeleteAttachment(int64_t id, FileContentType attachment) { OrthancPluginErrorCode error = backend_.deleteAttachment(payload_, id, static_cast<int32_t>(attachment)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::DeleteMetadata(int64_t id, MetadataType type) { OrthancPluginErrorCode error = backend_.deleteMetadata(payload_, id, static_cast<int32_t>(type)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::DeleteResource(int64_t id) { OrthancPluginErrorCode error = backend_.deleteResource(payload_, id); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::GetAllMetadata(std::map<MetadataType, std::string>& target, int64_t id) { std::list<MetadataType> metadata; ListAvailableMetadata(metadata, id); target.clear(); for (std::list<MetadataType>::const_iterator it = metadata.begin(); it != metadata.end(); ++it) { std::string value; if (!LookupMetadata(value, id, *it)) { throw OrthancException(ErrorCode_DatabasePlugin); } target[*it] = value; } } void OrthancPluginDatabase::GetAllPublicIds(std::list<std::string>& target, ResourceType resourceType) { ResetAnswers(); OrthancPluginErrorCode error = backend_.getAllPublicIds(GetContext(), payload_, Convert(resourceType)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } ForwardAnswers(target); } void OrthancPluginDatabase::GetAllPublicIds(std::list<std::string>& target, ResourceType resourceType, size_t since, size_t limit) { if (extensions_.getAllPublicIdsWithLimit != NULL) { // This extension is available since Orthanc 0.9.4 ResetAnswers(); OrthancPluginErrorCode error = extensions_.getAllPublicIdsWithLimit (GetContext(), payload_, Convert(resourceType), since, limit); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } ForwardAnswers(target); } else { // The extension is not available in the database plugin, use a // fallback implementation target.clear(); if (limit == 0) { return; } std::list<std::string> tmp; GetAllPublicIds(tmp, resourceType); if (tmp.size() <= since) { // Not enough results => empty answer return; } std::list<std::string>::iterator current = tmp.begin(); std::advance(current, since); while (limit > 0 && current != tmp.end()) { target.push_back(*current); --limit; ++current; } } } void OrthancPluginDatabase::GetChanges(std::list<ServerIndexChange>& target /*out*/, bool& done /*out*/, int64_t since, uint32_t maxResults) { ResetAnswers(); answerChanges_ = ⌖ answerDone_ = &done; done = false; OrthancPluginErrorCode error = backend_.getChanges(GetContext(), payload_, since, maxResults); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::GetChildrenInternalId(std::list<int64_t>& target, int64_t id) { ResetAnswers(); OrthancPluginErrorCode error = backend_.getChildrenInternalId(GetContext(), payload_, id); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } ForwardAnswers(target); } void OrthancPluginDatabase::GetChildrenPublicId(std::list<std::string>& target, int64_t id) { ResetAnswers(); OrthancPluginErrorCode error = backend_.getChildrenPublicId(GetContext(), payload_, id); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } ForwardAnswers(target); } void OrthancPluginDatabase::GetExportedResources(std::list<ExportedResource>& target /*out*/, bool& done /*out*/, int64_t since, uint32_t maxResults) { ResetAnswers(); answerExportedResources_ = ⌖ answerDone_ = &done; done = false; OrthancPluginErrorCode error = backend_.getExportedResources(GetContext(), payload_, since, maxResults); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::GetLastChange(std::list<ServerIndexChange>& target /*out*/) { bool ignored = false; ResetAnswers(); answerChanges_ = ⌖ answerDone_ = &ignored; OrthancPluginErrorCode error = backend_.getLastChange(GetContext(), payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::GetLastExportedResource(std::list<ExportedResource>& target /*out*/) { bool ignored = false; ResetAnswers(); answerExportedResources_ = ⌖ answerDone_ = &ignored; OrthancPluginErrorCode error = backend_.getLastExportedResource(GetContext(), payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::GetMainDicomTags(DicomMap& map, int64_t id) { ResetAnswers(); answerDicomMap_ = ↦ OrthancPluginErrorCode error = backend_.getMainDicomTags(GetContext(), payload_, id); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } std::string OrthancPluginDatabase::GetPublicId(int64_t resourceId) { ResetAnswers(); std::string s; OrthancPluginErrorCode error = backend_.getPublicId(GetContext(), payload_, resourceId); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } if (!ForwardSingleAnswer(s)) { throw OrthancException(ErrorCode_DatabasePlugin); } return s; } uint64_t OrthancPluginDatabase::GetResourceCount(ResourceType resourceType) { uint64_t count; OrthancPluginErrorCode error = backend_.getResourceCount(&count, payload_, Convert(resourceType)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return count; } ResourceType OrthancPluginDatabase::GetResourceType(int64_t resourceId) { OrthancPluginResourceType type; OrthancPluginErrorCode error = backend_.getResourceType(&type, payload_, resourceId); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return Convert(type); } uint64_t OrthancPluginDatabase::GetTotalCompressedSize() { uint64_t size; OrthancPluginErrorCode error = backend_.getTotalCompressedSize(&size, payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return size; } uint64_t OrthancPluginDatabase::GetTotalUncompressedSize() { uint64_t size; OrthancPluginErrorCode error = backend_.getTotalUncompressedSize(&size, payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return size; } bool OrthancPluginDatabase::IsExistingResource(int64_t internalId) { int32_t existing; OrthancPluginErrorCode error = backend_.isExistingResource(&existing, payload_, internalId); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return (existing != 0); } bool OrthancPluginDatabase::IsProtectedPatient(int64_t internalId) { int32_t isProtected; OrthancPluginErrorCode error = backend_.isProtectedPatient(&isProtected, payload_, internalId); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return (isProtected != 0); } void OrthancPluginDatabase::ListAvailableMetadata(std::list<MetadataType>& target, int64_t id) { ResetAnswers(); OrthancPluginErrorCode error = backend_.listAvailableMetadata(GetContext(), payload_, id); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } if (type_ != _OrthancPluginDatabaseAnswerType_None && type_ != _OrthancPluginDatabaseAnswerType_Int32) { throw OrthancException(ErrorCode_DatabasePlugin); } target.clear(); if (type_ == _OrthancPluginDatabaseAnswerType_Int32) { for (std::list<int32_t>::const_iterator it = answerInt32_.begin(); it != answerInt32_.end(); ++it) { target.push_back(static_cast<MetadataType>(*it)); } } } void OrthancPluginDatabase::ListAvailableAttachments(std::list<FileContentType>& target, int64_t id) { ResetAnswers(); OrthancPluginErrorCode error = backend_.listAvailableAttachments(GetContext(), payload_, id); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } if (type_ != _OrthancPluginDatabaseAnswerType_None && type_ != _OrthancPluginDatabaseAnswerType_Int32) { throw OrthancException(ErrorCode_DatabasePlugin); } target.clear(); if (type_ == _OrthancPluginDatabaseAnswerType_Int32) { for (std::list<int32_t>::const_iterator it = answerInt32_.begin(); it != answerInt32_.end(); ++it) { target.push_back(static_cast<FileContentType>(*it)); } } } void OrthancPluginDatabase::LogChange(int64_t internalId, const ServerIndexChange& change) { OrthancPluginChange tmp; tmp.seq = change.GetSeq(); tmp.changeType = static_cast<int32_t>(change.GetChangeType()); tmp.resourceType = Convert(change.GetResourceType()); tmp.publicId = change.GetPublicId().c_str(); tmp.date = change.GetDate().c_str(); OrthancPluginErrorCode error = backend_.logChange(payload_, &tmp); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::LogExportedResource(const ExportedResource& resource) { OrthancPluginExportedResource tmp; tmp.seq = resource.GetSeq(); tmp.resourceType = Convert(resource.GetResourceType()); tmp.publicId = resource.GetPublicId().c_str(); tmp.modality = resource.GetModality().c_str(); tmp.date = resource.GetDate().c_str(); tmp.patientId = resource.GetPatientId().c_str(); tmp.studyInstanceUid = resource.GetStudyInstanceUid().c_str(); tmp.seriesInstanceUid = resource.GetSeriesInstanceUid().c_str(); tmp.sopInstanceUid = resource.GetSopInstanceUid().c_str(); OrthancPluginErrorCode error = backend_.logExportedResource(payload_, &tmp); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } bool OrthancPluginDatabase::LookupAttachment(FileInfo& attachment, int64_t id, FileContentType contentType) { ResetAnswers(); OrthancPluginErrorCode error = backend_.lookupAttachment (GetContext(), payload_, id, static_cast<int32_t>(contentType)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } if (type_ == _OrthancPluginDatabaseAnswerType_None) { return false; } else if (type_ == _OrthancPluginDatabaseAnswerType_Attachment && answerAttachments_.size() == 1) { attachment = answerAttachments_.front(); return true; } else { throw OrthancException(ErrorCode_DatabasePlugin); } } bool OrthancPluginDatabase::LookupGlobalProperty(std::string& target, GlobalProperty property) { ResetAnswers(); OrthancPluginErrorCode error = backend_.lookupGlobalProperty (GetContext(), payload_, static_cast<int32_t>(property)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return ForwardSingleAnswer(target); } void OrthancPluginDatabase::LookupIdentifier(std::list<int64_t>& target, const DicomTag& tag, const std::string& value) { ResetAnswers(); OrthancPluginDicomTag tmp; tmp.group = tag.GetGroup(); tmp.element = tag.GetElement(); tmp.value = value.c_str(); OrthancPluginErrorCode error = backend_.lookupIdentifier(GetContext(), payload_, &tmp); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } ForwardAnswers(target); } void OrthancPluginDatabase::LookupIdentifier(std::list<int64_t>& target, const std::string& value) { ResetAnswers(); OrthancPluginErrorCode error = backend_.lookupIdentifier2(GetContext(), payload_, value.c_str()); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } ForwardAnswers(target); } bool OrthancPluginDatabase::LookupMetadata(std::string& target, int64_t id, MetadataType type) { ResetAnswers(); OrthancPluginErrorCode error = backend_.lookupMetadata(GetContext(), payload_, id, static_cast<int32_t>(type)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return ForwardSingleAnswer(target); } bool OrthancPluginDatabase::LookupParent(int64_t& parentId, int64_t resourceId) { ResetAnswers(); OrthancPluginErrorCode error = backend_.lookupParent(GetContext(), payload_, resourceId); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return ForwardSingleAnswer(parentId); } bool OrthancPluginDatabase::LookupResource(int64_t& id, ResourceType& type, const std::string& publicId) { ResetAnswers(); OrthancPluginErrorCode error = backend_.lookupResource(GetContext(), payload_, publicId.c_str()); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } if (type_ == _OrthancPluginDatabaseAnswerType_None) { return false; } else if (type_ == _OrthancPluginDatabaseAnswerType_Resource && answerResources_.size() == 1) { id = answerResources_.front().first; type = answerResources_.front().second; return true; } else { throw OrthancException(ErrorCode_DatabasePlugin); } } bool OrthancPluginDatabase::SelectPatientToRecycle(int64_t& internalId) { ResetAnswers(); OrthancPluginErrorCode error = backend_.selectPatientToRecycle(GetContext(), payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return ForwardSingleAnswer(internalId); } bool OrthancPluginDatabase::SelectPatientToRecycle(int64_t& internalId, int64_t patientIdToAvoid) { ResetAnswers(); OrthancPluginErrorCode error = backend_.selectPatientToRecycle2(GetContext(), payload_, patientIdToAvoid); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return ForwardSingleAnswer(internalId); } void OrthancPluginDatabase::SetGlobalProperty(GlobalProperty property, const std::string& value) { OrthancPluginErrorCode error = backend_.setGlobalProperty (payload_, static_cast<int32_t>(property), value.c_str()); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::SetMainDicomTag(int64_t id, const DicomTag& tag, const std::string& value) { OrthancPluginDicomTag tmp; tmp.group = tag.GetGroup(); tmp.element = tag.GetElement(); tmp.value = value.c_str(); OrthancPluginErrorCode error; if (tag.IsIdentifier()) { error = backend_.setIdentifierTag(payload_, id, &tmp); } else { error = backend_.setMainDicomTag(payload_, id, &tmp); } if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::SetMetadata(int64_t id, MetadataType type, const std::string& value) { OrthancPluginErrorCode error = backend_.setMetadata (payload_, id, static_cast<int32_t>(type), value.c_str()); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } void OrthancPluginDatabase::SetProtectedPatient(int64_t internalId, bool isProtected) { OrthancPluginErrorCode error = backend_.setProtectedPatient(payload_, internalId, isProtected); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } class OrthancPluginDatabase::Transaction : public SQLite::ITransaction { private: const OrthancPluginDatabaseBackend& backend_; void* payload_; PluginsErrorDictionary& errorDictionary_; public: Transaction(const OrthancPluginDatabaseBackend& backend, void* payload, PluginsErrorDictionary& errorDictionary) : backend_(backend), payload_(payload), errorDictionary_(errorDictionary) { } virtual void Begin() { OrthancPluginErrorCode error = backend_.startTransaction(payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } virtual void Rollback() { OrthancPluginErrorCode error = backend_.rollbackTransaction(payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } virtual void Commit() { OrthancPluginErrorCode error = backend_.commitTransaction(payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } }; SQLite::ITransaction* OrthancPluginDatabase::StartTransaction() { return new Transaction(backend_, payload_, errorDictionary_); } static void ProcessEvent(IDatabaseListener& listener, const _OrthancPluginDatabaseAnswer& answer) { switch (answer.type) { case _OrthancPluginDatabaseAnswerType_DeletedAttachment: { const OrthancPluginAttachment& attachment = *reinterpret_cast<const OrthancPluginAttachment*>(answer.valueGeneric); listener.SignalFileDeleted(Convert(attachment)); break; } case _OrthancPluginDatabaseAnswerType_RemainingAncestor: { ResourceType type = Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32)); listener.SignalRemainingAncestor(type, answer.valueString); break; } case _OrthancPluginDatabaseAnswerType_DeletedResource: { ResourceType type = Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32)); ServerIndexChange change(ChangeType_Deleted, type, answer.valueString); listener.SignalChange(change); break; } default: throw OrthancException(ErrorCode_DatabasePlugin); } } unsigned int OrthancPluginDatabase::GetDatabaseVersion() { if (extensions_.getDatabaseVersion != NULL) { uint32_t version; OrthancPluginErrorCode error = extensions_.getDatabaseVersion(&version, payload_); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } return version; } else { // Before adding the "GetDatabaseVersion()" extension in plugins // (OrthancPostgreSQL <= 1.2), the only supported DB schema was // version 5. return 5; } } void OrthancPluginDatabase::Upgrade(unsigned int targetVersion, IStorageArea& storageArea) { if (extensions_.upgradeDatabase != NULL) { OrthancPluginErrorCode error = extensions_.upgradeDatabase( payload_, targetVersion, reinterpret_cast<OrthancPluginStorageArea*>(&storageArea)); if (error != OrthancPluginErrorCode_Success) { errorDictionary_.LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } } } void OrthancPluginDatabase::AnswerReceived(const _OrthancPluginDatabaseAnswer& answer) { if (answer.type == _OrthancPluginDatabaseAnswerType_None) { throw OrthancException(ErrorCode_DatabasePlugin); } if (answer.type == _OrthancPluginDatabaseAnswerType_DeletedAttachment || answer.type == _OrthancPluginDatabaseAnswerType_DeletedResource || answer.type == _OrthancPluginDatabaseAnswerType_RemainingAncestor) { assert(listener_ != NULL); ProcessEvent(*listener_, answer); return; } if (type_ == _OrthancPluginDatabaseAnswerType_None) { type_ = answer.type; switch (type_) { case _OrthancPluginDatabaseAnswerType_Int32: answerInt32_.clear(); break; case _OrthancPluginDatabaseAnswerType_Int64: answerInt64_.clear(); break; case _OrthancPluginDatabaseAnswerType_Resource: answerResources_.clear(); break; case _OrthancPluginDatabaseAnswerType_Attachment: answerAttachments_.clear(); break; case _OrthancPluginDatabaseAnswerType_String: answerStrings_.clear(); break; case _OrthancPluginDatabaseAnswerType_DicomTag: assert(answerDicomMap_ != NULL); answerDicomMap_->Clear(); break; case _OrthancPluginDatabaseAnswerType_Change: assert(answerChanges_ != NULL); answerChanges_->clear(); break; case _OrthancPluginDatabaseAnswerType_ExportedResource: assert(answerExportedResources_ != NULL); answerExportedResources_->clear(); break; default: LOG(ERROR) << "Unhandled type of answer for custom index plugin: " << answer.type; throw OrthancException(ErrorCode_DatabasePlugin); } } else if (type_ != answer.type) { LOG(ERROR) << "Error in the plugin protocol: Cannot change the answer type"; throw OrthancException(ErrorCode_DatabasePlugin); } switch (answer.type) { case _OrthancPluginDatabaseAnswerType_Int32: { answerInt32_.push_back(answer.valueInt32); break; } case _OrthancPluginDatabaseAnswerType_Int64: { answerInt64_.push_back(answer.valueInt64); break; } case _OrthancPluginDatabaseAnswerType_Resource: { OrthancPluginResourceType type = static_cast<OrthancPluginResourceType>(answer.valueInt32); answerResources_.push_back(std::make_pair(answer.valueInt64, Convert(type))); break; } case _OrthancPluginDatabaseAnswerType_Attachment: { const OrthancPluginAttachment& attachment = *reinterpret_cast<const OrthancPluginAttachment*>(answer.valueGeneric); answerAttachments_.push_back(Convert(attachment)); break; } case _OrthancPluginDatabaseAnswerType_DicomTag: { const OrthancPluginDicomTag& tag = *reinterpret_cast<const OrthancPluginDicomTag*>(answer.valueGeneric); assert(answerDicomMap_ != NULL); answerDicomMap_->SetValue(tag.group, tag.element, std::string(tag.value)); break; } case _OrthancPluginDatabaseAnswerType_String: { if (answer.valueString == NULL) { throw OrthancException(ErrorCode_DatabasePlugin); } if (type_ == _OrthancPluginDatabaseAnswerType_None) { type_ = _OrthancPluginDatabaseAnswerType_String; answerStrings_.clear(); } else if (type_ != _OrthancPluginDatabaseAnswerType_String) { throw OrthancException(ErrorCode_DatabasePlugin); } answerStrings_.push_back(std::string(answer.valueString)); break; } case _OrthancPluginDatabaseAnswerType_Change: { assert(answerDone_ != NULL); if (answer.valueUint32 == 1) { *answerDone_ = true; } else if (*answerDone_) { throw OrthancException(ErrorCode_DatabasePlugin); } else { const OrthancPluginChange& change = *reinterpret_cast<const OrthancPluginChange*>(answer.valueGeneric); assert(answerChanges_ != NULL); answerChanges_->push_back (ServerIndexChange(change.seq, static_cast<ChangeType>(change.changeType), Convert(change.resourceType), change.publicId, change.date)); } break; } case _OrthancPluginDatabaseAnswerType_ExportedResource: { assert(answerDone_ != NULL); if (answer.valueUint32 == 1) { *answerDone_ = true; } else if (*answerDone_) { throw OrthancException(ErrorCode_DatabasePlugin); } else { const OrthancPluginExportedResource& exported = *reinterpret_cast<const OrthancPluginExportedResource*>(answer.valueGeneric); assert(answerExportedResources_ != NULL); answerExportedResources_->push_back (ExportedResource(exported.seq, Convert(exported.resourceType), exported.publicId, exported.modality, exported.date, exported.patientId, exported.studyInstanceUid, exported.seriesInstanceUid, exported.sopInstanceUid)); } break; } default: LOG(ERROR) << "Unhandled type of answer for custom index plugin: " << answer.type; throw OrthancException(ErrorCode_DatabasePlugin); } } }