Mercurial > hg > orthanc
changeset 6125:42e8033618d6 attach-custom-data
initial wrapping of keys-values iterators
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 20 May 2025 19:03:11 +0200 |
parents | 79e9fa2872cf |
children | 0f9dc84976ae |
files | OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Engine/OrthancPlugins.h OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h |
diffstat | 5 files changed, 358 insertions(+), 166 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Tue May 20 17:53:14 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Tue May 20 19:03:11 2025 +0200 @@ -623,22 +623,6 @@ } - static void CopyStringList(OrthancPluginMemoryBuffer& target, - const std::list<std::string>& list) - { - Json::Value json = Json::arrayValue; - - for (std::list<std::string>::const_iterator - it = list.begin(); it != list.end(); ++it) - { - json.append(*it); - } - - std::string s; - Toolbox::WriteFastJson(s, json); - CopyToMemoryBuffer(target, s); - } - namespace { class MemoryBufferRaii : public boost::noncopyable @@ -4761,16 +4745,6 @@ } } - void OrthancPlugins::ApplyListKeys(const _OrthancPluginListKeys& parameters) - { - PImpl::ServerContextReference lock(*pimpl_); - - std::list<std::string> keys; - - //lock.GetContext().GetIndex().ListKeys(keys, parameters.storeId, parameters.since, parameters.limit); - CopyStringList(*(parameters.keys), keys); - } - bool OrthancPlugins::HasQueuesSupport() { PImpl::ServerContextReference lock(*pimpl_); @@ -5903,81 +5877,136 @@ } case _OrthancPluginService_StoreKeyValue: - { if (!HasKeyValueStoresSupport()) { - LOG(ERROR) << "The DB engine does not support Key Value Store"; - return false; - } - - const _OrthancPluginStoreKeyValue& p = - *reinterpret_cast<const _OrthancPluginStoreKeyValue*>(parameters); - ApplyStoreKeyValue(p); - return true; - } + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginStoreKeyValue& p = + *reinterpret_cast<const _OrthancPluginStoreKeyValue*>(parameters); + ApplyStoreKeyValue(p); + return true; + } case _OrthancPluginService_DeleteKeyValue: - { if (!HasKeyValueStoresSupport()) { - LOG(ERROR) << "The DB engine does not support Key Value Store"; - return false; - } - - const _OrthancPluginDeleteKeyValue& p = - *reinterpret_cast<const _OrthancPluginDeleteKeyValue*>(parameters); - ApplyDeleteKeyValue(p); - return true; - } + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginDeleteKeyValue& p = + *reinterpret_cast<const _OrthancPluginDeleteKeyValue*>(parameters); + ApplyDeleteKeyValue(p); + return true; + } case _OrthancPluginService_GetKeyValue: - { + if (!HasKeyValueStoresSupport()) + { + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginGetKeyValue& p = + *reinterpret_cast<const _OrthancPluginGetKeyValue*>(parameters); + ApplyGetKeyValue(p); + return true; + } + + case _OrthancPluginService_CreateKeysValuesIterator: + if (!HasKeyValueStoresSupport()) + { + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginCreateKeysValuesIterator& p = + *reinterpret_cast<const _OrthancPluginCreateKeysValuesIterator*>(parameters); + + { + PImpl::ServerContextReference lock(*pimpl_); + *p.target = reinterpret_cast<OrthancPluginKeysValuesIterator*>(new StatelessDatabaseOperations::KeysValuesIterator(lock.GetContext().GetIndex(), p.storeId)); + } + + return true; + } + + case _OrthancPluginService_FreeKeysValuesIterator: if (!HasKeyValueStoresSupport()) { - LOG(ERROR) << "The DB engine does not support Key Value Store"; - return false; - } - - const _OrthancPluginGetKeyValue& p = - *reinterpret_cast<const _OrthancPluginGetKeyValue*>(parameters); - ApplyGetKeyValue(p); - return true; - } - - case _OrthancPluginService_ListKeys: - { + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginFreeKeysValuesIterator& p = + *reinterpret_cast<const _OrthancPluginFreeKeysValuesIterator*>(parameters); + delete reinterpret_cast<StatelessDatabaseOperations::KeysValuesIterator*>(p.iterator); + return true; + } + + case _OrthancPluginService_KeysValuesIteratorNext: if (!HasKeyValueStoresSupport()) { - LOG(ERROR) << "The DB engine does not support Key Value Store"; - return false; - } - - const _OrthancPluginListKeys& p = - *reinterpret_cast<const _OrthancPluginListKeys*>(parameters); - ApplyListKeys(p); - return true; - } + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginKeysValuesIteratorNext& p = + *reinterpret_cast<const _OrthancPluginKeysValuesIteratorNext*>(parameters); + + StatelessDatabaseOperations::KeysValuesIterator& iterator = *reinterpret_cast<StatelessDatabaseOperations::KeysValuesIterator*>(p.iterator); + *p.done = iterator.Next() ? 1 : 0; + return true; + } + + case _OrthancPluginService_KeysValuesIteratorGetKey: + case _OrthancPluginService_KeysValuesIteratorGetValue: + if (!HasKeyValueStoresSupport()) + { + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support key-value stores"); + } + else + { + const _OrthancPluginKeysValuesIteratorGetString& p = + *reinterpret_cast<const _OrthancPluginKeysValuesIteratorGetString*>(parameters); + + StatelessDatabaseOperations::KeysValuesIterator& iterator = *reinterpret_cast<StatelessDatabaseOperations::KeysValuesIterator*>(p.iterator); + + if (service == _OrthancPluginService_KeysValuesIteratorGetKey) + { + *p.target = iterator.GetKey().c_str(); + return true; + } + else if (service == _OrthancPluginService_KeysValuesIteratorGetValue) + { + *p.target = iterator.GetValue().c_str(); + return true; + } + else + { + throw OrthancException(ErrorCode_InternalError); + } + } case _OrthancPluginService_EnqueueValue: - { if (!HasQueuesSupport()) { - LOG(ERROR) << "The DB engine does not support Queues"; - return false; - } - - const _OrthancPluginEnqueueValue& p = - *reinterpret_cast<const _OrthancPluginEnqueueValue*>(parameters); - ApplyEnqueueValue(p); - return true; - } + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support queues"); + } + else + { + const _OrthancPluginEnqueueValue& p = + *reinterpret_cast<const _OrthancPluginEnqueueValue*>(parameters); + ApplyEnqueueValue(p); + return true; + } case _OrthancPluginService_DequeueValue: - { if (!HasQueuesSupport()) { - LOG(ERROR) << "The DB engine does not support Queues"; - return false; + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support queues"); } else { @@ -5986,21 +6015,19 @@ ApplyDequeueValue(p); return true; } - } case _OrthancPluginService_GetQueueSize: - { if (!HasQueuesSupport()) { - LOG(ERROR) << "The DB engine does not support Queues"; - return false; - } - - const _OrthancPluginGetQueueSize& p = - *reinterpret_cast<const _OrthancPluginGetQueueSize*>(parameters); - ApplyGetQueueSize(p); - return true; - } + throw OrthancException(ErrorCode_NotImplemented, "The DB engine does not support queues"); + } + else + { + const _OrthancPluginGetQueueSize& p = + *reinterpret_cast<const _OrthancPluginGetQueueSize*>(parameters); + ApplyGetQueueSize(p); + return true; + } default: return false;
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.h Tue May 20 17:53:14 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.h Tue May 20 19:03:11 2025 +0200 @@ -237,8 +237,6 @@ void ApplyGetKeyValue(const _OrthancPluginGetKeyValue& parameters); - void ApplyListKeys(const _OrthancPluginListKeys& parameters); - bool HasQueuesSupport(); void ApplyEnqueueValue(const _OrthancPluginEnqueueValue& parameters);
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Tue May 20 17:53:14 2025 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Tue May 20 19:03:11 2025 +0200 @@ -470,15 +470,19 @@ _OrthancPluginService_SetCurrentThreadName = 44, /* New in Orthanc 1.12.2 */ _OrthancPluginService_LogMessage = 45, /* New in Orthanc 1.12.4 */ _OrthancPluginService_AdoptAttachment = 46, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_StoreKeyValue = 47, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_DeleteKeyValue = 48, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_GetKeyValue = 49, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_ListKeys = 50, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_EnqueueValue = 51, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_DequeueValue = 52, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_GetQueueSize = 53, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_GetAttachmentCustomData = 54, /* New in Orthanc 1.12.99 */ - _OrthancPluginService_UpdateAttachmentCustomData = 55, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_GetAttachmentCustomData = 47, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_UpdateAttachmentCustomData = 48, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_StoreKeyValue = 49, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_DeleteKeyValue = 50, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_GetKeyValue = 51, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_CreateKeysValuesIterator = 52, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_FreeKeysValuesIterator = 53, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_KeysValuesIteratorNext = 54, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_KeysValuesIteratorGetKey = 55, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_KeysValuesIteratorGetValue = 56, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_EnqueueValue = 57, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_DequeueValue = 58, /* New in Orthanc 1.12.99 */ + _OrthancPluginService_GetQueueSize = 59, /* New in Orthanc 1.12.99 */ /* Registration of callbacks */ @@ -9849,7 +9853,7 @@ typedef struct { const char* attachmentUuid; /* in */ - // OrthancPluginContentType contentType; /* in */ + /* OrthancPluginContentType contentType; */ /* in */ OrthancPluginMemoryBuffer* customData; /* out */ } _OrthancPluginGetAttachmentCustomData; @@ -9862,13 +9866,13 @@ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetAttachmentCustomData( OrthancPluginContext* context, const char* attachmentUuid, /* in */ - // OrthancPluginContentType contentType, /* in */ + /* OrthancPluginContentType contentType, */ /* in */ OrthancPluginMemoryBuffer* customData /* out */ ) { _OrthancPluginGetAttachmentCustomData params; params.attachmentUuid = attachmentUuid; - // params.contentType = contentType; + /* params.contentType = contentType; */ params.customData = customData; return context->InvokeService(context, _OrthancPluginService_GetAttachmentCustomData, ¶ms); @@ -9998,40 +10002,138 @@ return context->InvokeService(context, _OrthancPluginService_GetKeyValue, ¶ms); } - typedef struct - { - const char* storeId; - uint64_t since; - uint64_t limit; - OrthancPluginMemoryBuffer* keys; - } _OrthancPluginListKeys; - - - /** - * @brief Create an iterator over the keys and values stored in a key-value store. - * - * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). - * @param storeId A unique identifier identifying both the plugin and the store - * @param since The index of the first key to return when sorted alphabetically - * @param limit The number of keys to return (0 for no limit) - * @param keys The keys serialized in a json string - * @return 0 if success, other value if error. - **/ - ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginListKeys( - OrthancPluginContext* context, - const char* storeId, /* in */ - uint64_t since, /* in */ - uint64_t limit, /* in */ - OrthancPluginMemoryBuffer* keys /* out */) - { - _OrthancPluginListKeys params; + + /** + * @brief Opaque structure that represents an iterator to the keys and values of + * a key-value store. + * @ingroup Callbacks + **/ + typedef struct _OrthancPluginKeysValuesIterator_t OrthancPluginKeysValuesIterator; + + + + typedef struct + { + OrthancPluginKeysValuesIterator** target; + const char* storeId; + } _OrthancPluginCreateKeysValuesIterator; + + + /* TODO_ATTACH_CUSTOM_DATA TODO DOCUMENT */ + + ORTHANC_PLUGIN_INLINE OrthancPluginKeysValuesIterator* OrthancPluginCreateKeysValuesIterator( + OrthancPluginContext* context, + const char* storeId) + { + OrthancPluginKeysValuesIterator* target = NULL; + + _OrthancPluginCreateKeysValuesIterator params; + params.target = ⌖ params.storeId = storeId; - params.since = since; - params.limit = limit; - params.keys = keys; - - return context->InvokeService(context, _OrthancPluginService_ListKeys, ¶ms); - } + + if (context->InvokeService(context, _OrthancPluginService_CreateKeysValuesIterator, ¶ms) != OrthancPluginErrorCode_Success) + { + return NULL; + } + else + { + return target; + } + } + + + typedef struct + { + OrthancPluginKeysValuesIterator* iterator; + } _OrthancPluginFreeKeysValuesIterator; + + /* TODO_ATTACH_CUSTOM_DATA TODO DOCUMENT */ + + ORTHANC_PLUGIN_INLINE void OrthancPluginFreeKeysValuesIterator( + OrthancPluginContext* context, + OrthancPluginKeysValuesIterator* iterator) + { + _OrthancPluginFreeKeysValuesIterator params; + params.iterator = iterator; + + context->InvokeService(context, _OrthancPluginService_FreeKeysValuesIterator, ¶ms); + } + + + typedef struct + { + uint8_t* done; + OrthancPluginKeysValuesIterator* iterator; + } _OrthancPluginKeysValuesIteratorNext; + + + /* TODO_ATTACH_CUSTOM_DATA TODO DOCUMENT */ + + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginKeysValuesIteratorNext( + OrthancPluginContext* context, + uint8_t* done, + OrthancPluginKeysValuesIterator* iterator) + { + _OrthancPluginKeysValuesIteratorNext params; + params.done = done; + params.iterator = iterator; + + return context->InvokeService(context, _OrthancPluginService_KeysValuesIteratorNext, ¶ms); + } + + + typedef struct + { + const char** target; + OrthancPluginKeysValuesIterator* iterator; + } _OrthancPluginKeysValuesIteratorGetString; + + + /* TODO_ATTACH_CUSTOM_DATA TODO DOCUMENT */ + + ORTHANC_PLUGIN_INLINE const char* OrthancPluginKeysValuesIteratorGetKey( + OrthancPluginContext* context, + OrthancPluginKeysValuesIterator* iterator) + { + const char* target = NULL; + + _OrthancPluginKeysValuesIteratorGetString params; + params.target = ⌖ + params.iterator = iterator; + + if (context->InvokeService(context, _OrthancPluginService_KeysValuesIteratorGetKey, ¶ms) == OrthancPluginErrorCode_Success) + { + return target; + } + else + { + return NULL; + } + } + + + /* TODO_ATTACH_CUSTOM_DATA TODO DOCUMENT */ + + ORTHANC_PLUGIN_INLINE const char* OrthancPluginKeysValuesIteratorGetValue( + OrthancPluginContext* context, + OrthancPluginKeysValuesIterator* iterator) + { + const char* target = NULL; + + _OrthancPluginKeysValuesIteratorGetString params; + params.target = ⌖ + params.iterator = iterator; + + if (context->InvokeService(context, _OrthancPluginService_KeysValuesIteratorGetValue, ¶ms) == OrthancPluginErrorCode_Success) + { + return target; + } + else + { + return NULL; + } + } + typedef struct
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Tue May 20 17:53:14 2025 +0200 +++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Tue May 20 19:03:11 2025 +0200 @@ -4350,6 +4350,76 @@ #if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + KeyValueStore::Iterator::Iterator(OrthancPluginKeysValuesIterator *iterator) : + iterator_(iterator) + { + if (iterator_ == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + KeyValueStore::Iterator::~Iterator() + { + OrthancPluginFreeKeysValuesIterator(OrthancPlugins::GetGlobalContext(), iterator_); + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + bool KeyValueStore::Iterator::Next() + { + uint8_t done; + OrthancPluginErrorCode code = OrthancPluginKeysValuesIteratorNext(OrthancPlugins::GetGlobalContext(), &done, iterator_); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + else + { + return (done != 0); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + std::string KeyValueStore::Iterator::GetKey() const + { + const char* s = OrthancPluginKeysValuesIteratorGetKey(OrthancPlugins::GetGlobalContext(), iterator_); + if (s == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + return s; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + std::string KeyValueStore::Iterator::GetValue() const + { + const char* s = OrthancPluginKeysValuesIteratorGetValue(OrthancPlugins::GetGlobalContext(), iterator_); + if (s == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + return s; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 void KeyValueStore::Store(const std::string& key, const std::string& value) { @@ -4404,32 +4474,9 @@ #if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 - bool KeyValueStore::GetAllKeys(std::list<std::string>& keys, uint64_t since, uint64_t limit) - { - OrthancPlugins::MemoryBuffer keysListBuffer; - OrthancPluginErrorCode ret = OrthancPluginListKeys(OrthancPlugins::GetGlobalContext(), storeId_.c_str(), - since, limit, *keysListBuffer); - - if (ret == OrthancPluginErrorCode_Success) - { - Json::Value jsonKeys; - keysListBuffer.ToJson(jsonKeys); - - for (Json::ArrayIndex i = 0; i < jsonKeys.size(); ++i) - { - keys.push_back(jsonKeys[i].asString()); - } - - // return true if all values have been read - return limit == 0 || (jsonKeys.size() < limit); - } - -#if HAS_ORTHANC_EXCEPTION == 1 - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to list keys"); -#else - ORTHANC_PLUGINS_LOG_ERROR("Unable to list keys"); - ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); -#endif + KeyValueStore::Iterator* KeyValueStore::CreateIterator() + { + return new Iterator(OrthancPluginCreateKeysValuesIterator(OrthancPlugins::GetGlobalContext(), storeId_.c_str())); } #endif
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h Tue May 20 17:53:14 2025 +0200 +++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h Tue May 20 19:03:11 2025 +0200 @@ -1631,6 +1631,24 @@ #if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 class KeyValueStore : public boost::noncopyable { + public: + class Iterator : public boost::noncopyable + { + private: + OrthancPluginKeysValuesIterator *iterator_; + + public: + Iterator(OrthancPluginKeysValuesIterator *iterator); + + ~Iterator(); + + bool Next(); + + std::string GetKey() const; + + std::string GetValue() const; + }; + private: std::string storeId_; @@ -1648,7 +1666,7 @@ void Delete(const std::string& key); - bool GetAllKeys(std::list<std::string>& keys, uint64_t since, uint64_t limit); + Iterator* CreateIterator(); }; #endif