Mercurial > hg > orthanc
changeset 6108:21370b265a86 attach-custom-data
SDK: Get & Update Attachment CustomData
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Wed, 14 May 2025 13:11:38 +0200 |
parents | d71be7893e49 |
children | 370479295564 |
files | OrthancServer/CMakeLists.txt OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Engine/OrthancPlugins.h OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Sources/Database/IDatabaseWrapper.h OrthancServer/Sources/Database/InstallKeyValueStore.sql OrthancServer/Sources/Database/InstallKeyValueStoresAndQueues.sql OrthancServer/Sources/Database/PrepareDatabase.sql OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.h |
diffstat | 14 files changed, 309 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/CMakeLists.txt Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/CMakeLists.txt Wed May 14 13:11:38 2025 +0200 @@ -253,7 +253,7 @@ INSTALL_TRACK_ATTACHMENTS_SIZE ${CMAKE_SOURCE_DIR}/Sources/Database/InstallTrackAttachmentsSize.sql INSTALL_LABELS_TABLE ${CMAKE_SOURCE_DIR}/Sources/Database/InstallLabelsTable.sql INSTALL_REVISION_AND_CUSTOM_DATA ${CMAKE_SOURCE_DIR}/Sources/Database/InstallRevisionAndCustomData.sql - INSTALL_KEY_VALUE_STORE ${CMAKE_SOURCE_DIR}/Sources/Database/InstallKeyValueStore.sql + INSTALL_KEY_VALUE_STORE_AND_QUEUES ${CMAKE_SOURCE_DIR}/Sources/Database/InstallKeyValueStoresAndQueues.sql ) if (STANDALONE_BUILD)
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp Wed May 14 13:11:38 2025 +0200 @@ -1484,6 +1484,18 @@ throw OrthancException(ErrorCode_InternalError); // Not supported } + virtual bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // Not supported + } + + virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // Not supported + } };
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp Wed May 14 13:11:38 2025 +0200 @@ -679,7 +679,6 @@ } } - virtual bool LookupGlobalProperty(std::string& target, GlobalProperty property, bool shared) ORTHANC_OVERRIDE @@ -1097,6 +1096,20 @@ throw OrthancException(ErrorCode_InternalError); // Not supported } + virtual bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // Not supported + } + + virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // Not supported + } + + };
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Wed May 14 13:11:38 2025 +0200 @@ -1018,7 +1018,21 @@ } } - + + virtual bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // TODO_ATTACH_CUSTOM_DATA + } + + virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // TODO_ATTACH_CUSTOM_DATA + } + + virtual bool LookupGlobalProperty(std::string& target, GlobalProperty property, bool shared) ORTHANC_OVERRIDE
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Wed May 14 13:11:38 2025 +0200 @@ -4681,6 +4681,31 @@ } } + void OrthancPlugins::ApplyGetAttachmentCustomData(const _OrthancPluginGetAttachmentCustomData& parameters) + { + PImpl::ServerContextReference lock(*pimpl_); + FileInfo fileInfo; + int64_t revision; + + if (lock.GetContext().GetIndex().GetAttachment(fileInfo, revision, parameters.attachmentUuid)) + { + CopyToMemoryBuffer(*parameters.customData, fileInfo.GetCustomData().size() > 0 ? fileInfo.GetCustomData().c_str() : NULL, fileInfo.GetCustomData().size()); + } + else + { + throw OrthancException(ErrorCode_UnknownResource); + } + } + + void OrthancPlugins::ApplyUpdateAttachmentCustomData(const _OrthancPluginUpdateAttachmentCustomData& parameters) + { + PImpl::ServerContextReference lock(*pimpl_); + FileInfo fileInfo; + std::string customData(parameters.customData, parameters.customDataSize); + + lock.GetContext().GetIndex().UpdateAttachmentCustomData(parameters.attachmentUuid, customData); + } + bool OrthancPlugins::HasKeyValueStore() { PImpl::ServerContextReference lock(*pimpl_); @@ -5828,6 +5853,22 @@ return true; } + case _OrthancPluginService_GetAttachmentCustomData: + { + const _OrthancPluginGetAttachmentCustomData& p = + *reinterpret_cast<const _OrthancPluginGetAttachmentCustomData*>(parameters); + ApplyGetAttachmentCustomData(p); + return true; + } + + case _OrthancPluginService_UpdateAttachmentCustomData: + { + const _OrthancPluginUpdateAttachmentCustomData& p = + *reinterpret_cast<const _OrthancPluginUpdateAttachmentCustomData*>(parameters); + ApplyUpdateAttachmentCustomData(p); + return true; + } + case _OrthancPluginService_StoreKeyValue: { if (!HasKeyValueStore())
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.h Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.h Wed May 14 13:11:38 2025 +0200 @@ -225,6 +225,10 @@ void ApplyAdoptAttachment(const _OrthancPluginAdoptAttachment& parameters); + void ApplyGetAttachmentCustomData(const _OrthancPluginGetAttachmentCustomData& parameters); + + void ApplyUpdateAttachmentCustomData(const _OrthancPluginUpdateAttachmentCustomData& parameters); + bool HasKeyValueStore(); void ApplyStoreKeyValue(const _OrthancPluginStoreKeyValue& parameters);
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Wed May 14 13:11:38 2025 +0200 @@ -475,6 +475,8 @@ _OrthancPluginService_GetKeyValue = 49, /* New in Orthanc 1.12.99 */ _OrthancPluginService_EnqueueValue = 50, /* New in Orthanc 1.12.99 */ _OrthancPluginService_DequeueValue = 51, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_GetAttachmentCustomData = 52, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_UpdateAttachmentCustomData = 53, /* New in Orthanc 1.12.99 */ /* Registration of callbacks */ @@ -9839,6 +9841,64 @@ typedef struct { + const char* attachmentUuid; /* in */ + // OrthancPluginContentType contentType; /* in */ + OrthancPluginMemoryBuffer* customData; /* out */ + } _OrthancPluginGetAttachmentCustomData; + + /** + * @brief Retrieve attachment customData from the Orthanc DB. + * + * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). +TODO_ATTACH_CUSTOM_DATA TODO TODO + **/ + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetAttachmentCustomData( + OrthancPluginContext* context, + const char* attachmentUuid, /* in */ + // OrthancPluginContentType contentType, /* in */ + OrthancPluginMemoryBuffer* customData /* out */ + ) + { + _OrthancPluginGetAttachmentCustomData params; + params.attachmentUuid = attachmentUuid; + // params.contentType = contentType; + params.customData = customData; + + return context->InvokeService(context, _OrthancPluginService_GetAttachmentCustomData, ¶ms); + } + + typedef struct + { + const char* attachmentUuid; /* in */ + const char* customData; /* in */ + int64_t customDataSize; /* in */ + } _OrthancPluginUpdateAttachmentCustomData; + + + /** + * @brief Update attachment custom data in the Orthanc DB. E.g if a plugin has moved an attachment. + * + * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). +TODO_ATTACH_CUSTOM_DATA TODO TODO + **/ + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginUpdateAttachmentCustomData( + OrthancPluginContext* context, + const char* attachmentUuid, /* in */ + const char* customData, /* in */ + int64_t customDataSize /* in */ + ) + { + _OrthancPluginUpdateAttachmentCustomData params; + params.attachmentUuid = attachmentUuid; + params.customData = customData; + params.customDataSize = customDataSize; + + return context->InvokeService(context, _OrthancPluginService_UpdateAttachmentCustomData, ¶ms); + } + + + typedef struct + { const char* storeId; const char* key; const char* value;
--- a/OrthancServer/Sources/Database/IDatabaseWrapper.h Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h Wed May 14 13:11:38 2025 +0200 @@ -286,6 +286,13 @@ int64_t id, FileContentType contentType) = 0; + virtual bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) = 0; + + virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) = 0; + /** * If "shared" is "true", the property is shared by all the * Orthanc servers that access the same database. If "shared" is
--- a/OrthancServer/Sources/Database/InstallKeyValueStore.sql Tue May 13 14:10:30 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ --- Orthanc - A Lightweight, RESTful DICOM Store --- Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics --- Department, University Hospital of Liege, Belgium --- Copyright (C) 2017-2023 Osimis S.A., Belgium --- Copyright (C) 2024-2025 Orthanc Team SRL, Belgium --- Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium --- --- This program is free software: you can redistribute it and/or --- modify it under the terms of the GNU General Public License as --- published by the Free Software Foundation, either version 3 of the --- License, or (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, but --- WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --- General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see <http://www.gnu.org/licenses/>. - - -CREATE TABLE KeyValueStores( - storeId TEXT NOT NULL, - key TEXT NOT NULL, - value TEXT NOT NULL, - PRIMARY KEY(storeId, key) -- Prevents duplicates - ); - -CREATE INDEX KeyValueStoresIndex ON KeyValueStores (storeId, key); - -CREATE TABLE Queues ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - queueId TEXT NOT NULL, - value TEXT -); - -CREATE INDEX QueuesIndex ON Queues (queueId, id);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Sources/Database/InstallKeyValueStoresAndQueues.sql Wed May 14 13:11:38 2025 +0200 @@ -0,0 +1,37 @@ +-- Orthanc - A Lightweight, RESTful DICOM Store +-- Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics +-- Department, University Hospital of Liege, Belgium +-- Copyright (C) 2017-2023 Osimis S.A., Belgium +-- Copyright (C) 2024-2025 Orthanc Team SRL, Belgium +-- Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +-- +-- This program is free software: you can redistribute it and/or +-- modify it under the terms of the GNU General Public License as +-- published by the Free Software Foundation, either version 3 of the +-- License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, but +-- WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. + + +CREATE TABLE KeyValueStores( + storeId TEXT NOT NULL, + key TEXT NOT NULL, + value TEXT NOT NULL, + PRIMARY KEY(storeId, key) -- Prevents duplicates + ); + +CREATE INDEX KeyValueStoresIndex ON KeyValueStores (storeId, key); + +CREATE TABLE Queues ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + queueId TEXT NOT NULL, + value TEXT +); + +CREATE INDEX QueuesIndex ON Queues (queueId, id);
--- a/OrthancServer/Sources/Database/PrepareDatabase.sql Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Sources/Database/PrepareDatabase.sql Wed May 14 13:11:38 2025 +0200 @@ -168,7 +168,7 @@ ); -- new in Orthanc 1.12.99 -CREATE INDEX KeyValueStoresIndex ON KeyValueStore (storeId, key); +CREATE INDEX KeyValueStoresIndex ON KeyValueStores (storeId, key); -- new in Orthanc 1.12.99 CREATE TABLE Queues (
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Wed May 14 13:11:38 2025 +0200 @@ -1784,6 +1784,43 @@ } } + virtual bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) ORTHANC_OVERRIDE + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "SELECT uuid, uncompressedSize, compressionType, compressedSize, " + "uncompressedMD5, compressedMD5, revision, customData, fileType FROM AttachedFiles WHERE uuid=?"); + s.BindString(0, attachmentUuid); + + if (!s.Step()) + { + return false; + } + else + { + attachment = FileInfo(s.ColumnString(0), + static_cast<FileContentType>(s.ColumnInt(8)), + s.ColumnInt64(1), + s.ColumnString(4), + static_cast<CompressionType>(s.ColumnInt(2)), + s.ColumnInt64(3), + s.ColumnString(5), + s.ColumnString(7)); + revision = s.ColumnInt(6); + return true; + } + } + + virtual void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) ORTHANC_OVERRIDE + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "UPDATE AttachedFiles SET customData=? WHERE uuid=?"); + s.BindString(0, customData); + s.BindString(1, attachmentUuid); + s.Run(); + } virtual bool LookupGlobalProperty(std::string& target, GlobalProperty property, @@ -2521,11 +2558,11 @@ db_.Execute(query); } - if (!db_.DoesTableExist("KeyValueStore")) + if (!db_.DoesTableExist("KeyValueStores")) { - LOG(INFO) << "Installing the \"KeyValueStore\" table"; + LOG(INFO) << "Installing the \"KeyValueStores\" and \"Queues\" tables"; std::string query; - ServerResources::GetFileResource(query, ServerResources::INSTALL_KEY_VALUE_STORE); + ServerResources::GetFileResource(query, ServerResources::INSTALL_KEY_VALUE_STORE_AND_QUEUES); db_.Execute(query); } }
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Wed May 14 13:11:38 2025 +0200 @@ -3488,4 +3488,61 @@ return operations.HasFound(); } + bool StatelessDatabaseOperations::GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) + { + class Operations : public ReadOnlyOperationsT3<FileInfo&, int64_t&, const std::string& > + { + bool found_; + public: + Operations(): + found_(false) + {} + + bool HasFound() + { + return found_; + } + + virtual void ApplyTuple(ReadOnlyTransaction& transaction, + const Tuple& tuple) ORTHANC_OVERRIDE + { + found_ = transaction.GetAttachment(tuple.get<0>(), tuple.get<1>(), tuple.get<2>()); + } + }; + + Operations operations; + operations.Apply(*this, attachment, revision, attachmentUuid); + + return operations.HasFound(); + } + + void StatelessDatabaseOperations::UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) + { + class Operations : public IReadWriteOperations + { + private: + const std::string& attachmentUuid_; + const std::string& customData_; + + public: + Operations(const std::string& attachmentUuid, + const std::string& customData) : + attachmentUuid_(attachmentUuid), + customData_(customData) + { + } + + virtual void Apply(ReadWriteTransaction& transaction) ORTHANC_OVERRIDE + { + transaction.UpdateAttachmentCustomData(attachmentUuid_, customData_); + } + }; + + Operations operations(attachmentUuid, customData); + Apply(operations); + } + }
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Tue May 13 14:10:30 2025 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Wed May 14 13:11:38 2025 +0200 @@ -226,6 +226,13 @@ return transaction_.LookupAttachment(attachment, revision, id, contentType); } + bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid) + { + return transaction_.GetAttachment(attachment, revision, attachmentUuid); + } + bool LookupGlobalProperty(std::string& target, GlobalProperty property, bool shared) @@ -464,6 +471,12 @@ } + void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData) + { + return transaction_.UpdateAttachmentCustomData(attachmentUuid, customData); + } + }; @@ -559,6 +572,13 @@ /* out */ uint64_t& countSeries, /* out */ uint64_t& countInstances); + bool GetAttachment(FileInfo& attachment, + int64_t& revision, + const std::string& attachmentUuid); + + void UpdateAttachmentCustomData(const std::string& attachmentUuid, + const std::string& customData); + bool LookupAttachment(FileInfo& attachment, int64_t& revision, ResourceType level,