From 37e1952f71a3bf0b989873d136f4a671484f5c25 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Tue, 14 Nov 2023 15:45:24 -0800 Subject: [PATCH] Fixed Linux AMQP crash and many other fixes. (#5166) * Return pointer to message rather than message; cleaned up API surface to remove uAMQP details * ASAN configuration via CMAKE preset, not environment variable * clang-tidy fixes --- CMakeLists.txt | 8 + CMakePresets.json | 124 +++++++++++++- sdk/core/azure-core-amqp/CHANGELOG.md | 4 + sdk/core/azure-core-amqp/CMakeLists.txt | 3 +- .../amqp/internal/common/global_state.hpp | 6 + .../azure/core/amqp/internal/connection.hpp | 2 +- .../internal/connection_string_credential.hpp | 37 +++- .../inc/azure/core/amqp/internal/endpoint.hpp | 2 +- .../azure/core/amqp/internal/management.hpp | 31 +++- .../core/amqp/internal/message_receiver.hpp | 6 +- .../core/amqp/internal/models/amqp_error.hpp | 21 ++- .../amqp/internal/models/message_source.hpp | 17 ++ .../amqp/internal/models/message_target.hpp | 28 ++- .../azure/core/amqp/models/amqp_header.hpp | 5 +- .../azure/core/amqp/models/amqp_message.hpp | 21 ++- .../core/amqp/models/amqp_properties.hpp | 10 +- .../inc/azure/core/amqp/models/amqp_value.hpp | 143 ++++++++-------- ...venthub_get_eventhub_properties_sample.cpp | 10 +- .../eventhub_sas_reader_sample.cpp | 2 +- .../eventhub_token_reader_sample.cpp | 2 +- .../local_server_sample.cpp | 8 +- .../src/amqp/claim_based_security.cpp | 4 +- .../azure-core-amqp/src/amqp/connection.cpp | 16 +- sdk/core/azure-core-amqp/src/amqp/link.cpp | 18 +- .../azure-core-amqp/src/amqp/management.cpp | 55 +++--- .../src/amqp/message_receiver.cpp | 34 ++-- .../src/amqp/message_sender.cpp | 14 +- .../src/amqp/private/management_impl.hpp | 14 +- .../amqp/private/message_receiver_impl.hpp | 9 +- sdk/core/azure-core-amqp/src/amqp/session.cpp | 9 +- .../src/common/global_state.cpp | 2 +- .../azure-core-amqp/src/models/amqp_error.cpp | 10 +- .../src/models/amqp_header.cpp | 22 +-- .../src/models/amqp_message.cpp | 125 +++++++------- .../src/models/amqp_properties.cpp | 39 +++-- .../azure-core-amqp/src/models/amqp_value.cpp | 159 ++++++++++-------- .../src/models/message_source.cpp | 78 ++++++--- .../src/models/message_target.cpp | 41 +++-- .../src/models/messaging_values.cpp | 24 +-- .../test/ut/amqp_header_tests.cpp | 20 +-- .../test/ut/amqp_message_tests.cpp | 78 +++++---- .../test/ut/amqp_properties_tests.cpp | 52 +++--- .../test/ut/management_tests.cpp | 14 +- .../test/ut/message_sender_receiver.cpp | 21 ++- .../test/ut/mock_amqp_server.hpp | 50 +++--- .../test/ut_uamqp/amqp_error_tests.cpp | 2 +- .../vendor/azure-uamqp-c/CMakeLists.txt | 6 +- sdk/core/azure-core/inc/azure/core/uuid.hpp | 2 +- .../azure-messaging-eventhubs/CHANGELOG.md | 2 + .../messaging/eventhubs/event_data_batch.hpp | 9 +- .../messaging/eventhubs/models/event_data.hpp | 13 +- .../messaging/eventhubs/partition_client.hpp | 16 +- .../eventhubs/processor_partition_client.hpp | 4 +- .../samples/consume-events/consume_events.cpp | 4 +- .../consume-events/consume_events_aad.cpp | 4 +- .../src/event_data.cpp | 32 ++-- .../src/event_data_batch.cpp | 16 +- .../src/partition_client.cpp | 45 ++--- .../src/private/eventhubs_utilities.hpp | 10 +- .../src/processor.cpp | 4 +- .../src/processor_partition_client.cpp | 12 +- .../test/ut/consumer_client_test.cpp | 8 +- .../test/ut/event_data_test.cpp | 109 ++++++------ .../test/ut/processor_test.cpp | 10 +- .../test/ut/producer_client_test.cpp | 4 +- .../test/ut/round_trip_test.cpp | 26 +-- 66 files changed, 1054 insertions(+), 682 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ae16216ec..038cd99241 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. +# cspell: words fsanitize + cmake_minimum_required (VERSION 3.13) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules") @@ -120,6 +122,12 @@ if(MSVC_USE_STATIC_CRT AND MSVC) endif() endif() +# If the cmake presets enable Address Sanitizer, enable it for the project. +if (ENABLE_ADDRESS_SANITIZER) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +endif() + if(BUILD_TESTING) include(AddGoogleTest) enable_testing () diff --git a/CMakePresets.json b/CMakePresets.json index b3f83b004d..6b18df3c29 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -52,6 +52,56 @@ "rhs": "Windows" } }, + { + "name": "clang-windows-default", + "displayName": "Windows", + "description": "Sets Ninja generator, and compilers. Configures vcpkg in manifest mode using clang", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "hidden": true, + "cacheVariables": { + "VCPKG_MANIFEST_MODE": true, + "CMAKE_CXX_COMPILER": "clang++.exe", + "CMAKE_C_COMPILER": "clang.exe" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "gcc-windows-default", + "displayName": "Windows", + "description": "Sets Ninja generator, and compilers. Configures vcpkg in manifest mode using gcc", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "hidden": true, + "cacheVariables": { + "VCPKG_MANIFEST_MODE": true, + "CMAKE_CXX_COMPILER": "g++.exe", + "CMAKE_C_COMPILER": "gcc.exe" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, { "name": "x64-static", "displayName": "Windows x64 Static", @@ -109,6 +159,60 @@ "strategy": "external" } }, + { + "name": "x86-clang-static", + "displayName": "Windows x86 clang Static", + "description": "Windows Default, clang, x86 architecture.", + "inherits": "gcc-windows-default", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x86-windows-static", + "MSVC_USE_STATIC_CRT": true + }, + "architecture": "win32" + }, + { + "name": "x64-clang-static", + "displayName": "Windows x64 CLANG Static", + "description": "Windows Default, clang, x64 architecture.", + "inherits": "clang-windows-default", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-windows-static", + "MSVC_USE_STATIC_CRT": true + }, + "architecture": { + "value": "x64", + "strategy": "external" + } + }, + { + "name": "x86-gcc-static", + "displayName": "Windows x86 gccStatic", + "description": "Windows Default, gcc, x86 architecture.", + "inherits": "gcc-windows-default", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x86-windows-static", + "MSVC_USE_STATIC_CRT": true + }, + "architecture": "win32" + }, + { + "name": "x64-gcc-static", + "displayName": "Windows x64 GCC Static", + "description": "Windows Default, gcc, x64 architecture.", + "inherits": "gcc-windows-default", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-windows-static", + "MSVC_USE_STATIC_CRT": true + }, + "architecture": { + "value": "x64", + "strategy": "external" + } + }, { "name": "x64", "displayName": "Windows x64", @@ -213,9 +317,8 @@ "displayName": "Enable Address Sanitizer", "description": "Enable Address Sanitizer (Hidden). Note: ASAN can be extremely disruptive, when enabling ASAN, make sure you run your application under the debugger.", "hidden": true, - "environment": { - "CXXFLAGS": "-fsanitize=address", - "CFLAGS": "-fsanitize=address" + "cacheVariables": { + "ENABLE_ADDRESS_SANITIZER": true } }, { @@ -370,7 +473,7 @@ "enable-address-sanitizer" ], "cacheVariables": { - "DISABLE_AZURE_CORE_OPENTELEMETRY": true + "DISABLE_AZURE_CORE_OPENTELEMETRY": true } }, { @@ -421,6 +524,19 @@ "enable-perf" ] }, + { + "name": "x64-static-debug-perftests-clang", + "displayName": "x64 Debug static With Perf Tests and samples+clang, libcurl+winhttp", + "inherits": [ + "x64-clang-static", + "debug-build", + "enable-tests", + "enable-samples", + "enable-perf", + "winhttp-transport", + "curl-transport" + ] + }, { "name": "linux-basic-gcc9", "displayName": "Linux GCC 9", diff --git a/sdk/core/azure-core-amqp/CHANGELOG.md b/sdk/core/azure-core-amqp/CHANGELOG.md index 3cc4e94596..c113e22ded 100644 --- a/sdk/core/azure-core-amqp/CHANGELOG.md +++ b/sdk/core/azure-core-amqp/CHANGELOG.md @@ -4,8 +4,12 @@ ### Features Added +- AMQP Value reference counts are now atomic, this fixes several AMQP related crashes. + ### Breaking Changes +- `MessageReceiver` returns a pointer to the received message instead of a copy. + ### Bugs Fixed - Fixed several memory leaks. diff --git a/sdk/core/azure-core-amqp/CMakeLists.txt b/sdk/core/azure-core-amqp/CMakeLists.txt index 4896a57715..61aad508d6 100644 --- a/sdk/core/azure-core-amqp/CMakeLists.txt +++ b/sdk/core/azure-core-amqp/CMakeLists.txt @@ -36,6 +36,7 @@ if (VENDOR_UAMQP) set(use_installed_dependencies ON CACHE BOOL "Use vcpkg dependencies." FORCE) set(skip_samples ON CACHE BOOL "Skip building samples" FORCE) set(build_as_object_library ON CACHE BOOL "Produce object library" FORCE) + set(atomic_refcount ON CACHE BOOL "Use atomic refcount" FORCE) add_subdirectory(vendor/azure-uamqp-c SYSTEM) @@ -43,7 +44,7 @@ if (VENDOR_UAMQP) if (MSVC) target_compile_definitions(uamqp PRIVATE _CRT_SECURE_NO_WARNINGS) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(uamqp PUBLIC -Wno-extra-semi -Wno-gnu-zero-variadic-macro-arguments -Wno-cast-qual -Wno-format-pedantic) + target_compile_options(uamqp PUBLIC -Wno-extra-semi -Wno-gnu-zero-variadic-macro-arguments -Wno-cast-qual -Wno-format-pedantic -Wno-c11-extensions) else() target_compile_options(uamqp PUBLIC -Wno-pedantic -Wno-implicit-fallthrough -Wno-strict-aliasing) endif() diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/common/global_state.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/common/global_state.hpp index c5c179135a..9780a2fe4b 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/common/global_state.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/common/global_state.hpp @@ -25,6 +25,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Common { namespace class Pollable { public: + Pollable() = default; + Pollable(const Pollable&) = delete; + Pollable& operator=(const Pollable&) = delete; + Pollable(Pollable&&) = delete; + Pollable& operator=(Pollable&&) = delete; + virtual void Poll() = 0; virtual ~Pollable() = default; }; diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection.hpp index e170d543c7..eadeda04e1 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection.hpp @@ -215,7 +215,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { * * If no frames are received within the timeout, the connection will be closed. */ - std::chrono::milliseconds IdleTimeout{std::chrono::milliseconds(60000)}; + std::chrono::milliseconds IdleTimeout{std::chrono::minutes(1)}; /** @brief The maximum frame size for the connection. * diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection_string_credential.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection_string_credential.hpp index 259e81bdf9..23d8512d12 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection_string_credential.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/connection_string_credential.hpp @@ -86,6 +86,41 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { } } + /** @brief Copy constructor + * + * @remarks Note that TokenCredential derived objects are expected to be passed via + * std::shared_ptr and thus should never be directly constructed. + */ + ServiceBusSasConnectionStringCredential(const ServiceBusSasConnectionStringCredential& other) + = delete; + + /** @brief Copy assignment operator + * + * * @remarks Note that TokenCredential derived objects are expected to be passed via + std::shared_ptr and thus + * should never be directly constructed. + + */ + ServiceBusSasConnectionStringCredential& operator=( + const ServiceBusSasConnectionStringCredential& other) + = delete; + + /** @brief Move constructor + * + * @remarks Note that TokenCredential derived objects are expected to be passed via + * std::shared_ptr and thus should never be directly constructed. + */ + ServiceBusSasConnectionStringCredential( + ServiceBusSasConnectionStringCredential&& other) noexcept = delete; + + /** @brief Move assignment operator + * + * @remarks Note that TokenCredential derived objects are expected to be passed via + * std::shared_ptr and thus should never be directly constructed. + */ + ServiceBusSasConnectionStringCredential& operator=( + ServiceBusSasConnectionStringCredential&& other) noexcept = delete; + /** @brief Destroy a SAS connection string credential. */ ~ServiceBusSasConnectionStringCredential() override = default; @@ -123,7 +158,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { * * @throw Credentials::AuthenticationException Authentication error occurred. */ - virtual Credentials::AccessToken GetToken( + Credentials::AccessToken GetToken( Credentials::TokenRequestContext const& tokenRequestContext, Context const& context) const override; diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/endpoint.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/endpoint.hpp index 6104676369..9af14df1f8 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/endpoint.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/endpoint.hpp @@ -35,7 +35,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { Endpoint(Endpoint const&) = delete; Endpoint& operator=(Endpoint const&) = delete; - Endpoint& operator=(Endpoint&& other); + Endpoint& operator=(Endpoint&& other) noexcept; ENDPOINT_INSTANCE_TAG* Release() { ENDPOINT_INSTANCE_TAG* rv = m_endpoint; diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/management.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/management.hpp index 3cd932f676..bb18b299ed 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/management.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/management.hpp @@ -113,7 +113,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { /** * @brief The response message from the operation, if Status is ManagementOperationStatus::Ok. */ - Models::AmqpMessage Message; + std::shared_ptr Message; /** * @brief The error code associated with the message, if Status is @@ -137,8 +137,36 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { */ class ManagementClient final { public: + /** + * @brief Represents a client used to manage AMQP entities. + */ + ManagementClient() = default; + + /** + * @brief Destructor for the ManagementClient class. + */ ~ManagementClient() noexcept = default; + /** + * @brief Copy constructor. + */ + ManagementClient(ManagementClient const&) = default; + + /** + * @brief Assignment operator. + */ + ManagementClient& operator=(ManagementClient const&) = default; + + /** + * @brief Move constructor. + */ + ManagementClient(ManagementClient&&) = default; + + /** + * @brief Move assignment operator. + */ + ManagementClient& operator=(ManagementClient&&) = default; + /** * @brief Open the management instance. * @@ -178,7 +206,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { private: friend class Azure::Core::Amqp::_detail::ManagementClientFactory; ManagementClient(std::shared_ptr<_detail::ManagementClientImpl> impl) : m_impl{impl} {} - std::shared_ptr<_detail::ManagementClientImpl> m_impl; }; diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/message_receiver.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/message_receiver.hpp index d1b2bffcec..5e4584e352 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/message_receiver.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/message_receiver.hpp @@ -102,7 +102,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { = 0; virtual Models::AmqpValue OnMessageReceived( MessageReceiver const& receiver, - Models::AmqpMessage const& message) + std::shared_ptr const& message) = 0; virtual void OnMessageReceiverDisconnected(Models::_internal::AmqpError const& error) = 0; }; @@ -167,7 +167,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { * * @return A pair of the received message and the error if any. */ - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> WaitForIncomingMessage(Context const& context = {}); /** @brief Return if there are messages waiting to be processed. @@ -175,7 +175,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { * @return A pair of the received message and the error if any. If both values are empty, then * no messages are available and the caller should call WaitForIncomingMessage. */ - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> TryWaitForIncomingMessage(); private: diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/amqp_error.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/amqp_error.hpp index 083c4f612e..f73907bfec 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/amqp_error.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/amqp_error.hpp @@ -20,9 +20,11 @@ namespace Azure { namespace Core { namespace _internal { }; }}} // namespace Azure::Core::_internal -namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { - +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { using UniqueAmqpErrorHandle = Azure::Core::_internal::UniqueHandle; +}}}}} // namespace Azure::Core::Amqp::Models::_detail + +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { class AmqpErrorCondition final : public Azure::Core::_internal::ExtendableEnumeration { @@ -317,9 +319,24 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace struct AmqpError final { + /** @brief Construct an AmqpError. */ AmqpError() = default; + + /** @brief Destroy an AmqpError. */ ~AmqpError() = default; + /** @brief Copy Constructor */ + AmqpError(AmqpError const&) = default; + + /** @brief Assignment operator */ + AmqpError& operator=(AmqpError const&) = default; + + /** @brief Move Constructor */ + AmqpError(AmqpError&&) = default; + + /** @brief Move assignment operator */ + AmqpError& operator=(AmqpError&&) = default; + /** @brief A symbolic value indicating the error condition. * * @remarks For more information, see [AMQP diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_source.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_source.hpp index 3abf21e720..8da8a8f704 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_source.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_source.hpp @@ -35,6 +35,17 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace AmqpArray Capabilities; }; + /** + * @brief Represents an AMQP message source. + * + * An AMQP message source is a node that originates messages. It is the source of messages for a + * link. The message source is identified by its address, which is a string that uniquely + * identifies the node within the scope of the AMQP container. + * + * @remarks See + * [source](http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-source) + * for more information about the fields in a message source. + */ class MessageSource final { public: /** @brief Creates a default message target. @@ -53,6 +64,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace */ MessageSource& operator=(MessageSource const& that); + /** @brief Move constructor */ + MessageSource(MessageSource&& other) noexcept; + + /** @brief Move assignment operator */ + MessageSource& operator=(MessageSource&& other) noexcept; + /** @brief Creates a message source with detailed options. * * @param options Options used constructing the message source. diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_target.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_target.hpp index 6f4efd223e..db6243f2f4 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_target.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/internal/models/message_target.hpp @@ -18,8 +18,11 @@ namespace Azure { namespace Core { namespace _internal { }; }}} // namespace Azure::Core::_internal -namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { using UniqueMessageTargetHandle = Azure::Core::_internal::UniqueHandle; +}}}}} // namespace Azure::Core::Amqp::Models::_detail + +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { struct MessageTargetOptions final { @@ -32,6 +35,16 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace AmqpArray Capabilities; }; + /** + * @brief Represents an AMQP message target. + * + * The MessageTarget class provides methods to create and manipulate an AMQP message target. + * A message target is the intended destination of an AMQP message. + * + * @remarks See + * [source](http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-target) + * for more information about the fields in a message target. + */ class MessageTarget final { public: /** @brief Creates a default message target. @@ -43,6 +56,15 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace /** @brief Copies a MessageTarget */ MessageTarget(MessageTarget const& that); + /** @brief Copy assignment operator */ + MessageTarget& operator=(MessageTarget const& that); + + /** @brief Moves a MessageTarget */ + MessageTarget(MessageTarget&&) noexcept; + + /** @brief Moves assignment operator */ + MessageTarget& operator=(MessageTarget&&) noexcept; + /** @brief Creates a message target with the given address. * * @param address The address of the target. @@ -69,8 +91,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace */ MessageTarget(Models::AmqpValue const& value); - MessageTarget& operator=(MessageTarget const& that); - /** @brief Creates an AMQP value from a message target. * * @remarks Creates an AMQP Described value with the descriptor being the message target @@ -148,7 +168,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace AmqpArray GetCapabilities() const; private: - UniqueMessageTargetHandle m_target; + _detail::UniqueMessageTargetHandle m_target; operator TARGET_INSTANCE_TAG*() const { return m_target.get(); } diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_header.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_header.hpp index 8cf062603e..6a50bec7f0 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_header.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_header.hpp @@ -24,7 +24,6 @@ namespace Azure { namespace Core { namespace _internal { }; }}} // namespace Azure::Core::_internal namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { - using UniqueMessageHeaderHandle = Azure::Core::_internal::UniqueHandle; }}}}} // namespace Azure::Core::Amqp::Models::_detail @@ -130,7 +129,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { }}}} // namespace Azure::Core::Amqp::Models -namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { /** * @brief uAMQP interoperability functions to convert a MessageHeader to a uAMQP HEADER_HANDLE * and back. @@ -144,4 +143,4 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace static _detail::UniqueMessageHeaderHandle ToUamqp(MessageHeader const& properties); }; -}}}}} // namespace Azure::Core::Amqp::Models::_internal +}}}}} // namespace Azure::Core::Amqp::Models::_detail diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_message.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_message.hpp index 8f49ad0091..44f641e6da 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_message.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_message.hpp @@ -24,12 +24,13 @@ namespace Azure { namespace Core { namespace _internal { }; }}} // namespace Azure::Core::_internal -namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { class AmqpMessageFactory; -}}}}} // namespace Azure::Core::Amqp::Models::_internal + using UniqueMessageHandle = Azure::Core::_internal::UniqueHandle; -namespace Azure { namespace Core { namespace Amqp { namespace Models { +}}}}} // namespace Azure::Core::Amqp::Models::_detail +namespace Azure { namespace Core { namespace Amqp { namespace Models { /** * @brief The type of the body of an AMQP Message. * @@ -42,7 +43,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { Sequence, Value, }; - using UniqueMessageHandle = Azure::Core::_internal::UniqueHandle; constexpr int AmqpDefaultMessageFormatValue = 0; // Specifies the message format for an AMQP message. @@ -291,7 +291,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { */ static AmqpMessage Deserialize(std::uint8_t const* buffer, size_t size); - friend class _internal::AmqpMessageFactory; + friend class _detail::AmqpMessageFactory; private: std::vector m_binaryDataBody; @@ -302,10 +302,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { std::ostream& operator<<(std::ostream&, AmqpMessage const&); }}}} // namespace Azure::Core::Amqp::Models -namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { /** - * @brief uAMQP interoperability functions to convert a MessageProperties to a uAMQP - * PROPERTIES_HANDLE and back. + * @brief uAMQP interoperability functions to convert a Message to a uAMQP + * MESSAGE_HANDLE and back. * * @remarks This class should not be used directly. It is used by the uAMQP interoperability * layer. @@ -314,8 +314,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace AmqpMessageFactory() = delete; public: - static AmqpMessage FromUamqp(UniqueMessageHandle const& properties); - static AmqpMessage FromUamqp(MESSAGE_INSTANCE_TAG* properties); + static std::shared_ptr FromUamqp(MESSAGE_INSTANCE_TAG* properties); static UniqueMessageHandle ToUamqp(AmqpMessage const& properties); }; -}}}}} // namespace Azure::Core::Amqp::Models::_internal +}}}}} // namespace Azure::Core::Amqp::Models::_detail diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_properties.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_properties.hpp index 73c14ebd7c..31fa67cc9c 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_properties.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_properties.hpp @@ -23,9 +23,11 @@ namespace Azure { namespace Core { namespace _internal { }}} // namespace Azure::Core::_internal -namespace Azure { namespace Core { namespace Amqp { namespace Models { - +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { using UniquePropertiesHandle = Azure::Core::_internal::UniqueHandle; +}}}}} // namespace Azure::Core::Amqp::Models::_detail + +namespace Azure { namespace Core { namespace Amqp { namespace Models { /** @brief Represents the immutable properties of an AMQP message. * @@ -212,7 +214,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { std::ostream& operator<<(std::ostream& stream, MessageProperties const& properties); }}}} // namespace Azure::Core::Amqp::Models -namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { +namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { /** * @brief uAMQP interoperability functions to convert a MessageProperties to a uAMQP * PROPERTIES_HANDLE and back. @@ -227,4 +229,4 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace static MessageProperties FromUamqp(UniquePropertiesHandle const& properties); static UniquePropertiesHandle ToUamqp(MessageProperties const& properties); }; -}}}}} // namespace Azure::Core::Amqp::Models::_internal +}}}}} // namespace Azure::Core::Amqp::Models::_detail diff --git a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_value.hpp b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_value.hpp index 0bfe2d43f6..86b6eb3281 100644 --- a/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_value.hpp +++ b/sdk/core/azure-core-amqp/inc/azure/core/amqp/models/amqp_value.hpp @@ -34,7 +34,8 @@ namespace Azure { namespace Core { namespace _internal { namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { using UniqueAmqpValueHandle = Azure::Core::_internal::UniqueHandle; - std::ostream& operator<<(std::ostream& os, AMQP_VALUE_DATA_TAG const* value); + class AmqpValueFactory; + std::ostream& operator<<(std::ostream& os, AMQP_VALUE_DATA_TAG* const value); }}}}} // namespace Azure::Core::Amqp::Models::_detail namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _internal { @@ -108,7 +109,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * Defined in [AMQP Core Types * section 1.6.1](http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#type-null). - ). * */ AmqpValue() noexcept; @@ -308,41 +308,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { */ AmqpValue(Azure::Core::Uuid const& value); - // Interoperability functions for uAMQP - /// @cond - - /** @brief Interoperability helper function which converts an AmqpValue to a uAMQP - * AMQP_VALUE object. - * - * @returns uAMQP AMQP_VALUE object. - * - * @remarks This is an internal operator which should not be called by customers. - */ - operator AMQP_VALUE_DATA_TAG*() const; - - /** @brief Interoperability helper function which releases the internal AmqpValue. - * - * @returns uAMQP AMQP_VALUE object. - * - * @remarks This is an internal operator which should not be called by customers. - */ - AMQP_VALUE_DATA_TAG* Release(); - - /** @brief Interoperability helper function which creates an AmqpValue from a uAMQP - * AMQP_VALUE object. - * - * @param value source uAMQP AMQP_VALUE object. - * - * @remarks This is an internal operator which should not be called by customers. - * - * @remarks Note that this does NOT capture the passed in AMQP_VALUE object, instead it clones - * the underlying AMQP_VALUE. This is why it takes a UniqueAmqpValueHandle as a parameter - * instead of a raw AMQP_VALUE - that ensures that someone will free the underlying AMQP_VALUE - * if needed. - */ - AmqpValue(_detail::UniqueAmqpValueHandle const& value); - /// @endcond - /** @brief Equality comparison operator. * @param that - Value to compare to this value. * @returns true if the that is equal to this. @@ -582,7 +547,22 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { private: AmqpValue(AMQP_VALUE_DATA_TAG*) = delete; + /** @brief Interoperability helper function which creates an AmqpValue from a uAMQP + * AMQP_VALUE object. + * + * @param value source uAMQP AMQP_VALUE object. + * + * @remarks This is an internal operator which should not be called by customers. + * + * @remarks Note that this does NOT capture the passed in AMQP_VALUE object, instead it clones + * the underlying AMQP_VALUE. This is why it takes a UniqueAmqpValueHandle as a parameter + * instead of a raw AMQP_VALUE - that ensures that someone will free the underlying AMQP_VALUE + * if needed. + */ + AmqpValue(_detail::UniqueAmqpValueHandle const& value); + AmqpValue(_detail::UniqueAmqpValueHandle&& value); _detail::UniqueAmqpValueHandle m_value; + friend class _detail::AmqpValueFactory; }; std::ostream& operator<<(std::ostream& os, AmqpValue const& value); @@ -590,6 +570,14 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { + class AmqpValueFactory final { + public: + static AmqpValue FromUamqp(UniqueAmqpValueHandle const& value); + static AmqpValue FromUamqp(UniqueAmqpValueHandle&& value); + // Returns the internal AMQP value handle, without referencing it. + static AMQP_VALUE_DATA_TAG* ToUamqp(AmqpValue const& value); + }; + /** @brief Base type for AMQP collection types. * * Provides convenient conversions for STL collection types to enable classes derived from @@ -625,19 +613,23 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace explicit operator T const &() const { return m_value; } /** @brief Convert this collection type to an AMQP value.*/ - AmqpValue AsAmqpValue() const { return AmqpValue{UniqueAmqpValueHandle{*this}}; } + AmqpValue AsAmqpValue() const + { + return _detail::AmqpValueFactory::FromUamqp(UniqueAmqpValueHandle{*this}); + } /** @brief Returns the size of the underlying value.*/ inline typename T::size_type size() const { return m_value.size(); } - /// @brief Array accessor operator. - /// @param pos Position of an element in the container. - /// @return element value. + /** @brief Array accessor operator. + * @param pos Position of an element in the container. + * @return element value. + */ const typename T::value_type& operator[](const typename T::size_type pos) const noexcept { return m_value.operator[](pos); } - void push_back(typename T::value_type&& val) { m_value.push_back(val); } + void push_back(typename T::value_type&& val) { m_value.push_back(std::move(val)); } typename T::const_iterator begin() const noexcept { return m_value.begin(); } typename T::const_iterator end() const noexcept { return m_value.end(); } size_t find(T const& val) noexcept { return m_value.find(val); } @@ -702,7 +694,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP array value to capture. */ - AmqpArray(AMQP_VALUE_DATA_TAG* const value); + AmqpArray(AmqpValue const& value); }; std::ostream& operator<<(std::ostream& os, AmqpArray const& value); @@ -745,7 +737,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP array value to capture. */ - AmqpMap(AMQP_VALUE_DATA_TAG* const value); + AmqpMap(AmqpValue const& value); virtual ~AmqpMap() = default; @@ -755,7 +747,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { */ decltype(m_value)::mapped_type& operator[](decltype(m_value)::key_type&& keyVal) { - return m_value.operator[](keyVal); + return m_value.operator[](std::move(keyVal)); } /** @brief Insert a new key/value pair into the map. @@ -767,7 +759,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { template std::pair emplace(ValueTypes&&... values) { - return m_value.emplace(values...); + return m_value.emplace(std::forward(values)...); } }; std::ostream& operator<<(std::ostream& os, AmqpMap const& value); @@ -797,17 +789,14 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { /** @brief Move assignment operator */ AmqpList& operator=(AmqpList&& other) noexcept = default; - /** @brief Construct a new AmqpList object from an existing uAMQP AMQP_VALUE item + /** @brief Construct a new AmqpList object from an existing AmqpValue item * * @remarks Note that this does NOT capture the passed in AMQP_VALUE object, the caller is * responsible for freeing that object. * - * @remarks This is an internal accessor and should never be used by code outside the AMQP - * implementation. - * * @param value - the AMQP array value to capture. */ - AmqpList(AMQP_VALUE_DATA_TAG* const value); + AmqpList(AmqpValue const& value); }; std::ostream& operator<<(std::ostream& os, AmqpList const& value); @@ -856,7 +845,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP "binary" value to capture. */ - AmqpBinaryData(AMQP_VALUE_DATA_TAG* const value); + AmqpBinaryData(AmqpValue const& value); }; std::ostream& operator<<(std::ostream& os, AmqpBinaryData const& value); @@ -903,7 +892,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP "binary" value to capture. */ - AmqpSymbol(AMQP_VALUE_DATA_TAG* const value); + AmqpSymbol(AmqpValue const& value); /** @brief Compare two AMQP symbols for equality. * @@ -949,7 +938,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP "binary" value to capture. */ - AmqpTimestamp(AMQP_VALUE_DATA_TAG* const value); + AmqpTimestamp(AmqpValue const& value); /** @brief Copy constructor */ AmqpTimestamp(const AmqpTimestamp& other) = default; @@ -978,7 +967,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @return An AmqpValue containing this AmqpTimestamp. */ - AmqpValue AsAmqpValue() const { return AmqpValue{_detail::UniqueAmqpValueHandle{*this}}; } + AmqpValue AsAmqpValue() const + { + return _detail::AmqpValueFactory::FromUamqp(_detail::UniqueAmqpValueHandle{*this}); + } /** * @brief Convert an AmqpTimestamp instance to a std::chrono::milliseconds. @@ -1044,7 +1036,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP array value to capture. */ - AmqpComposite(AMQP_VALUE_DATA_TAG* const value); + AmqpComposite(AmqpValue const& value); /** @brief Compare this AmqpComposite value with another. * @@ -1071,14 +1063,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { */ AmqpValue const& GetDescriptor() const { return m_descriptor; } - /** - * @brief Convert an existing AmqpComposite to an AmqpValue. - */ - explicit operator AmqpValue() const - { - return static_cast<_detail::UniqueAmqpValueHandle>(*this); - } - protected: /** * @brief Convert an AmqpComposite instance to a uAMQP AMQP_VALUE. @@ -1089,7 +1073,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * @remarks Note that this returns a newly allocated AMQP_VALUE object which must be freed * by the caller. */ - operator _detail::UniqueAmqpValueHandle() const; + operator _detail::UniqueAmqpValueHandle() const override; private: AmqpValue m_descriptor; @@ -1116,6 +1100,33 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { */ AmqpDescribed(AmqpSymbol const& descriptor, AmqpValue const& value); + /** @brief Construct a new AmqpDescribed object by moving the contents of another AmqpDescribed + * object. + * + * @param other - the AmqpDescribed object to move. + */ + AmqpDescribed(AmqpDescribed&& other) noexcept = default; + + /** @brief Copy constructor for AmqpDescribed. + * + * @param other - the AmqpDescribed object to copy. + */ + AmqpDescribed(const AmqpDescribed& other) = default; + + /** @brief Move assignment operator for AmqpDescribed. + * + * @param other - the AmqpDescribed object to move. + * @returns reference to this AmqpDescribed object. + */ + AmqpDescribed& operator=(AmqpDescribed&& other) noexcept = default; + + /** @brief Copy assignment operator for AmqpDescribed. + * + * @param other - the AmqpDescribed object to copy. + * @returns reference to this AmqpDescribed object. + */ + AmqpDescribed& operator=(const AmqpDescribed& other) = default; + ~AmqpDescribed() = default; /** @brief Construct a new AmqpDescribed object with a 64bit descriptor. @@ -1136,7 +1147,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { * * @param value - the AMQP array value to capture. */ - AmqpDescribed(AMQP_VALUE_DATA_TAG* const value); + AmqpDescribed(AmqpValue const& value); /** @brief Compare this AmqpDescribed value with another. * diff --git a/sdk/core/azure-core-amqp/samples/internal/eventhub_get_properties_sample/eventhub_get_eventhub_properties_sample.cpp b/sdk/core/azure-core-amqp/samples/internal/eventhub_get_properties_sample/eventhub_get_eventhub_properties_sample.cpp index fbc3d1b89c..d653afaab7 100644 --- a/sdk/core/azure-core-amqp/samples/internal/eventhub_get_properties_sample/eventhub_get_eventhub_properties_sample.cpp +++ b/sdk/core/azure-core-amqp/samples/internal/eventhub_get_properties_sample/eventhub_get_eventhub_properties_sample.cpp @@ -50,17 +50,17 @@ EventHubProperties GetEventHubProperties( EventHubProperties properties; if (result.Status == Azure::Core::Amqp::_internal::ManagementOperationStatus::Error) { - std::cerr << "Error: " << result.Message.ApplicationProperties["status-description"]; + std::cerr << "Error: " << result.Message->ApplicationProperties["status-description"]; } else { std::cout << "Management endpoint properties message: " << result.Message; - if (result.Message.BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) + if (result.Message->BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) { throw std::runtime_error("Unexpected body type"); } - Azure::Core::Amqp::Models::AmqpValue body = result.Message.GetBodyAsAmqpValue(); + Azure::Core::Amqp::Models::AmqpValue body = result.Message->GetBodyAsAmqpValue(); if (body.GetType() != Azure::Core::Amqp::Models::AmqpValueType::Map) { throw std::runtime_error("Unexpected body type"); @@ -128,12 +128,12 @@ std::tuple GetPartitionProperties( else { std::cout << "Partition properties message: " << result.Message; - if (result.Message.BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) + if (result.Message->BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) { throw std::runtime_error("Unexpected body type"); } - auto body = result.Message.GetBodyAsAmqpValue(); + auto body = result.Message->GetBodyAsAmqpValue(); if (body.GetType() != Azure::Core::Amqp::Models::AmqpValueType::Map) { throw std::runtime_error("Unexpected body type"); diff --git a/sdk/core/azure-core-amqp/samples/internal/eventhub_sas_reader_sample/eventhub_sas_reader_sample.cpp b/sdk/core/azure-core-amqp/samples/internal/eventhub_sas_reader_sample/eventhub_sas_reader_sample.cpp index a0cced541b..01b57de524 100644 --- a/sdk/core/azure-core-amqp/samples/internal/eventhub_sas_reader_sample/eventhub_sas_reader_sample.cpp +++ b/sdk/core/azure-core-amqp/samples/internal/eventhub_sas_reader_sample/eventhub_sas_reader_sample.cpp @@ -56,7 +56,7 @@ int main() auto message = receiver.WaitForIncomingMessage(); if (message.first) { - std::cout << "Received message: " << message.first.Value() << std::endl; + std::cout << "Received message: " << *message.first << std::endl; } else { diff --git a/sdk/core/azure-core-amqp/samples/internal/eventhub_token_reader_sample/eventhub_token_reader_sample.cpp b/sdk/core/azure-core-amqp/samples/internal/eventhub_token_reader_sample/eventhub_token_reader_sample.cpp index 7cb8e3354d..8c103c40fd 100644 --- a/sdk/core/azure-core-amqp/samples/internal/eventhub_token_reader_sample/eventhub_token_reader_sample.cpp +++ b/sdk/core/azure-core-amqp/samples/internal/eventhub_token_reader_sample/eventhub_token_reader_sample.cpp @@ -56,7 +56,7 @@ int main() auto message = receiver.WaitForIncomingMessage(); if (message.first) { - std::cout << "Received message: " << message.first.Value() << std::endl; + std::cout << "Received message: " << *message.first << std::endl; } else { diff --git a/sdk/core/azure-core-amqp/samples/internal/local_server_sample/local_server_sample.cpp b/sdk/core/azure-core-amqp/samples/internal/local_server_sample/local_server_sample.cpp index 2156be0bad..7cd512e211 100644 --- a/sdk/core/azure-core-amqp/samples/internal/local_server_sample/local_server_sample.cpp +++ b/sdk/core/azure-core-amqp/samples/internal/local_server_sample/local_server_sample.cpp @@ -11,6 +11,7 @@ #include #include +#include #include using namespace Azure::Core::Amqp::_internal; @@ -47,7 +48,7 @@ class SampleEvents : public ConnectionEvents, // Wait for incoming messages. This method is somewhat more complicated because it // needs to wait on multiple waiters (both the connection and the transport). template - Azure::Core::Amqp::Models::AmqpMessage WaitForIncomingMessage( + std::shared_ptr WaitForIncomingMessage( Azure::Core::Context const& context, Waiters&... waiters) { @@ -60,7 +61,8 @@ class SampleEvents : public ConnectionEvents, Common::_internal::AsyncOperationQueue> m_connectionQueue; Common::_internal::AsyncOperationQueue m_sessionQueue; Common::_internal::AsyncOperationQueue> m_messageReceiverQueue; - Common::_internal::AsyncOperationQueue m_messageQueue; + Common::_internal::AsyncOperationQueue> + m_messageQueue; virtual void OnSocketAccepted(std::shared_ptr transport) override { @@ -142,7 +144,7 @@ class SampleEvents : public ConnectionEvents, } virtual Azure::Core::Amqp::Models::AmqpValue OnMessageReceived( Azure::Core::Amqp::_internal::MessageReceiver const&, - Azure::Core::Amqp::Models::AmqpMessage const& message) override + std::shared_ptr const& message) override { m_messageQueue.CompleteOperation(message); return Azure::Core::Amqp::Models::_internal::Messaging::DeliveryAccepted(); diff --git a/sdk/core/azure-core-amqp/src/amqp/claim_based_security.cpp b/sdk/core/azure-core-amqp/src/amqp/claim_based_security.cpp index df54e78d2f..1a5f210cff 100644 --- a/sdk/core/azure-core-amqp/src/amqp/claim_based_security.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/claim_based_security.cpp @@ -131,7 +131,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { default: throw std::runtime_error("Unknown management operation status."); } - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Informational) << "CBS PutToken result: " << cbsResult << " status code: " << result.StatusCode << " Error: " << result.Error.Description << "."; return std::make_tuple(cbsResult, result.StatusCode, result.Error.Description); @@ -188,7 +188,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { void ClaimsBasedSecurityImpl::OnError(Models::_internal::AmqpError const& error) { - Log::Stream(Logger::Level::Error) << "AMQP Error processing ClaimsBasedSecurity: " << error; + Log::Stream(Logger::Level::Warning) << "AMQP Error processing ClaimsBasedSecurity: " << error; } }}}} // namespace Azure::Core::Amqp::_detail diff --git a/sdk/core/azure-core-amqp/src/amqp/connection.cpp b/sdk/core/azure-core-amqp/src/amqp/connection.cpp index 5d16a85225..4a02d6ed73 100644 --- a/sdk/core/azure-core-amqp/src/amqp/connection.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/connection.cpp @@ -269,7 +269,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { { throw std::runtime_error("Failed to set max frame size."); } - if (connection_set_properties(m_connection.get(), m_options.Properties.AsAmqpValue())) + if (connection_set_properties( + m_connection.get(), + Models::_detail::AmqpValueFactory::ToUamqp(m_options.Properties.AsAmqpValue()))) { throw std::runtime_error("Failed to set connection properties."); } @@ -509,7 +511,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { m_connection.get(), (condition.empty() ? nullptr : condition.c_str()), (description.empty() ? nullptr : description.c_str()), - info)) + Models::_detail::AmqpValueFactory::ToUamqp(info))) { throw std::runtime_error("Could not close connection."); } @@ -522,7 +524,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { uint32_t maxSize; if (connection_get_max_frame_size(m_connection.get(), &maxSize)) { - throw std::runtime_error("COuld not get max frame size."); + throw std::runtime_error("Could not get max frame size."); } return maxSize; } @@ -532,7 +534,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { uint16_t maxChannel; if (connection_get_channel_max(m_connection.get(), &maxChannel)) { - throw std::runtime_error("COuld not get channel max."); + throw std::runtime_error("Could not get channel max."); } return maxChannel; } @@ -552,9 +554,11 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { AMQP_VALUE value; if (connection_get_properties(m_connection.get(), &value)) { - throw std::runtime_error("COuld not get properties."); + throw std::runtime_error("Could not get properties."); } - return Models::AmqpValue{Models::_detail::UniqueAmqpValueHandle{value}}.AsMap(); + return Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{value}) + .AsMap(); } uint32_t ConnectionImpl::GetRemoteMaxFrameSize() const diff --git a/sdk/core/azure-core-amqp/src/amqp/link.cpp b/sdk/core/azure-core-amqp/src/amqp/link.cpp index bbc8e02cf4..3e2154f8b5 100644 --- a/sdk/core/azure-core-amqp/src/amqp/link.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/link.cpp @@ -110,8 +110,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { *session, name.c_str(), role == _internal::SessionRole::Sender ? role_sender : role_receiver, - sourceValue, - targetValue); + Models::_detail::AmqpValueFactory::ToUamqp(sourceValue), + Models::_detail::AmqpValueFactory::ToUamqp(targetValue)); } LinkImpl::LinkImpl( @@ -130,8 +130,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { LinkEndpointFactory::Release(linkEndpoint), name.c_str(), role == _internal::SessionRole::Sender ? role_sender : role_receiver, - sourceValue, - targetValue); + Models::_detail::AmqpValueFactory::ToUamqp(sourceValue), + Models::_detail::AmqpValueFactory::ToUamqp(targetValue)); } LinkImpl::~LinkImpl() noexcept @@ -299,7 +299,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { } void LinkImpl::SetAttachProperties(Models::AmqpValue properties) { - if (link_set_attach_properties(m_link, properties)) + if (link_set_attach_properties(m_link, Models::_detail::AmqpValueFactory::ToUamqp(properties))) { throw std::runtime_error("Could not set attach properties."); } @@ -314,7 +314,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { void LinkImpl::SetDesiredCapabilities(Models::AmqpValue desiredCapabilities) { - if (link_set_desired_capabilities(m_link, desiredCapabilities)) + if (link_set_desired_capabilities( + m_link, Models::_detail::AmqpValueFactory::ToUamqp(desiredCapabilities))) { throw std::runtime_error("Could not set desired capabilities."); } @@ -327,7 +328,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { { throw std::runtime_error("Could not convert field to header."); } - return Models::AmqpValue{Models::_detail::UniqueAmqpValueHandle{desiredCapabilitiesVal}}; + return Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{desiredCapabilitiesVal}); } void LinkImpl::SubscribeToDetachEvent(OnLinkDetachEvent onLinkDetach) @@ -387,7 +389,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { close, (condition.empty() ? nullptr : condition.c_str()), (description.empty() ? nullptr : description.c_str()), - info)) + Models::_detail::AmqpValueFactory::ToUamqp(info))) { throw std::runtime_error("Could not set attach properties."); } diff --git a/sdk/core/azure-core-amqp/src/amqp/management.cpp b/sdk/core/azure-core-amqp/src/amqp/management.cpp index 5a58fc6fd1..b816a17463 100644 --- a/sdk/core/azure-core-amqp/src/amqp/management.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/management.cpp @@ -118,7 +118,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { } catch (std::runtime_error const& e) { - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Exception thrown opening message sender and receiver." << e.what(); return _internal::ManagementOpenStatus::Error; } @@ -131,6 +131,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { _internal::ManagementOpenStatus rv = std::get<0>(*result); if (rv != _internal::ManagementOpenStatus::Ok) { + Log::Stream(Logger::Level::Warning) << "Management operation failed to open."; m_messageSender->Close(); m_messageSenderOpen = false; m_messageReceiver->Close(); @@ -177,7 +178,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { rv.Status = _internal::ManagementOperationStatus::Error; rv.StatusCode = 500; rv.Error = std::get<1>(sendResult); - rv.Message = Models::AmqpMessage{}; + rv.Message = nullptr; return rv; } auto result = m_messageQueue.WaitForResult(context); @@ -256,8 +257,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { case _internal::MessageSenderState::Idle: case _internal::MessageSenderState::Closing: case _internal::MessageSenderState::Error: - Log::Stream(Logger::Level::Error) << "Message Sender Changed State to " << newState - << " while management client is opening"; + Log::Stream(Logger::Level::Warning) << "Message Sender Changed State to " << newState + << " while management client is opening"; SetState(ManagementState::Closing); m_openCompleteQueue.CompleteOperation(_internal::ManagementOpenStatus::Error); break; @@ -271,8 +272,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { case _internal::MessageSenderState::Idle: case _internal::MessageSenderState::Closing: case _internal::MessageSenderState::Error: - Log::Stream(Logger::Level::Error) << "Message Sender Changed State to " << newState - << " while management client is open"; + Log::Stream(Logger::Level::Warning) << "Message Sender Changed State to " << newState + << " while management client is open"; SetState(ManagementState::Closing); if (m_eventHandler) { @@ -292,8 +293,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { case _internal::MessageSenderState::Open: case _internal::MessageSenderState::Opening: case _internal::MessageSenderState::Error: - Log::Stream(Logger::Level::Error) << "Message Sender Changed State to " << newState - << " while management client is closing"; + Log::Stream(Logger::Level::Warning) << "Message Sender Changed State to " << newState + << " while management client is closing"; SetState(ManagementState::Closing); if (m_eventHandler) { @@ -308,7 +309,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { break; case ManagementState::Idle: case ManagementState::Error: - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message sender state changed to " << newState << " when management client is in the error state, ignoring."; break; @@ -317,7 +318,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { void ManagementClientImpl::OnMessageSenderDisconnected(Models::_internal::AmqpError const& error) { - Log::Stream(Logger::Level::Error) << "Message sender disconnected: " << error << std::endl; + Log::Stream(Logger::Level::Warning) << "Message sender disconnected: " << error << std::endl; SetState(ManagementState::Error); if (m_eventHandler) { @@ -332,7 +333,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { { if (newState == oldState) { - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Verbose) << "OnMessageReceiverStateChanged: newState == oldState" << std::endl; return; } @@ -367,7 +368,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { case _internal::MessageReceiverState::Idle: case _internal::MessageReceiverState::Closing: case _internal::MessageReceiverState::Error: - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message Receiver Changed State to " << static_cast::type>(newState) << " while management client is opening"; @@ -384,7 +385,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { case _internal::MessageReceiverState::Idle: case _internal::MessageReceiverState::Closing: case _internal::MessageReceiverState::Error: - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message Sender Changed State to " << static_cast::type>(newState) << " while management client is open"; @@ -407,7 +408,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { case _internal::MessageReceiverState::Open: case _internal::MessageReceiverState::Opening: case _internal::MessageReceiverState::Error: - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message Sender Changed State to " << static_cast::type>(newState) << " while management client is closing"; @@ -425,7 +426,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { break; case ManagementState::Idle: case ManagementState::Error: - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message sender state changed to " << static_cast::type>(newState) << " when management client is in the error state, ignoring."; @@ -441,7 +442,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { error.Condition = Models::_internal::AmqpErrorCondition(condition); error.Description = "Message Delivery Rejected: " + description; - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Indicate Management Error: " << condition << " - " << description; if (m_eventHandler) { @@ -451,37 +452,37 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { // Complete any outstanding receives with an error. m_messageQueue.CompleteOperation( - _internal::ManagementOperationStatus::Error, 500, error, Models::AmqpMessage()); + _internal::ManagementOperationStatus::Error, 500, error, nullptr); return Models::_internal::Messaging::DeliveryRejected(condition, description, {}); } Models::AmqpValue ManagementClientImpl::OnMessageReceived( _internal::MessageReceiver const&, - Models::AmqpMessage const& message) + std::shared_ptr const& message) { - if (message.ApplicationProperties.empty()) + if (message->ApplicationProperties.empty()) { return IndicateError( Models::_internal::AmqpErrorCondition::InternalError.ToString(), "Received message does not have application properties."); } - if (!message.Properties.CorrelationId.HasValue()) + if (!message->Properties.CorrelationId.HasValue()) { return IndicateError( Models::_internal::AmqpErrorCondition::InternalError.ToString(), "Received message correlation ID not found."); } - else if (message.Properties.CorrelationId.Value().GetType() != Models::AmqpValueType::Ulong) + else if (message->Properties.CorrelationId.Value().GetType() != Models::AmqpValueType::Ulong) { return IndicateError( Models::_internal::AmqpErrorCondition::InternalError.ToString(), "Received message correlation ID is not a ulong."); } - uint64_t correlationId = message.Properties.CorrelationId.Value(); + uint64_t correlationId = message->Properties.CorrelationId.Value(); - auto statusCodeMap = message.ApplicationProperties.find(m_options.ExpectedStatusCodeKeyName); - if (statusCodeMap == message.ApplicationProperties.end()) + auto statusCodeMap = message->ApplicationProperties.find(m_options.ExpectedStatusCodeKeyName); + if (statusCodeMap == message->ApplicationProperties.end()) { return IndicateError( Models::_internal::AmqpErrorCondition::InternalError.ToString(), @@ -498,9 +499,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { // If the message has a status description, remember it. auto statusDescription - = message.ApplicationProperties.find(m_options.ExpectedStatusDescriptionKeyName); + = message->ApplicationProperties.find(m_options.ExpectedStatusDescriptionKeyName); std::string description; - if (statusDescription != message.ApplicationProperties.end()) + if (statusDescription != message->ApplicationProperties.end()) { if (statusDescription->second.GetType() != Models::AmqpValueType::String) { @@ -548,7 +549,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { void ManagementClientImpl::OnMessageReceiverDisconnected( Models::_internal::AmqpError const& error) { - Log::Stream(Logger::Level::Error) << "Message receiver disconnected: " << error << std::endl; + Log::Stream(Logger::Level::Warning) << "Message receiver disconnected: " << error << std::endl; SetState(ManagementState::Error); if (m_eventHandler) { diff --git a/sdk/core/azure-core-amqp/src/amqp/message_receiver.cpp b/sdk/core/azure-core-amqp/src/amqp/message_receiver.cpp index 27e4b06c6b..c7ad975819 100644 --- a/sdk/core/azure-core-amqp/src/amqp/message_receiver.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/message_receiver.cpp @@ -60,7 +60,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { } } std::string MessageReceiver::GetSourceName() const { return m_impl->GetSourceName(); } - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> MessageReceiver::WaitForIncomingMessage(Azure::Core::Context const& context) { if (m_impl) @@ -76,7 +76,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _internal { } } - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> MessageReceiver::TryWaitForIncomingMessage() { if (m_impl) @@ -182,7 +182,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { m_eventHandler->OnMessageReceiverDisconnected(error); } // Log that an error occurred. - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message receiver link detached: " + error.Condition.ToString() << ": " << error.Description; @@ -222,7 +222,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { // the message receiver is open before attempting to process the incoming message. if (receiver->m_receiverOpen) { - auto incomingMessage(Models::_internal::AmqpMessageFactory::FromUamqp(message)); + auto incomingMessage(Models::_detail::AmqpMessageFactory::FromUamqp(message)); Models::AmqpValue rv; if (receiver->m_eventHandler) { @@ -234,22 +234,24 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { { rv = receiver->OnMessageReceived(incomingMessage); } - return rv.Release(); + return amqpvalue_clone(Models::_detail::AmqpValueFactory::ToUamqp(rv)); } - return Models::_internal::Messaging::DeliveryRejected( - Models::_internal::AmqpErrorCondition::ConnectionForced.ToString(), - "Message Receiver is closed.", - {}); + return amqpvalue_clone( + Models::_detail::AmqpValueFactory::ToUamqp(Models::_internal::Messaging::DeliveryRejected( + Models::_internal::AmqpErrorCondition::ConnectionForced.ToString(), + "Message Receiver is closed.", + {}))); } - Models::AmqpValue MessageReceiverImpl::OnMessageReceived(Models::AmqpMessage message) + Models::AmqpValue MessageReceiverImpl::OnMessageReceived( + std::shared_ptr const& message) { m_messageQueue.CompleteOperation(message, Models::_internal::AmqpError{}); return Models::_internal::Messaging::DeliveryAccepted(); } - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> MessageReceiverImpl::WaitForIncomingMessage(Context const& context) { if (m_eventHandler) @@ -260,8 +262,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { auto result = m_messageQueue.WaitForResult(context); if (result) { - std::pair, Models::_internal::AmqpError> rv; - Models::AmqpMessage message{std::move(std::get<0>(*result))}; + std::pair, Models::_internal::AmqpError> rv; + std::shared_ptr message{std::move(std::get<0>(*result))}; if (message) { rv.first = std::move(message); @@ -274,7 +276,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { throw Azure::Core::OperationCancelledException("Receive Operation was cancelled."); } } - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> MessageReceiverImpl::TryWaitForIncomingMessage() { if (m_eventHandler) @@ -285,8 +287,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { auto result = m_messageQueue.TryWaitForResult(); if (result) { - std::pair, Models::_internal::AmqpError> rv; - Models::AmqpMessage message{std::move(std::get<0>(*result))}; + std::pair, Models::_internal::AmqpError> rv; + std::shared_ptr message{std::move(std::get<0>(*result))}; if (message) { rv.first = std::move(message); diff --git a/sdk/core/azure-core-amqp/src/amqp/message_sender.cpp b/sdk/core/azure-core-amqp/src/amqp/message_sender.cpp index 1afffd7dcc..6f4e5ef51b 100644 --- a/sdk/core/azure-core-amqp/src/amqp/message_sender.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/message_sender.cpp @@ -163,7 +163,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { m_events->OnMessageSenderDisconnected(error); } // Log that an error occurred. - Log::Stream(Logger::Level::Error) + Log::Stream(Logger::Level::Warning) << "Message sender link detached: " << error.Condition.ToString() << ": " << error.Description; @@ -412,7 +412,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { } // Reference disposition so that we don't over-release when the AmqpValue passed to OnComplete // is destroyed. - onComplete(result, Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(disposition)}); + onComplete( + result, + Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(disposition)})); } }; @@ -426,7 +429,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { RewriteSendComplete>>(onSendComplete)); auto result = messagesender_send_async( m_messageSender.get(), - Models::_internal::AmqpMessageFactory::ToUamqp(message).get(), + Models::_detail::AmqpMessageFactory::ToUamqp(message).get(), std::remove_pointer::type::OnOperationFn, operation.release(), 0 /*timeout*/); @@ -474,9 +477,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { } Models::AmqpValue firstState{deliveryStatusAsList[0]}; ERROR_HANDLE errorHandle; - if (!amqpvalue_get_error(firstState, &errorHandle)) + if (!amqpvalue_get_error( + Models::_detail::AmqpValueFactory::ToUamqp(firstState), &errorHandle)) { - Models::_internal::UniqueAmqpErrorHandle uniqueError{ + Models::_detail::UniqueAmqpErrorHandle uniqueError{ errorHandle}; // This will free the error handle when it goes out of scope. error = Models::_internal::AmqpErrorFactory::FromUamqp(errorHandle); } diff --git a/sdk/core/azure-core-amqp/src/amqp/private/management_impl.hpp b/sdk/core/azure-core-amqp/src/amqp/private/management_impl.hpp index c172425776..4a5d288e27 100644 --- a/sdk/core/azure-core-amqp/src/amqp/private/management_impl.hpp +++ b/sdk/core/azure-core-amqp/src/amqp/private/management_impl.hpp @@ -110,24 +110,24 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { _internal::ManagementOperationStatus, std::uint32_t, Models::_internal::AmqpError, - Models::AmqpMessage> + std::shared_ptr> m_messageQueue; // Inherited via MessageSenderEvents - virtual void OnMessageSenderStateChanged( + void OnMessageSenderStateChanged( _internal::MessageSender const& sender, _internal::MessageSenderState newState, _internal::MessageSenderState oldState) override; - virtual void OnMessageSenderDisconnected(Models::_internal::AmqpError const& error) override; + void OnMessageSenderDisconnected(Models::_internal::AmqpError const& error) override; // Inherited via MessageReceiverEvents - virtual void OnMessageReceiverStateChanged( + void OnMessageReceiverStateChanged( _internal::MessageReceiver const& receiver, _internal::MessageReceiverState newState, _internal::MessageReceiverState oldState) override; - virtual Models::AmqpValue OnMessageReceived( + Models::AmqpValue OnMessageReceived( _internal::MessageReceiver const& receiver, - Models::AmqpMessage const& message) override; - virtual void OnMessageReceiverDisconnected(Models::_internal::AmqpError const& error) override; + std::shared_ptr const& message) override; + void OnMessageReceiverDisconnected(Models::_internal::AmqpError const& error) override; }; }}}} // namespace Azure::Core::Amqp::_detail diff --git a/sdk/core/azure-core-amqp/src/amqp/private/message_receiver_impl.hpp b/sdk/core/azure-core-amqp/src/amqp/private/message_receiver_impl.hpp index 4102e68a7d..8766c8a414 100644 --- a/sdk/core/azure-core-amqp/src/amqp/private/message_receiver_impl.hpp +++ b/sdk/core/azure-core-amqp/src/amqp/private/message_receiver_impl.hpp @@ -70,10 +70,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { std::string GetLinkName() const; std::string GetSourceName() const { return static_cast(m_source.GetAddress()); } - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> WaitForIncomingMessage(Context const& context); - std::pair, Models::_internal::AmqpError> + std::pair, Models::_internal::AmqpError> TryWaitForIncomingMessage(); private: @@ -87,7 +87,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { _internal::MessageReceiverState m_currentState{}; Azure::Core::Amqp::Common::_internal:: - AsyncOperationQueue + AsyncOperationQueue, Models::_internal::AmqpError> m_messageQueue; #if RECEIVER_SYNCHRONOUS_CLOSE @@ -102,7 +102,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { static AMQP_VALUE OnMessageReceivedFn(const void* context, MESSAGE_HANDLE message); - virtual Models::AmqpValue OnMessageReceived(Models::AmqpMessage message); + virtual Models::AmqpValue OnMessageReceived( + std::shared_ptr const& message); static void OnMessageReceiverStateChangedFn( const void* context, diff --git a/sdk/core/azure-core-amqp/src/amqp/session.cpp b/sdk/core/azure-core-amqp/src/amqp/session.cpp index c7610df7d2..be13a690a8 100644 --- a/sdk/core/azure-core-amqp/src/amqp/session.cpp +++ b/sdk/core/azure-core-amqp/src/amqp/session.cpp @@ -243,9 +243,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace _detail { name, role == role_receiver ? Azure::Core::Amqp::_internal::SessionRole::Receiver : Azure::Core::Amqp::_internal::SessionRole::Sender, - Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(source)}, - Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(target)}, - Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(properties)}); + Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(source)}), + Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(target)}), + Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(properties)})); } else { diff --git a/sdk/core/azure-core-amqp/src/common/global_state.cpp b/sdk/core/azure-core-amqp/src/common/global_state.cpp index 4b576a708f..e2dfa5b5a4 100644 --- a/sdk/core/azure-core-amqp/src/common/global_state.cpp +++ b/sdk/core/azure-core-amqp/src/common/global_state.cpp @@ -45,7 +45,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Common { namespace switch (logCategory) { case AZ_LOG_ERROR: - logLevel = Logger::Level::Error; + logLevel = Logger::Level::Warning; break; case AZ_LOG_INFO: logLevel = Logger::Level::Informational; diff --git a/sdk/core/azure-core-amqp/src/models/amqp_error.cpp b/sdk/core/azure-core-amqp/src/models/amqp_error.cpp index 73408c2feb..1bcc460ed9 100644 --- a/sdk/core/azure-core-amqp/src/models/amqp_error.cpp +++ b/sdk/core/azure-core-amqp/src/models/amqp_error.cpp @@ -44,7 +44,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { // error_get_info returns the AMQP value in place, so we clone it before passing it to the // UniqueAmqpValueHandle. - rv.Info = AmqpValue{Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(info)}}.AsMap(); + rv.Info = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(info)}) + .AsMap(); } return rv; @@ -52,7 +54,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace AmqpValue AmqpErrorFactory::ToAmqp(AmqpError const& error) { - UniqueAmqpErrorHandle errorHandle(error_create(error.Condition.ToString().data())); + _detail::UniqueAmqpErrorHandle errorHandle(error_create(error.Condition.ToString().data())); if (!error.Description.empty()) { error_set_description(errorHandle.get(), error.Description.data()); @@ -60,14 +62,14 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace if (!error.Info.empty()) { AmqpValue infoValue(error.Info.AsAmqpValue()); - error_set_info(errorHandle.get(), infoValue); + error_set_info(errorHandle.get(), _detail::AmqpValueFactory::ToUamqp(infoValue)); } // amqpvalue_create_error clones the error handle, so we remember it separately. _detail::UniqueAmqpValueHandle handleAsValue{amqpvalue_create_error(errorHandle.get())}; // The AmqpValue constructor will clone the handle passed into it. // The UniqueAmqpValueHandle will take care of freeing the cloned handle. - return handleAsValue; + return _detail::AmqpValueFactory::FromUamqp(handleAsValue); } std::ostream& operator<<(std::ostream& os, AmqpError const& error) { diff --git a/sdk/core/azure-core-amqp/src/models/amqp_header.cpp b/sdk/core/azure-core-amqp/src/models/amqp_header.cpp index 2521944537..7f8fb5e9d2 100644 --- a/sdk/core/azure-core-amqp/src/models/amqp_header.cpp +++ b/sdk/core/azure-core-amqp/src/models/amqp_header.cpp @@ -29,7 +29,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { : true); } - MessageHeader _internal::MessageHeaderFactory::FromUamqp( + MessageHeader _detail::MessageHeaderFactory::FromUamqp( _detail::UniqueMessageHeaderHandle const& handle) { MessageHeader rv; @@ -64,7 +64,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return rv; } - _detail::UniqueMessageHeaderHandle _internal::MessageHeaderFactory::ToUamqp( + _detail::UniqueMessageHeaderHandle _detail::MessageHeaderFactory::ToUamqp( MessageHeader const& header) { _detail::UniqueMessageHeaderHandle rv{header_create()}; @@ -129,19 +129,19 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { || (DeliveryCount != 0); } - size_t MessageHeader::GetSerializedSize(MessageHeader const& properties) + size_t MessageHeader::GetSerializedSize(MessageHeader const& header) { - auto handle = _internal::MessageHeaderFactory::ToUamqp(properties); - AmqpValue propertiesAsValue{ - Models::_detail::UniqueAmqpValueHandle{amqpvalue_create_header(handle.get())}}; + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + AmqpValue propertiesAsValue{_detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_create_header(handle.get())})}; return AmqpValue::GetSerializedSize(propertiesAsValue); } std::vector MessageHeader::Serialize(MessageHeader const& header) { - auto handle = _internal::MessageHeaderFactory::ToUamqp(header); - AmqpValue headerAsValue{ - Models::_detail::UniqueAmqpValueHandle{amqpvalue_create_header(handle.get())}}; + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + AmqpValue headerAsValue{_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_create_header(handle.get())})}; return Models::AmqpValue::Serialize(headerAsValue); } @@ -149,13 +149,13 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { { AmqpValue value{AmqpValue::Deserialize(data, size)}; HEADER_HANDLE handle; - if (amqpvalue_get_header(value, &handle)) + if (amqpvalue_get_header(_detail::AmqpValueFactory::ToUamqp(value), &handle)) { throw std::runtime_error("Could not convert value to AMQP Header."); } _detail::UniqueMessageHeaderHandle uniqueHandle{handle}; handle = nullptr; - return _internal::MessageHeaderFactory::FromUamqp(uniqueHandle); + return _detail::MessageHeaderFactory::FromUamqp(uniqueHandle); } }}}} // namespace Azure::Core::Amqp::Models diff --git a/sdk/core/azure-core-amqp/src/models/amqp_message.cpp b/sdk/core/azure-core-amqp/src/models/amqp_message.cpp index 4e913bcdc7..eaaa7f6e64 100644 --- a/sdk/core/azure-core-amqp/src/models/amqp_message.cpp +++ b/sdk/core/azure-core-amqp/src/models/amqp_message.cpp @@ -55,21 +55,17 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return nullptr; } } // namespace - AmqpMessage _internal::AmqpMessageFactory::FromUamqp(UniqueMessageHandle const& message) - { - return FromUamqp(message.get()); - } - AmqpMessage _internal::AmqpMessageFactory::FromUamqp(MESSAGE_INSTANCE_TAG* message) + std::shared_ptr _detail::AmqpMessageFactory::FromUamqp(MESSAGE_INSTANCE_TAG* message) { if (message == nullptr) { return nullptr; } - AmqpMessage rv; - rv.Header = _internal::MessageHeaderFactory::FromUamqp(GetHeaderFromMessage(message)); - rv.Properties - = _internal::MessagePropertiesFactory::FromUamqp(GetPropertiesFromMessage(message)); + auto rv{std::make_shared()}; + rv->Header = _detail::MessageHeaderFactory::FromUamqp(GetHeaderFromMessage(message)); + rv->Properties + = _detail::MessagePropertiesFactory::FromUamqp(GetPropertiesFromMessage(message)); { delivery_annotations annotationsVal; @@ -77,21 +73,19 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!message_get_delivery_annotations(message, &annotationsVal) && annotationsVal != nullptr) { UniqueAmqpValueHandle deliveryAnnotations(annotationsVal); - auto deliveryMap = AmqpValue{deliveryAnnotations}.AsMap(); - rv.DeliveryAnnotations = deliveryMap; + auto deliveryMap + = Models::_detail::AmqpValueFactory::FromUamqp(deliveryAnnotations).AsMap(); + rv->DeliveryAnnotations = deliveryMap; } } { // message_get_message_annotations returns a clone of the message annotations. - AMQP_VALUE annotationVal; - if (!message_get_message_annotations(message, &annotationVal) && annotationVal) + AMQP_VALUE messageAnnotations{}; + if (!message_get_message_annotations(message, &messageAnnotations) && messageAnnotations) { - UniqueAmqpValueHandle messageAnnotations(annotationVal); - if (messageAnnotations) - { - auto messageMap = AmqpValue{messageAnnotations}.AsMap(); - rv.MessageAnnotations = messageMap; - } + rv->MessageAnnotations = Models::_detail::AmqpValueFactory::FromUamqp( + UniqueAmqpValueHandle{messageAnnotations}) + .AsMap(); } } { @@ -141,14 +135,15 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { { throw std::runtime_error("Application Properties must be a map?!"); } - auto appProperties = AmqpMap(value); + auto appProperties = AmqpMap(_detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)})); for (auto const& val : appProperties) { if (val.first.GetType() != AmqpValueType::String) { throw std::runtime_error("Key of Application Properties must be a string."); } - rv.ApplicationProperties.emplace( + rv->ApplicationProperties.emplace( std::make_pair(static_cast(val.first), val.second)); } } @@ -159,7 +154,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!message_get_delivery_tag(message, &deliveryTagVal)) { UniqueAmqpValueHandle deliveryTag(deliveryTagVal); - rv.DeliveryTag = AmqpValue{deliveryTag}; + rv->DeliveryTag = _detail::AmqpValueFactory::FromUamqp(deliveryTag); } } { @@ -168,8 +163,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { { UniqueAmqpValueHandle footerAnnotations(footerVal); footerVal = nullptr; - auto footerMap = AmqpValue{footerAnnotations}.AsMap(); - rv.Footer = footerMap; + auto footerMap = _detail::AmqpValueFactory::FromUamqp(footerAnnotations).AsMap(); + rv->Footer = footerMap; } } { @@ -180,7 +175,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { switch (bodyType) { case MESSAGE_BODY_TYPE_NONE: - rv.BodyType = MessageBodyType::None; + rv->BodyType = MessageBodyType::None; break; case MESSAGE_BODY_TYPE_DATA: { size_t dataCount; @@ -191,12 +186,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { BINARY_DATA binaryValue; if (!message_get_body_amqp_data_in_place(message, i, &binaryValue)) { - rv.m_binaryDataBody.push_back(AmqpBinaryData(std::vector( + rv->m_binaryDataBody.push_back(AmqpBinaryData(std::vector( binaryValue.bytes, binaryValue.bytes + binaryValue.length))); } } } - rv.BodyType = MessageBodyType::Data; + rv->BodyType = MessageBodyType::Data; } break; case MESSAGE_BODY_TYPE_SEQUENCE: { @@ -209,20 +204,22 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { AMQP_VALUE sequence; if (!message_get_body_amqp_sequence_in_place(message, i, &sequence)) { - rv.m_amqpSequenceBody.push_back(sequence); + rv->m_amqpSequenceBody.push_back(_detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(sequence)})); } } } - rv.BodyType = MessageBodyType::Sequence; + rv->BodyType = MessageBodyType::Sequence; } break; case MESSAGE_BODY_TYPE_VALUE: { AMQP_VALUE bodyValue; if (!message_get_body_amqp_value_in_place(message, &bodyValue)) { - rv.m_amqpValueBody = _detail::UniqueAmqpValueHandle{amqpvalue_clone(bodyValue)}; + rv->m_amqpValueBody = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(bodyValue)}); } - rv.BodyType = MessageBodyType::Value; + rv->BodyType = MessageBodyType::Value; } break; case MESSAGE_BODY_TYPE_INVALID: @@ -235,7 +232,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return rv; } - UniqueMessageHandle _internal::AmqpMessageFactory::ToUamqp(AmqpMessage const& message) + UniqueMessageHandle _detail::AmqpMessageFactory::ToUamqp(AmqpMessage const& message) { UniqueMessageHandle rv(message_create()); @@ -245,20 +242,21 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { throw std::runtime_error("Could not set destination message format."); } - if (message_set_header( - rv.get(), _internal::MessageHeaderFactory::ToUamqp(message.Header).get())) + if (message_set_header(rv.get(), _detail::MessageHeaderFactory::ToUamqp(message.Header).get())) { throw std::runtime_error("Could not set message header."); } if (message_set_properties( - rv.get(), _internal::MessagePropertiesFactory::ToUamqp(message.Properties).get())) + rv.get(), _detail::MessagePropertiesFactory::ToUamqp(message.Properties).get())) { throw std::runtime_error("Could not set message properties."); } if (!message.DeliveryAnnotations.empty()) { - if (message_set_delivery_annotations(rv.get(), message.DeliveryAnnotations.AsAmqpValue())) + if (message_set_delivery_annotations( + rv.get(), + _detail::AmqpValueFactory::ToUamqp(message.DeliveryAnnotations.AsAmqpValue()))) { throw std::runtime_error("Could not set delivery annotations."); } @@ -266,7 +264,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!message.MessageAnnotations.empty()) { - if (message_set_message_annotations(rv.get(), message.MessageAnnotations.AsAmqpValue())) + if (message_set_message_annotations( + rv.get(), + _detail::AmqpValueFactory::ToUamqp(message.MessageAnnotations.AsAmqpValue()))) { throw std::runtime_error("Could not set message annotations."); } @@ -287,7 +287,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } appProperties.emplace(val); } - if (message_set_application_properties(rv.get(), appProperties.AsAmqpValue())) + if (message_set_application_properties( + rv.get(), _detail::AmqpValueFactory::ToUamqp(appProperties.AsAmqpValue()))) { throw std::runtime_error("Could not set application properties."); } @@ -295,7 +296,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!message.DeliveryTag.IsNull()) { - if (message_set_delivery_tag(rv.get(), message.DeliveryTag)) + if (message_set_delivery_tag( + rv.get(), _detail::AmqpValueFactory::ToUamqp(message.DeliveryTag))) { throw std::runtime_error("Could not set delivery tag."); } @@ -303,7 +305,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!message.Footer.empty()) { - if (message_set_footer(rv.get(), message.Footer.AsAmqpValue())) + if (message_set_footer( + rv.get(), _detail::AmqpValueFactory::ToUamqp(message.Footer.AsAmqpValue()))) { throw std::runtime_error("Could not set message annotations."); } @@ -327,14 +330,16 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { case MessageBodyType::Sequence: for (auto const& sequenceVal : message.m_amqpSequenceBody) { - if (message_add_body_amqp_sequence(rv.get(), sequenceVal.AsAmqpValue())) + if (message_add_body_amqp_sequence( + rv.get(), _detail::AmqpValueFactory::ToUamqp(sequenceVal.AsAmqpValue()))) { throw std::runtime_error("Could not set message body AMQP sequence value."); } } break; case MessageBodyType::Value: - if (message_set_body_amqp_value(rv.get(), message.m_amqpValueBody)) + if (message_set_body_amqp_value( + rv.get(), _detail::AmqpValueFactory::ToUamqp(message.m_amqpValueBody))) { throw std::runtime_error("Could not set message body AMQP value."); } @@ -420,16 +425,18 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } if (!message.DeliveryAnnotations.empty()) { - AmqpValue deliveryAnnotations{Models::_detail::UniqueAmqpValueHandle{ - amqpvalue_create_delivery_annotations(message.DeliveryAnnotations.AsAmqpValue())}}; + AmqpValue deliveryAnnotations{_detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_create_delivery_annotations( + _detail::AmqpValueFactory::ToUamqp(message.DeliveryAnnotations.AsAmqpValue()))})}; auto serializedDeliveryAnnotations = AmqpValue::Serialize(deliveryAnnotations); rv.insert( rv.end(), serializedDeliveryAnnotations.begin(), serializedDeliveryAnnotations.end()); } if (!message.MessageAnnotations.empty()) { - AmqpValue messageAnnotations{Models::_detail::UniqueAmqpValueHandle{ - amqpvalue_create_message_annotations(message.MessageAnnotations.AsAmqpValue())}}; + AmqpValue messageAnnotations{_detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_create_message_annotations( + _detail::AmqpValueFactory::ToUamqp(message.MessageAnnotations.AsAmqpValue()))})}; auto serializedAnnotations = AmqpValue::Serialize(messageAnnotations); rv.insert(rv.end(), serializedAnnotations.begin(), serializedAnnotations.end()); } @@ -455,8 +462,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } appProperties.emplace(val); } - AmqpValue propertiesValue{Models::_detail::UniqueAmqpValueHandle{ - amqpvalue_create_application_properties(appProperties.AsAmqpValue())}}; + AmqpValue propertiesValue{Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_create_application_properties( + Models::_detail::AmqpValueFactory::ToUamqp(appProperties.AsAmqpValue()))})}; auto serializedApplicationProperties = AmqpValue::Serialize(propertiesValue); rv.insert( rv.end(), serializedApplicationProperties.begin(), serializedApplicationProperties.end()); @@ -498,8 +506,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } if (!message.Footer.empty()) { - AmqpValue footer{Models::_detail::UniqueAmqpValueHandle{ - amqpvalue_create_footer(message.Footer.AsAmqpValue())}}; + AmqpValue footer{Models::_detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_create_footer( + Models::_detail::AmqpValueFactory::ToUamqp(message.Footer.AsAmqpValue()))})}; auto serializedFooter = AmqpValue::Serialize(footer); rv.insert(rv.end(), serializedFooter.begin(), serializedFooter.end()); } @@ -544,8 +553,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { { auto deserializer = static_cast(context); - deserializer->OnAmqpMessageFieldDecoded( - _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); + deserializer->OnAmqpMessageFieldDecoded(Models::_detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)})); } // Invoked when a message field @@ -658,13 +667,13 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { case AmqpDescriptors::Header: { UniqueMessageHeaderHandle messageHeader; HEADER_HANDLE h; - if (amqpvalue_get_header(value, &h)) + if (amqpvalue_get_header(_detail::AmqpValueFactory::ToUamqp(value), &h)) { throw std::runtime_error("Could not convert field to header."); } messageHeader.reset(h); h = nullptr; - m_decodedValue.Header = _internal::MessageHeaderFactory::FromUamqp(messageHeader); + m_decodedValue.Header = _detail::MessageHeaderFactory::FromUamqp(messageHeader); break; } case AmqpDescriptors::DeliveryAnnotations: @@ -676,13 +685,13 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { case AmqpDescriptors::Properties: { UniquePropertiesHandle properties; PROPERTIES_HANDLE h; - if (amqpvalue_get_properties(value, &h)) + if (amqpvalue_get_properties(_detail::AmqpValueFactory::ToUamqp(value), &h)) { throw std::runtime_error("Could not convert field to header."); } properties.reset(h); h = nullptr; - m_decodedValue.Properties = _internal::MessagePropertiesFactory::FromUamqp(properties); + m_decodedValue.Properties = _detail::MessagePropertiesFactory::FromUamqp(properties); break; } case AmqpDescriptors::ApplicationProperties: { @@ -791,7 +800,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { break; case MessageBodyType::Data: { os << " AMQP Data: ["; - auto bodyBinary = message.GetBodyAsBinary(); + auto const& bodyBinary = message.GetBodyAsBinary(); uint8_t i = 0; for (auto const& val : bodyBinary) { @@ -807,7 +816,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { break; case MessageBodyType::Sequence: { os << " AMQP Sequence: ["; - auto bodySequence = message.GetBodyAsAmqpList(); + auto const& bodySequence = message.GetBodyAsAmqpList(); uint8_t i = 0; for (auto const& val : bodySequence) { diff --git a/sdk/core/azure-core-amqp/src/models/amqp_properties.cpp b/sdk/core/azure-core-amqp/src/models/amqp_properties.cpp index 8171dabf67..5156fb3a66 100644 --- a/sdk/core/azure-core-amqp/src/models/amqp_properties.cpp +++ b/sdk/core/azure-core-amqp/src/models/amqp_properties.cpp @@ -24,7 +24,7 @@ namespace Azure { namespace Core { namespace _internal { namespace Azure { namespace Core { namespace Amqp { namespace Models { - MessageProperties _internal::MessagePropertiesFactory::FromUamqp( + MessageProperties _detail::MessagePropertiesFactory::FromUamqp( UniquePropertiesHandle const& properties) { MessageProperties rv; @@ -32,12 +32,14 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { // properties_get_message_id returns the value in-place. if (!properties_get_message_id(properties.get(), &value)) { - rv.MessageId = _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}; + rv.MessageId = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); } if (!properties_get_correlation_id(properties.get(), &value)) { - rv.CorrelationId = _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}; + rv.CorrelationId = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); } { @@ -53,7 +55,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!properties_get_to(properties.get(), &value)) { - rv.To = _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}; + rv.To = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); } const char* stringValue; @@ -66,7 +69,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (!properties_get_reply_to(properties.get(), &value)) { - rv.ReplyTo = _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}; + rv.ReplyTo = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); } if (!properties_get_content_type(properties.get(), &stringValue)) @@ -111,20 +115,23 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return rv; } - UniquePropertiesHandle _internal::MessagePropertiesFactory::ToUamqp( + _detail::UniquePropertiesHandle _detail::MessagePropertiesFactory::ToUamqp( MessageProperties const& properties) { UniquePropertiesHandle returnValue(properties_create()); if (properties.MessageId.HasValue()) { - if (properties_set_message_id(returnValue.get(), properties.MessageId.Value())) + if (properties_set_message_id( + returnValue.get(), _detail::AmqpValueFactory::ToUamqp(properties.MessageId.Value()))) { throw std::runtime_error("Could not set message id"); } } if (properties.CorrelationId.HasValue()) { - if (properties_set_correlation_id(returnValue.get(), properties.CorrelationId.Value())) + if (properties_set_correlation_id( + returnValue.get(), + _detail::AmqpValueFactory::ToUamqp(properties.CorrelationId.Value()))) { throw std::runtime_error("Could not set correlation id"); } @@ -143,7 +150,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (properties.To.HasValue()) { - if (properties_set_to(returnValue.get(), properties.To.Value())) + if (properties_set_to( + returnValue.get(), _detail::AmqpValueFactory::ToUamqp(properties.To.Value()))) { throw std::runtime_error("Could not set to"); } @@ -159,7 +167,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { if (properties.ReplyTo.HasValue()) { - if (properties_set_reply_to(returnValue.get(), properties.ReplyTo.Value())) + if (properties_set_reply_to( + returnValue.get(), _detail::AmqpValueFactory::ToUamqp(properties.ReplyTo.Value()))) { throw std::runtime_error("Could not set reply to"); } @@ -275,10 +284,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { std::vector MessageProperties::Serialize(MessageProperties const& properties) { - auto handle = _internal::MessagePropertiesFactory::ToUamqp(properties); + auto handle = _detail::MessagePropertiesFactory::ToUamqp(properties); Models::_detail::UniqueAmqpValueHandle propertiesAsuAMQPValue{ amqpvalue_create_properties(handle.get())}; - AmqpValue propertiesAsValue{propertiesAsuAMQPValue}; + AmqpValue propertiesAsValue{_detail::AmqpValueFactory::FromUamqp(propertiesAsuAMQPValue)}; return Models::AmqpValue::Serialize(propertiesAsValue); } @@ -286,13 +295,13 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { { AmqpValue value{AmqpValue::Deserialize(data, size)}; PROPERTIES_HANDLE handle; - if (amqpvalue_get_properties(value, &handle)) + if (amqpvalue_get_properties(_detail::AmqpValueFactory::ToUamqp(value), &handle)) { throw std::runtime_error("Could not convert value to AMQP Properties."); } - UniquePropertiesHandle uniqueHandle{handle}; + _detail::UniquePropertiesHandle uniqueHandle{handle}; handle = nullptr; - return _internal::MessagePropertiesFactory::FromUamqp(uniqueHandle); + return _detail::MessagePropertiesFactory::FromUamqp(uniqueHandle); } namespace { diff --git a/sdk/core/azure-core-amqp/src/models/amqp_value.cpp b/sdk/core/azure-core-amqp/src/models/amqp_value.cpp index 0e94763de1..4488b595ae 100644 --- a/sdk/core/azure-core-amqp/src/models/amqp_value.cpp +++ b/sdk/core/azure-core-amqp/src/models/amqp_value.cpp @@ -46,7 +46,7 @@ namespace Azure { namespace Core { namespace _internal { namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace _detail { - std::ostream& operator<<(std::ostream& os, AMQP_TYPE const& value) + std::ostream& operator<<(std::ostream& os, AMQP_TYPE const value) { switch (value) { @@ -183,8 +183,6 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { that.m_value = nullptr; } - ///@cond - AmqpValue::AmqpValue(UniqueAmqpValueHandle const& value) { // We shouldn't take ownership of the incoming value, so instead we clone it. @@ -198,11 +196,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { m_value.reset(amqpvalue_create_null()); } } - /** @brief Internal accessor to convert an AmqpValue to a uAMQP AMQP_VALUE. */ - AmqpValue::operator AMQP_VALUE_DATA_TAG*() const { return m_value.get(); } - AMQP_VALUE_DATA_TAG* AmqpValue::Release() { return m_value.release(); } - ///@endcond + AmqpValue::AmqpValue(UniqueAmqpValueHandle&& value) : m_value{std::move(value)} {} AmqpValue& AmqpValue::operator=(AmqpValue const& that) { @@ -466,17 +461,17 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } } - AmqpMap AmqpValue::AsMap() const { return AmqpMap(m_value.get()); } + AmqpMap AmqpValue::AsMap() const { return AmqpMap(*this); } - AmqpArray AmqpValue::AsArray() const { return AmqpArray(m_value.get()); } + AmqpArray AmqpValue::AsArray() const { return AmqpArray(*this); } - AmqpSymbol AmqpValue::AsSymbol() const { return AmqpSymbol(m_value.get()); } + AmqpSymbol AmqpValue::AsSymbol() const { return AmqpSymbol(*this); } - AmqpComposite AmqpValue::AsComposite() const { return AmqpComposite(m_value.get()); } - AmqpList AmqpValue::AsList() const { return AmqpList(m_value.get()); } - AmqpBinaryData AmqpValue::AsBinary() const { return AmqpBinaryData(m_value.get()); } - AmqpDescribed AmqpValue::AsDescribed() const { return AmqpDescribed(m_value.get()); } - AmqpTimestamp AmqpValue::AsTimestamp() const { return AmqpTimestamp(m_value.get()); } + AmqpComposite AmqpValue::AsComposite() const { return AmqpComposite(*this); } + AmqpList AmqpValue::AsList() const { return AmqpList(*this); } + AmqpBinaryData AmqpValue::AsBinary() const { return AmqpBinaryData(*this); } + AmqpDescribed AmqpValue::AsDescribed() const { return AmqpDescribed(*this); } + AmqpTimestamp AmqpValue::AsTimestamp() const { return AmqpTimestamp(*this); } namespace { @@ -528,7 +523,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { static void OnAmqpValueDecoded(void* context, AMQP_VALUE value) { auto deserializer = static_cast(context); - deserializer->m_decodedValue = _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}; + deserializer->m_decodedValue = _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); } }; class AmqpValueSerializer final { @@ -537,7 +533,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { std::vector operator()(AmqpValue const& value) { - if (amqpvalue_encode(value, OnAmqpValueEncoded, this)) + if (amqpvalue_encode(_detail::AmqpValueFactory::ToUamqp(value), OnAmqpValueEncoded, this)) { throw std::runtime_error("Could not encode object"); } @@ -573,7 +569,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { std::ostream& operator<<(std::ostream& os, AmqpValue const& value) { - char* valueAsString{amqpvalue_to_string(value)}; + char* valueAsString{amqpvalue_to_string(_detail::AmqpValueFactory::ToUamqp(value))}; os << valueAsString; free(valueAsString); return os; @@ -591,21 +587,35 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { size_t AmqpValue::GetSerializedSize(AmqpValue const& value) { size_t encodedSize; - if (amqpvalue_get_encoded_size(value, &encodedSize)) + if (amqpvalue_get_encoded_size(_detail::AmqpValueFactory::ToUamqp(value), &encodedSize)) { throw std::runtime_error("Could not get encoded size for value."); } return encodedSize; } - AmqpArray::AmqpArray(AMQP_VALUE_DATA_TAG* const value) + AmqpValue _detail::AmqpValueFactory::FromUamqp(UniqueAmqpValueHandle const& value) + { + return AmqpValue(value); + } + AmqpValue _detail::AmqpValueFactory::FromUamqp(UniqueAmqpValueHandle&& value) + { + return AmqpValue(std::move(value)); + } + + AMQP_VALUE _detail::AmqpValueFactory::ToUamqp(AmqpValue const& value) + { + return value.m_value.get(); + } + + AmqpArray::AmqpArray(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_ARRAY) + if (value.GetType() != AmqpValueType::Array) { throw std::runtime_error("Input AMQP value MUST be an array."); } std::uint32_t arraySize; - if (amqpvalue_get_array_item_count(value, &arraySize)) + if (amqpvalue_get_array_item_count(_detail::AmqpValueFactory::ToUamqp(value), &arraySize)) { throw std::runtime_error("Could not get array size from AMQP_VALUE"); } @@ -613,8 +623,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { for (std::uint32_t i = 0; i < arraySize; i += 1) { // amqpvalue_get_array_item clones the value. We don't need to clone it again. - UniqueAmqpValueHandle item{amqpvalue_get_array_item(value, i)}; - m_value.push_back(item); + UniqueAmqpValueHandle item{ + amqpvalue_get_array_item(_detail::AmqpValueFactory::ToUamqp(value), i)}; + m_value.push_back(_detail::AmqpValueFactory::FromUamqp(item)); } } AmqpArray::AmqpArray(initializer_type const& initializer) : AmqpCollectionBase(initializer) @@ -638,7 +649,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { UniqueAmqpValueHandle array{amqpvalue_create_array()}; for (const auto& val : *this) { - if (amqpvalue_add_array_item(array.get(), val)) + if (amqpvalue_add_array_item(array.get(), _detail::AmqpValueFactory::ToUamqp(val))) { throw(std::runtime_error("Could not add value to array.")); } @@ -646,29 +657,24 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return array; } - AmqpMap::AmqpMap(AMQP_VALUE_DATA_TAG* const value) + AmqpMap::AmqpMap(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_MAP) + if (value.GetType() != AmqpValueType::Map) { throw std::runtime_error("Input AMQP value MUST be a map."); } std::uint32_t mapSize; - if (amqpvalue_get_map_pair_count(value, &mapSize)) + if (amqpvalue_get_map_pair_count(_detail::AmqpValueFactory::ToUamqp(value), &mapSize)) { throw std::runtime_error("Could not get array size from AMQP_VALUE"); } for (std::uint32_t i = 0; i < mapSize; i += 1) { - UniqueAmqpValueHandle key; - UniqueAmqpValueHandle val; - - { - AMQP_VALUE kv, vv; - amqpvalue_get_map_key_value_pair(value, i, &kv, &vv); - key.reset(kv); - val.reset(vv); - } - m_value.emplace(std::make_pair(AmqpValue(key), AmqpValue(val))); + AMQP_VALUE key{}, val{}; + amqpvalue_get_map_key_value_pair(_detail::AmqpValueFactory::ToUamqp(value), i, &key, &val); + m_value.emplace(std::make_pair( + _detail::AmqpValueFactory::FromUamqp(UniqueAmqpValueHandle{key}), + _detail::AmqpValueFactory::FromUamqp(UniqueAmqpValueHandle{val}))); } } @@ -679,7 +685,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { UniqueAmqpValueHandle value{amqpvalue_create_map()}; for (const auto& val : *this) { - if (amqpvalue_set_map_value(value.get(), val.first, val.second)) + if (amqpvalue_set_map_value( + value.get(), + _detail::AmqpValueFactory::ToUamqp(val.first), + _detail::AmqpValueFactory::ToUamqp(val.second))) { throw(std::runtime_error("Could not add value to array.")); } @@ -687,21 +696,22 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return value; } - AmqpList::AmqpList(AMQP_VALUE_DATA_TAG* const value) + AmqpList::AmqpList(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_LIST) + if (value.GetType() != AmqpValueType::List) { - throw std::runtime_error("Input AMQP value MUST be an array."); + throw std::runtime_error("Input AMQP value MUST be a list."); } std::uint32_t listSize; - if (amqpvalue_get_list_item_count(value, &listSize)) + if (amqpvalue_get_list_item_count(_detail::AmqpValueFactory::ToUamqp(value), &listSize)) { throw std::runtime_error("Could not get array size from AMQP_VALUE"); } for (std::uint32_t i = 0; i < listSize; i += 1) { - UniqueAmqpValueHandle item{amqpvalue_get_list_item(value, i)}; - push_back(item); + UniqueAmqpValueHandle item{ + amqpvalue_get_list_item(_detail::AmqpValueFactory::ToUamqp(value), i)}; + push_back(_detail::AmqpValueFactory::FromUamqp(item)); } } @@ -717,7 +727,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { std::uint32_t i = 0; for (const auto& val : *this) { - if (amqpvalue_set_list_item(list.get(), i, val)) + if (amqpvalue_set_list_item(list.get(), i, _detail::AmqpValueFactory::ToUamqp(val))) { throw(std::runtime_error("Could not add value to list.")); } @@ -734,14 +744,14 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return binary; } - AmqpBinaryData::AmqpBinaryData(AMQP_VALUE_DATA_TAG* const value) + AmqpBinaryData::AmqpBinaryData(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_BINARY) + if (value.GetType() != AmqpValueType::Binary) { throw std::runtime_error("Input AMQP value MUST be binary."); } amqp_binary binaryData; - if (amqpvalue_get_binary(value, &binaryData)) + if (amqpvalue_get_binary(_detail::AmqpValueFactory::ToUamqp(value), &binaryData)) { throw std::runtime_error("Could not retrieve binary data."); } @@ -758,14 +768,15 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return symbol; } - AmqpSymbol::AmqpSymbol(AMQP_VALUE_DATA_TAG* const value) + AmqpSymbol::AmqpSymbol(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_SYMBOL) + if (value.GetType() != AmqpValueType::Symbol) { throw std::runtime_error("Input AMQP value MUST be a symbol."); } + const char* binaryData; - if (amqpvalue_get_symbol(value, &binaryData)) + if (amqpvalue_get_symbol(_detail::AmqpValueFactory::ToUamqp(value), &binaryData)) { throw std::runtime_error("Could not retrieve binary data."); } @@ -795,8 +806,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } } // namespace - AmqpTimestamp::AmqpTimestamp(AMQP_VALUE_DATA_TAG* const value) - : m_value(GetMillisecondsFromAmqp(value)) + AmqpTimestamp::AmqpTimestamp(AmqpValue const& value) + : m_value(GetMillisecondsFromAmqp(_detail::AmqpValueFactory::ToUamqp(value))) { } @@ -805,26 +816,28 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { } AmqpTimestamp::AmqpTimestamp() : m_value{} {} - AmqpComposite::AmqpComposite(AMQP_VALUE_DATA_TAG* const value) + AmqpComposite::AmqpComposite(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_COMPOSITE) + if (value.GetType() != AmqpValueType::Composite) { throw std::runtime_error("Input AMQP value MUST be a composite value."); } std::uint32_t compositeSize; - if (amqpvalue_get_composite_item_count(value, &compositeSize)) + if (amqpvalue_get_composite_item_count( + _detail::AmqpValueFactory::ToUamqp(value), &compositeSize)) { throw std::runtime_error("Could not get composite size from AMQP_VALUE"); } for (std::uint32_t i = 0; i < compositeSize; i += 1) { - push_back(_detail::UniqueAmqpValueHandle{ - amqpvalue_clone(amqpvalue_get_composite_item_in_place(value, i))}); + push_back(_detail::AmqpValueFactory::FromUamqp(_detail::UniqueAmqpValueHandle{amqpvalue_clone( + amqpvalue_get_composite_item_in_place(_detail::AmqpValueFactory::ToUamqp(value), i))})); } m_descriptor - = _detail::UniqueAmqpValueHandle{amqpvalue_clone(amqpvalue_get_inplace_descriptor(value))}; + = _detail::AmqpValueFactory::FromUamqp(_detail::UniqueAmqpValueHandle{amqpvalue_clone( + amqpvalue_get_inplace_descriptor(_detail::AmqpValueFactory::ToUamqp(value)))}); if (m_descriptor.IsNull()) { throw std::runtime_error("Could not read descriptor for composite value."); @@ -847,12 +860,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { AmqpComposite::operator _detail::UniqueAmqpValueHandle() const { - UniqueAmqpValueHandle composite{ - amqpvalue_create_composite(m_descriptor, static_cast(size()))}; + UniqueAmqpValueHandle composite{amqpvalue_create_composite( + _detail::AmqpValueFactory::ToUamqp(m_descriptor), static_cast(size()))}; std::uint32_t i = 0; for (const auto& val : *this) { - if (amqpvalue_set_composite_item(composite.get(), i, val)) + if (amqpvalue_set_composite_item(composite.get(), i, _detail::AmqpValueFactory::ToUamqp(val))) { throw(std::runtime_error("Could not add value to list.")); } @@ -861,22 +874,23 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { return composite; } - AmqpDescribed::AmqpDescribed(AMQP_VALUE_DATA_TAG* const value) + AmqpDescribed::AmqpDescribed(AmqpValue const& value) { - if (amqpvalue_get_type(value) != AMQP_TYPE_DESCRIBED) + if (value.GetType() != AmqpValueType::Described) { throw std::runtime_error("Input AMQP value MUST be a described value."); } m_descriptor - = _detail::UniqueAmqpValueHandle{amqpvalue_clone(amqpvalue_get_inplace_descriptor(value))}; + = _detail::AmqpValueFactory::FromUamqp(_detail::UniqueAmqpValueHandle{amqpvalue_clone( + amqpvalue_get_inplace_descriptor(_detail::AmqpValueFactory::ToUamqp(value)))}); if (m_descriptor.IsNull()) { throw std::runtime_error("Could not read descriptor for described value."); } - m_value = _detail::UniqueAmqpValueHandle{ - amqpvalue_clone(amqpvalue_get_inplace_described_value(value))}; + m_value = _detail::AmqpValueFactory::FromUamqp(_detail::UniqueAmqpValueHandle{amqpvalue_clone( + amqpvalue_get_inplace_described_value(_detail::AmqpValueFactory::ToUamqp(value)))}); if (m_value.IsNull()) { throw std::runtime_error("Could not read descriptor for described value."); @@ -897,19 +911,20 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { // For , amqpvalue_create_described does not clone the provided descriptor or value, // but amqpvalue_destroy on a described destroys the underlying value. That means we need to // manually clone the input descriptors to ensure that the reference counts work out. - UniqueAmqpValueHandle composite{ - amqpvalue_create_described(amqpvalue_clone(m_descriptor), amqpvalue_clone(m_value))}; + UniqueAmqpValueHandle composite{amqpvalue_create_described( + amqpvalue_clone(_detail::AmqpValueFactory::ToUamqp(m_descriptor)), + amqpvalue_clone(_detail::AmqpValueFactory::ToUamqp(m_value)))}; return composite; } AmqpValue AmqpDescribed::AsAmqpValue() const { - return AmqpValue{static_cast<_detail::UniqueAmqpValueHandle>(*this)}; + return _detail::AmqpValueFactory::FromUamqp(static_cast<_detail::UniqueAmqpValueHandle>(*this)); } AmqpDescribed::operator AmqpValue const() const { - return static_cast(*this); + return _detail::AmqpValueFactory::FromUamqp(static_cast(*this)); } namespace { diff --git a/sdk/core/azure-core-amqp/src/models/message_source.cpp b/sdk/core/azure-core-amqp/src/models/message_source.cpp index 0b938b85d7..140d2b42ca 100644 --- a/sdk/core/azure-core-amqp/src/models/message_source.cpp +++ b/sdk/core/azure-core-amqp/src/models/message_source.cpp @@ -32,7 +32,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } { SOURCE_HANDLE sourceHandle; - if (amqpvalue_get_source(source, &sourceHandle)) + if (amqpvalue_get_source(_detail::AmqpValueFactory::ToUamqp(source), &sourceHandle)) { throw std::runtime_error("Could not retrieve source from value."); } @@ -50,7 +50,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not create source."); } - if (source_set_address(m_source.get(), AmqpValue{address})) + if (source_set_address( + m_source.get(), + _detail::UniqueAmqpValueHandle{amqpvalue_create_string(address.c_str())}.get())) { throw std::runtime_error("Could not set address."); } @@ -66,7 +68,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not create source."); } - if (source_set_address(m_source.get(), AmqpValue{address})) + if (source_set_address( + m_source.get(), _detail::UniqueAmqpValueHandle{amqpvalue_create_string(address)}.get())) { throw std::runtime_error("Could not set address."); } @@ -83,13 +86,23 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace return *this; } + MessageSource::MessageSource(MessageSource&& that) noexcept : m_source(std::move(that.m_source)) + { + } + + MessageSource& MessageSource::operator=(MessageSource&& that) noexcept + { + m_source = std::move(that.m_source); + return *this; + } + MessageSource::MessageSource() : m_source(source_create()) {} MessageSource::MessageSource(MessageSourceOptions const& options) : m_source(source_create()) { if (!options.Address.IsNull()) { - if (source_set_address(m_source.get(), options.Address)) + if (source_set_address(m_source.get(), _detail::AmqpValueFactory::ToUamqp(options.Address))) { throw std::runtime_error("Could not set source address."); } @@ -162,7 +175,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace if (!options.DynamicNodeProperties.empty()) { AmqpValue dynamicNodeProperties(options.DynamicNodeProperties.AsAmqpValue()); - if (source_set_dynamic_node_properties(m_source.get(), dynamicNodeProperties)) + if (source_set_dynamic_node_properties( + m_source.get(), _detail::AmqpValueFactory::ToUamqp(dynamicNodeProperties))) { throw std::runtime_error("Could not set dynamic node properties."); } @@ -176,28 +190,33 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } if (!options.Filter.empty()) { - if (source_set_filter(m_source.get(), options.Filter.AsAmqpValue())) + if (source_set_filter( + m_source.get(), _detail::AmqpValueFactory::ToUamqp(options.Filter.AsAmqpValue()))) { throw std::runtime_error("Could not set filter set."); } } if (!options.DefaultOutcome.IsNull()) { - if (source_set_default_outcome(m_source.get(), options.DefaultOutcome)) + if (source_set_default_outcome( + m_source.get(), _detail::AmqpValueFactory::ToUamqp(options.DefaultOutcome))) { throw std::runtime_error("Could not set default outcome."); } } if (!options.Outcomes.empty()) { - if (source_set_outcomes(m_source.get(), options.Outcomes.AsAmqpValue())) + if (source_set_outcomes( + m_source.get(), _detail::AmqpValueFactory::ToUamqp(options.Outcomes.AsAmqpValue()))) { throw std::runtime_error("Could not set outcomes."); } } if (!options.Capabilities.empty()) { - if (source_set_capabilities(m_source.get(), options.Capabilities.AsAmqpValue())) + if (source_set_capabilities( + m_source.get(), + _detail::AmqpValueFactory::ToUamqp(options.Capabilities.AsAmqpValue()))) { throw std::runtime_error("Could not set capabilities."); } @@ -208,7 +227,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace Models::AmqpValue MessageSource::AsAmqpValue() const { Models::_detail::UniqueAmqpValueHandle sourceValue{amqpvalue_create_source(m_source.get())}; - return sourceValue; + return _detail::AmqpValueFactory::FromUamqp(sourceValue); } Models::AmqpValue MessageSource::GetAddress() const @@ -220,7 +239,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } // source_get_address does not reference its value, so we need to reference it before creating // an AmqpValueHandle. - return Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(address)}; + return _detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(address)}); } TerminusDurability MessageSource::GetTerminusDurability() const @@ -289,14 +309,16 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace return value; } - Models::AmqpMap MessageSource::GetDynamicNodeProperties() const + AmqpMap MessageSource::GetDynamicNodeProperties() const { AMQP_VALUE value; if (source_get_dynamic_node_properties(m_source.get(), &value)) { throw std::runtime_error("Could not get dynamic."); } - return value; + return _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}) + .AsMap(); } std::string MessageSource::GetDistributionMode() const { @@ -307,17 +329,20 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } return value; } - Models::AmqpMap MessageSource::GetFilter() const + + AmqpMap MessageSource::GetFilter() const { AMQP_VALUE value; if (source_get_filter(m_source.get(), &value)) { throw std::runtime_error("Could not get filter set."); } - return value; + return _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}) + .AsMap(); } - Models::AmqpValue MessageSource::GetDefaultOutcome() const + AmqpValue MessageSource::GetDefaultOutcome() const { AMQP_VALUE value; if (source_get_default_outcome(m_source.get(), &value)) @@ -326,27 +351,32 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } // source_get_default_outcome does not reference the value returned, we reference it so it can // be put into a UniqueAmqpValueHandle. - return Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}; + return _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}); } - Models::AmqpArray MessageSource::GetOutcomes() const + AmqpArray MessageSource::GetOutcomes() const { AMQP_VALUE value; if (source_get_outcomes(m_source.get(), &value)) { throw std::runtime_error("Could not get outcomes."); } - return value; + return _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}) + .AsArray(); } - Models::AmqpArray MessageSource::GetCapabilities() const + AmqpArray MessageSource::GetCapabilities() const { AMQP_VALUE value; if (source_get_capabilities(m_source.get(), &value)) { throw std::runtime_error("Could not get capabilities."); } - return value; + return _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}) + .AsArray(); } const char* StringFromTerminusDurability(TerminusDurability durability) @@ -435,7 +465,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace // source_get_default_outcome does not reference the value returned, we reference it so it // can be put into a UniqueAmqpValueHandle. os << ", Default Outcome: " - << AmqpValue{Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(outcome)}}; + << _detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(outcome)}); } } { @@ -447,7 +478,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace // will leak an AMQPSymbol if the value at location 9 is a symbol (as opposed to being an // array). os << ", Outcomes: " - << AmqpValue{Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(outcomes)}}; + << _detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(outcomes)}); } } os << "}"; diff --git a/sdk/core/azure-core-amqp/src/models/message_target.cpp b/sdk/core/azure-core-amqp/src/models/message_target.cpp index 7ae19070b5..ef0a9080d7 100644 --- a/sdk/core/azure-core-amqp/src/models/message_target.cpp +++ b/sdk/core/azure-core-amqp/src/models/message_target.cpp @@ -37,7 +37,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace throw std::invalid_argument("target cannot be null"); } TARGET_HANDLE targetHandle; - if (amqpvalue_get_target(target, &targetHandle)) + if (amqpvalue_get_target(_detail::AmqpValueFactory::ToUamqp(target), &targetHandle)) { throw std::runtime_error("Could not retrieve target from value."); } @@ -50,7 +50,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not create source."); } - if (target_set_address(m_target.get(), AmqpValue{address})) + if (target_set_address( + m_target.get(), + _detail::UniqueAmqpValueHandle(amqpvalue_create_string(address.c_str())).get())) { throw std::runtime_error("Could not set address."); } @@ -61,7 +63,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not create source."); } - if (target_set_address(m_target.get(), AmqpValue{address})) + if (target_set_address( + m_target.get(), _detail::UniqueAmqpValueHandle(amqpvalue_create_string(address)).get())) { throw std::runtime_error("Could not set address."); } @@ -77,11 +80,21 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace return *this; } + MessageTarget::MessageTarget(MessageTarget&& that) noexcept : m_target{std::move(that.m_target)} + { + } + + MessageTarget& MessageTarget::operator=(MessageTarget&& that) noexcept + { + m_target = std::move(that.m_target); + return *this; + } + MessageTarget::MessageTarget(MessageTargetOptions const& options) : m_target{target_create()} { if (!options.Address.IsNull()) { - if (target_set_address(m_target.get(), options.Address)) + if (target_set_address(m_target.get(), _detail::AmqpValueFactory::ToUamqp(options.Address))) { throw std::runtime_error("Could not set source address."); } @@ -155,7 +168,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace if (!options.DynamicNodeProperties.empty()) { if (target_set_dynamic_node_properties( - m_target.get(), options.DynamicNodeProperties.AsAmqpValue())) + m_target.get(), + _detail::AmqpValueFactory::ToUamqp(options.DynamicNodeProperties.AsAmqpValue()))) { throw std::runtime_error("Could not set dynamic node properties."); } @@ -163,7 +177,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace if (!options.Capabilities.empty()) { - if (target_set_capabilities(m_target.get(), options.Capabilities.AsAmqpValue())) + if (target_set_capabilities( + m_target.get(), + _detail::AmqpValueFactory::ToUamqp(options.Capabilities.AsAmqpValue()))) { throw std::runtime_error("Could not set capabilities."); } @@ -174,7 +190,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace Models::AmqpValue MessageTarget::AsAmqpValue() const { Models::_detail::UniqueAmqpValueHandle targetValue{amqpvalue_create_target(m_target.get())}; - return targetValue; + return _detail::AmqpValueFactory::FromUamqp(targetValue); } Models::AmqpValue MessageTarget::GetAddress() const @@ -186,7 +202,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } // target_get_address does not reference the underlying address so we need to addref it here so // it gets freed properly. - return Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(address)}; + return _detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(address)}); } TerminusDurability MessageTarget::GetTerminusDurability() const @@ -265,7 +282,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace } // We clone the value before converting it to a UniqueAmqpValueHandle because the destructor for // UniqueAmqpValueHandle will remove the reference. - return AmqpValue{Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}}.AsMap(); + return _detail::AmqpValueFactory::FromUamqp( + Models::_detail::UniqueAmqpValueHandle{amqpvalue_clone(value)}) + .AsMap(); } Models::AmqpArray MessageTarget::GetCapabilities() const @@ -275,7 +294,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not get capabilities."); } - return value; + return _detail::AmqpValueFactory::FromUamqp( + _detail::UniqueAmqpValueHandle(amqpvalue_clone(value))) + .AsArray(); } std::ostream& operator<<(std::ostream& os, MessageTarget const& target) diff --git a/sdk/core/azure-core-amqp/src/models/messaging_values.cpp b/sdk/core/azure-core-amqp/src/models/messaging_values.cpp index 0f11b97f8f..02bec5cd9a 100644 --- a/sdk/core/azure-core-amqp/src/models/messaging_values.cpp +++ b/sdk/core/azure-core-amqp/src/models/messaging_values.cpp @@ -15,7 +15,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not allocate delivery accepted described value."); } - return rv; + return _detail::AmqpValueFactory::FromUamqp(rv); } Models::AmqpValue Messaging::DeliveryReleased() { @@ -24,7 +24,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not allocate delivery released described value."); } - return rv; + return _detail::AmqpValueFactory::FromUamqp(rv); } Models::AmqpValue Messaging::DeliveryReceived(uint32_t sectionNumber, uint64_t sectionOffset) { @@ -34,35 +34,35 @@ namespace Azure { namespace Core { namespace Amqp { namespace Models { namespace { throw std::runtime_error("Could not allocate delivery received described value."); } - return rv; + return _detail::AmqpValueFactory::FromUamqp(rv); } - Models::AmqpValue Messaging::DeliveryRejected( + AmqpValue Messaging::DeliveryRejected( std::string const& errorCondition, std::string const& errorDescription, AmqpValue const& errorInfo) { - Models::_detail::UniqueAmqpValueHandle rv{messaging_delivery_rejected( + _detail::UniqueAmqpValueHandle rv{messaging_delivery_rejected( errorCondition.empty() ? nullptr : errorCondition.c_str(), errorDescription.empty() ? nullptr : errorDescription.c_str(), - errorInfo)}; + _detail::AmqpValueFactory::ToUamqp(errorInfo))}; if (!rv) { throw std::runtime_error("Could not allocate delivery rejected described value."); } - return rv; + return _detail::AmqpValueFactory::FromUamqp(rv); } - Models::AmqpValue Messaging::DeliveryModified( + AmqpValue Messaging::DeliveryModified( bool deliveryFailed, bool undeliverableHere, - Models::AmqpValue annotations) + AmqpValue annotations) { - Models::_detail::UniqueAmqpValueHandle rv{ - messaging_delivery_modified(deliveryFailed, undeliverableHere, annotations)}; + Models::_detail::UniqueAmqpValueHandle rv{messaging_delivery_modified( + deliveryFailed, undeliverableHere, _detail::AmqpValueFactory::ToUamqp(annotations))}; if (!rv) { throw std::runtime_error("Could not allocate delivery modified described value."); } - return rv; + return _detail::AmqpValueFactory::FromUamqp(rv); } }}}}} // namespace Azure::Core::Amqp::Models::_internal diff --git a/sdk/core/azure-core-amqp/test/ut/amqp_header_tests.cpp b/sdk/core/azure-core-amqp/test/ut/amqp_header_tests.cpp index 3971df9947..1025a08439 100644 --- a/sdk/core/azure-core-amqp/test/ut/amqp_header_tests.cpp +++ b/sdk/core/azure-core-amqp/test/ut/amqp_header_tests.cpp @@ -34,8 +34,8 @@ TEST_F(TestHeaders, TestTtl) MessageHeader header; header.TimeToLive = std::chrono::milliseconds(100); - auto handle = _internal::MessageHeaderFactory::ToUamqp(header); - MessageHeader header2(_internal::MessageHeaderFactory::FromUamqp(handle)); + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + MessageHeader header2(_detail::MessageHeaderFactory::FromUamqp(handle)); EXPECT_EQ(100, header2.TimeToLive.Value().count()); @@ -48,8 +48,8 @@ TEST_F(TestHeaders, TestDeliveryCount) EXPECT_EQ(0, header.DeliveryCount); header.DeliveryCount = 1; - auto handle = _internal::MessageHeaderFactory::ToUamqp(header); - MessageHeader header2(_internal::MessageHeaderFactory::FromUamqp(handle)); + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + MessageHeader header2(_detail::MessageHeaderFactory::FromUamqp(handle)); EXPECT_EQ(1, header2.DeliveryCount); @@ -61,8 +61,8 @@ TEST_F(TestHeaders, TestPriority) MessageHeader header; header.Priority = 1; - auto handle = _internal::MessageHeaderFactory::ToUamqp(header); - MessageHeader header2(_internal::MessageHeaderFactory::FromUamqp(handle)); + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + MessageHeader header2(_detail::MessageHeaderFactory::FromUamqp(handle)); EXPECT_EQ(1, header2.Priority); GTEST_LOG_(INFO) << header; @@ -74,8 +74,8 @@ TEST_F(TestHeaders, TestDurable) EXPECT_EQ(false, header.Durable); header.Durable = true; - auto handle = _internal::MessageHeaderFactory::ToUamqp(header); - MessageHeader header2(_internal::MessageHeaderFactory::FromUamqp(handle)); + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + MessageHeader header2(_detail::MessageHeaderFactory::FromUamqp(handle)); EXPECT_EQ(true, header2.Durable); GTEST_LOG_(INFO) << header; @@ -87,8 +87,8 @@ TEST_F(TestHeaders, TestFirstAcquirer) EXPECT_EQ(false, header.IsFirstAcquirer); header.IsFirstAcquirer = true; - auto handle = _internal::MessageHeaderFactory::ToUamqp(header); - MessageHeader header2(_internal::MessageHeaderFactory::FromUamqp(handle)); + auto handle = _detail::MessageHeaderFactory::ToUamqp(header); + MessageHeader header2(_detail::MessageHeaderFactory::FromUamqp(handle)); EXPECT_EQ(true, header2.IsFirstAcquirer); GTEST_LOG_(INFO) << header; diff --git a/sdk/core/azure-core-amqp/test/ut/amqp_message_tests.cpp b/sdk/core/azure-core-amqp/test/ut/amqp_message_tests.cpp index bb04a56a3e..02af679766 100644 --- a/sdk/core/azure-core-amqp/test/ut/amqp_message_tests.cpp +++ b/sdk/core/azure-core-amqp/test/ut/amqp_message_tests.cpp @@ -58,10 +58,10 @@ TEST_F(TestMessage, TestApplicationProperties) // Ensure that ApplicationProperties values round-trip through uAMQP value serialization. message.ApplicationProperties["Blah"] = 19532; - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + auto message2(_detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); - EXPECT_EQ(message2.ApplicationProperties["Blah"], AmqpValue(19532)); + EXPECT_EQ(message2->ApplicationProperties["Blah"], AmqpValue(19532)); GTEST_LOG_(INFO) << message; } @@ -71,9 +71,9 @@ TEST_F(TestMessage, TestDeliveryAnnotations) AmqpMessage message; message.DeliveryAnnotations["12345"] = 19532; - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); - EXPECT_EQ(AmqpValue{19532}, message2.DeliveryAnnotations["12345"]); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + auto message2(_detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); + EXPECT_EQ(AmqpValue{19532}, message2->DeliveryAnnotations["12345"]); GTEST_LOG_(INFO) << message; } @@ -82,9 +82,9 @@ TEST_F(TestMessage, TestAnnotations) AmqpMessage message; message.MessageAnnotations["12345"] = 19532; - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); - EXPECT_EQ(AmqpValue{19532}, message2.MessageAnnotations["12345"]); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + auto message2(_detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); + EXPECT_EQ(AmqpValue{19532}, message2->MessageAnnotations["12345"]); GTEST_LOG_(INFO) << message; } @@ -93,9 +93,10 @@ TEST_F(TestMessage, TestFooter) AmqpMessage message; message.Footer["12345"] = 37.2; - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); - EXPECT_EQ(AmqpValue{37.2}, message2.Footer["12345"]); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + std::shared_ptr message2( + _detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); + EXPECT_EQ(AmqpValue{37.2}, message2->Footer["12345"]); GTEST_LOG_(INFO) << message; } @@ -105,11 +106,12 @@ TEST_F(TestMessage, TestHeader) AmqpMessage message; message.Header.DeliveryCount = 1; - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + std::shared_ptr message2( + _detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); // Ensure that message values survive across round-trips through MESSAGE. - EXPECT_EQ(message2.Header.DeliveryCount, 1); + EXPECT_EQ(message2->Header.DeliveryCount, 1); GTEST_LOG_(INFO) << message; } @@ -120,10 +122,11 @@ TEST_F(TestMessage, TestProperties) properties.Subject = "Message subject."; message.Properties = properties; - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + std::shared_ptr message2( + _detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); - auto newProperties{message2.Properties}; + auto newProperties{message2->Properties}; EXPECT_EQ(newProperties.Subject.Value(), properties.Subject.Value()); GTEST_LOG_(INFO) << message; } @@ -140,13 +143,14 @@ TEST_F(TestMessage, TestBodyAmqpSequence) EXPECT_EQ(95, static_cast(message.GetBodyAsAmqpList()[0].at(1))); EXPECT_EQ(message.BodyType, MessageBodyType::Sequence); - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); - EXPECT_EQ(1, message2.GetBodyAsAmqpList().size()); - EXPECT_EQ(message, message2); - EXPECT_EQ("Test", static_cast(message2.GetBodyAsAmqpList()[0].at(0))); - EXPECT_EQ(95, static_cast(message2.GetBodyAsAmqpList()[0].at(1))); - EXPECT_EQ(message2.BodyType, MessageBodyType::Sequence); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + std::shared_ptr message2( + _detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); + EXPECT_EQ(1, message2->GetBodyAsAmqpList().size()); + EXPECT_EQ(message, *message2); + EXPECT_EQ("Test", static_cast(message2->GetBodyAsAmqpList()[0].at(0))); + EXPECT_EQ(95, static_cast(message2->GetBodyAsAmqpList()[0].at(1))); + EXPECT_EQ(message2->BodyType, MessageBodyType::Sequence); GTEST_LOG_(INFO) << message; } @@ -157,12 +161,13 @@ TEST_F(TestMessage, TestBodyAmqpSequence) EXPECT_EQ("Test", static_cast(message.GetBodyAsAmqpList()[1].at(0))); EXPECT_EQ(95, static_cast(message.GetBodyAsAmqpList()[2].at(1))); EXPECT_EQ(message.BodyType, MessageBodyType::Sequence); - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); - EXPECT_EQ(3, message2.GetBodyAsAmqpList().size()); - EXPECT_EQ("Test", static_cast(message2.GetBodyAsAmqpList()[2].at(0))); - EXPECT_EQ(95, static_cast(message2.GetBodyAsAmqpList()[2].at(1))); - EXPECT_EQ(message2.BodyType, MessageBodyType::Sequence); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + std::shared_ptr message2( + _detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); + EXPECT_EQ(3, message2->GetBodyAsAmqpList().size()); + EXPECT_EQ("Test", static_cast(message2->GetBodyAsAmqpList()[2].at(0))); + EXPECT_EQ(95, static_cast(message2->GetBodyAsAmqpList()[2].at(1))); + EXPECT_EQ(message2->BodyType, MessageBodyType::Sequence); GTEST_LOG_(INFO) << message; } } @@ -180,15 +185,16 @@ TEST_F(TestMessage, TestBodyAmqpData) EXPECT_EQ(message.BodyType, MessageBodyType::Data); - auto messageInstance = _internal::AmqpMessageFactory::ToUamqp(message); - AmqpMessage message2(_internal::AmqpMessageFactory::FromUamqp(messageInstance)); - EXPECT_EQ(message2.GetBodyAsBinary().size(), 1); + auto messageInstance = _detail::AmqpMessageFactory::ToUamqp(message); + std::shared_ptr message2( + _detail::AmqpMessageFactory::FromUamqp(messageInstance.get())); + EXPECT_EQ(message2->GetBodyAsBinary().size(), 1); - auto const& body2 = message2.GetBodyAsBinary()[0]; + auto const& body2 = message2->GetBodyAsBinary()[0]; EXPECT_EQ(body2.size(), sizeof(testBody)); EXPECT_EQ(memcmp(body2.data(), testBody, sizeof(testBody)), 0); - EXPECT_EQ(message2.BodyType, MessageBodyType::Data); + EXPECT_EQ(message2->BodyType, MessageBodyType::Data); GTEST_LOG_(INFO) << message; } diff --git a/sdk/core/azure-core-amqp/test/ut/amqp_properties_tests.cpp b/sdk/core/azure-core-amqp/test/ut/amqp_properties_tests.cpp index bba2511933..8766753fa3 100644 --- a/sdk/core/azure-core-amqp/test/ut/amqp_properties_tests.cpp +++ b/sdk/core/azure-core-amqp/test/ut/amqp_properties_tests.cpp @@ -35,8 +35,8 @@ TEST_F(TestProperties, SetAbsoluteExpiryTime) // Set the test timestamp and verify that the returned value is accurate to milliseconds. properties.AbsoluteExpiryTime = testTimestamp; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.AbsoluteExpiryTime.Value(), testTimestampToCheck); GTEST_LOG_(INFO) << properties; @@ -49,8 +49,8 @@ TEST_F(TestProperties, SetContentEncoding) std::string contentEncoding = "utf-8"; properties.ContentEncoding = contentEncoding; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.ContentEncoding.Value(), contentEncoding); EXPECT_EQ(properties.ContentEncoding.Value(), properties2.ContentEncoding.Value()); @@ -64,8 +64,8 @@ TEST_F(TestProperties, SetContentType) std::string contentType = "text/plain"; properties.ContentType = contentType; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.ContentType.Value(), contentType); EXPECT_EQ(properties.ContentType.Value(), properties2.ContentType.Value()); @@ -79,8 +79,8 @@ TEST_F(TestProperties, SetCorrelationId) std::string correlationId = "1234"; properties.CorrelationId = AmqpValue{correlationId}; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.CorrelationId.Value(), AmqpValue{correlationId}); GTEST_LOG_(INFO) << properties; @@ -98,8 +98,8 @@ TEST_F(TestProperties, SetCreationTime) properties.CreationTime = testTimestamp; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.CreationTime.Value(), testTimestampToCheck); @@ -112,8 +112,8 @@ TEST_F(TestProperties, SetGroupId) std::string groupId = "1234"; properties.GroupId = groupId; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties.GroupId.Value(), groupId); GTEST_LOG_(INFO) << properties; @@ -125,8 +125,8 @@ TEST_F(TestProperties, SetGroupSequence) uint32_t groupSequence = 1234; properties.GroupSequence = groupSequence; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.GroupSequence.Value(), groupSequence); GTEST_LOG_(INFO) << properties; @@ -138,8 +138,8 @@ TEST_F(TestProperties, SetMessageId) std::string messageId = "1234"; properties.MessageId = AmqpValue{messageId}; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.MessageId.Value(), AmqpValue{messageId}); GTEST_LOG_(INFO) << properties; @@ -151,8 +151,8 @@ TEST_F(TestProperties, SetReplyTo) std::string replyTo = "1234"; properties.ReplyTo = AmqpValue{replyTo}; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.ReplyTo.Value(), AmqpValue{replyTo}); GTEST_LOG_(INFO) << properties; @@ -164,8 +164,8 @@ TEST_F(TestProperties, SetReplyToGroupId) std::string replyToGroupId = "1234"; properties.ReplyToGroupId = replyToGroupId; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.ReplyToGroupId.Value(), replyToGroupId); GTEST_LOG_(INFO) << properties; @@ -176,8 +176,8 @@ TEST_F(TestProperties, SetTo) MessageProperties properties; std::string to = "1234"; properties.To = AmqpValue{to}; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.To.Value(), AmqpValue{to}); GTEST_LOG_(INFO) << properties; } @@ -186,8 +186,8 @@ TEST_F(TestProperties, SetUserId) { MessageProperties properties; properties.UserId = {'1', '2', '3', '4', '\0'}; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.UserId.Value().size(), 5); GTEST_LOG_(INFO) << properties; } @@ -197,8 +197,8 @@ TEST_F(TestProperties, SetSubject) MessageProperties properties; std::string subject = "1234"; properties.Subject = subject; - auto data = _internal::MessagePropertiesFactory::ToUamqp(properties); - MessageProperties properties2(_internal::MessagePropertiesFactory::FromUamqp(data)); + auto data = _detail::MessagePropertiesFactory::ToUamqp(properties); + MessageProperties properties2(_detail::MessagePropertiesFactory::FromUamqp(data)); EXPECT_EQ(properties2.Subject.Value(), subject); GTEST_LOG_(INFO) << properties; } diff --git a/sdk/core/azure-core-amqp/test/ut/management_tests.cpp b/sdk/core/azure-core-amqp/test/ut/management_tests.cpp index a8d05efa9c..a90428a3ff 100644 --- a/sdk/core/azure-core-amqp/test/ut/management_tests.cpp +++ b/sdk/core/azure-core-amqp/test/ut/management_tests.cpp @@ -146,7 +146,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { private: AmqpValue OnMessageReceived( MessageReceiver const& receiver, - AmqpMessage const& incomingMessage) override + std::shared_ptr const& incomingMessage) override { // We can only listen on the management or cbs nodes. if (receiver.GetSourceName() != "$management" && receiver.GetSourceName() != "$cbs") @@ -159,7 +159,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { } // If this is coming on the management node, we only support the Test operation. if (receiver.GetSourceName() == "$management" - && incomingMessage.ApplicationProperties.at("operation") != "Test") + && incomingMessage->ApplicationProperties.at("operation") != "Test") { GTEST_LOG_(INFO) << "Rejecting message because it is for an unknown operation."; auto rv = Azure::Core::Amqp::Models::_internal::Messaging::DeliveryRejected( @@ -172,9 +172,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { void MessageReceived( std::string const&, AmqpServerMock::MessageLinkComponents const& linkComponents, - AmqpMessage const& incomingMessage) const override + std::shared_ptr const& incomingMessage) const override { - if (incomingMessage.ApplicationProperties.at("operation") == "Test") + if (incomingMessage->ApplicationProperties.at("operation") == "Test") { AmqpMessage responseMessage; responseMessage.ApplicationProperties[m_expectedStatusCodeName] = m_expectedStatusCode; @@ -185,10 +185,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { // Management specification section 3.2: The correlation-id of the response message // MUST be the correlation-id from the request message (if present), else the // message-id from the request message. - auto requestCorrelationId = incomingMessage.Properties.CorrelationId; - if (!incomingMessage.Properties.CorrelationId.HasValue()) + auto requestCorrelationId = incomingMessage->Properties.CorrelationId; + if (!incomingMessage->Properties.CorrelationId.HasValue()) { - requestCorrelationId = incomingMessage.Properties.MessageId.Value(); + requestCorrelationId = incomingMessage->Properties.MessageId.Value(); } responseMessage.Properties.CorrelationId = requestCorrelationId; diff --git a/sdk/core/azure-core-amqp/test/ut/message_sender_receiver.cpp b/sdk/core/azure-core-amqp/test/ut/message_sender_receiver.cpp index a9af5132e0..3b13070764 100644 --- a/sdk/core/azure-core-amqp/test/ut/message_sender_receiver.cpp +++ b/sdk/core/azure-core-amqp/test/ut/message_sender_receiver.cpp @@ -143,7 +143,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { Models::AmqpValue OnMessageReceived( Azure::Core::Amqp::_internal::MessageReceiver const&, - Models::AmqpMessage const&) override + std::shared_ptr const&) override { return Models::AmqpValue(); } @@ -528,11 +528,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { server.ShouldSendMessage(true); auto message = receiver.WaitForIncomingMessage(); GTEST_LOG_(INFO) << "Received message."; - ASSERT_TRUE(message.first.HasValue()); + ASSERT_TRUE(message.first); ASSERT_FALSE(message.second); EXPECT_EQ( - static_cast(message.first.Value().GetBodyAsAmqpValue()), - "This is a message body."); + static_cast(message.first->GetBodyAsAmqpValue()), "This is a message body."); } { @@ -545,7 +544,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { { auto result = receiver.TryWaitForIncomingMessage(); - EXPECT_FALSE(result.first.HasValue()); + EXPECT_FALSE(result.first); } { @@ -554,7 +553,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { std::this_thread::sleep_for(std::chrono::milliseconds(5000)); GTEST_LOG_(INFO) << "Message should have been sent and processed."; auto result = receiver.TryWaitForIncomingMessage(); - EXPECT_TRUE(result.first.HasValue()); + EXPECT_TRUE(result.first); } receiver.Close(); server.StopListening(); @@ -644,12 +643,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { // Tell the server it should send a message in the polling loop. server.ShouldSendMessage(true); GTEST_LOG_(INFO) << "Waiting for message to be received."; - std::pair, bool> response; + std::pair, bool> response; ASSERT_NO_THROW(response = receiver.WaitForIncomingMessage(receiveContext)); - ASSERT_TRUE(response.first.HasValue()); + ASSERT_TRUE(response.first); ASSERT_FALSE(response.second); EXPECT_EQ( - static_cast(response.first.Value().GetBodyAsAmqpValue()), + static_cast(response.first->GetBodyAsAmqpValue()), "This is a message body."); } @@ -732,7 +731,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { { auto result = receiver.TryWaitForIncomingMessage(); - EXPECT_FALSE(result.first.HasValue()); + EXPECT_FALSE(result.first); } { @@ -741,7 +740,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { std::this_thread::sleep_for(std::chrono::milliseconds(500)); GTEST_LOG_(INFO) << "Message should have been sent and processed."; auto result = receiver.TryWaitForIncomingMessage(); - EXPECT_TRUE(result.first.HasValue()); + EXPECT_TRUE(result.first); } receiver.Close(); server.StopListening(); diff --git a/sdk/core/azure-core-amqp/test/ut/mock_amqp_server.hpp b/sdk/core/azure-core-amqp/test/ut/mock_amqp_server.hpp index 075f669a7d..cf54d73b65 100644 --- a/sdk/core/azure-core-amqp/test/ut/mock_amqp_server.hpp +++ b/sdk/core/azure-core-amqp/test/ut/mock_amqp_server.hpp @@ -37,7 +37,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { std::unique_ptr LinkSender; std::unique_ptr LinkReceiver; Azure::Core::Amqp::Common::_internal::AsyncOperationQueue< - std::unique_ptr> + std::shared_ptr> MessageQueue; Azure::Core::Amqp::Common::_internal::AsyncOperationQueue MessageReceiverPresentQueue; Azure::Core::Amqp::Common::_internal::AsyncOperationQueue MessageSenderPresentQueue; @@ -105,7 +105,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { return result != nullptr; } - std::unique_ptr TryWaitForMessage( + std::shared_ptr TryWaitForMessage( std::string const& nodeName) { // Poll for completion on both the mock server and the connection, that ensures that @@ -122,7 +122,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { } } - std::unique_ptr WaitForMessage( + std::shared_ptr WaitForMessage( std::string const& nodeName) { // Poll for completion on both the mock server and the connection, that ensures that @@ -145,7 +145,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { virtual void MessageReceived( std::string const&, MessageLinkComponents const&, - Azure::Core::Amqp::Models::AmqpMessage const&) const {}; + std::shared_ptr const&) const {}; virtual void MessageLoop( std::string const& nodeName, @@ -155,13 +155,13 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { if (message) { GTEST_LOG_(INFO) << "Received message: " << *message; - if (nodeName == "$cbs" && IsCbsMessage(*message)) + if (nodeName == "$cbs" && IsCbsMessage(message)) { - ProcessCbsMessage(linkComponents, *message); + ProcessCbsMessage(linkComponents, message); } else { - MessageReceived(nodeName, linkComponents, *message); + MessageReceived(nodeName, linkComponents, message); } } std::this_thread::yield(); @@ -278,13 +278,13 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { std::map m_linkMessageQueues; Azure::Core::Context m_listenerContext; // Used to cancel the listener if necessary. - bool IsCbsMessage(Azure::Core::Amqp::Models::AmqpMessage const& message) + bool IsCbsMessage(std::shared_ptr const& message) { - if (!message.ApplicationProperties.empty()) + if (!message->ApplicationProperties.empty()) { Azure::Core::Amqp::Models::AmqpValue operation - = message.ApplicationProperties.at("operation"); - Azure::Core::Amqp::Models::AmqpValue type = message.ApplicationProperties.at("type"); + = message->ApplicationProperties.at("operation"); + Azure::Core::Amqp::Models::AmqpValue type = message->ApplicationProperties.at("type"); // If we're processing a put-token message, then we should get a "type" and "name" // value. @@ -303,12 +303,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { void ProcessCbsMessage( MessageLinkComponents const& linkComponents, - Azure::Core::Amqp::Models::AmqpMessage const& message) + std::shared_ptr const& message) { Azure::Core::Amqp::Models::AmqpValue operation - = message.ApplicationProperties.at("operation"); - Azure::Core::Amqp::Models::AmqpValue type = message.ApplicationProperties.at("type"); - Azure::Core::Amqp::Models::AmqpValue name = message.ApplicationProperties.at("name"); + = message->ApplicationProperties.at("operation"); + Azure::Core::Amqp::Models::AmqpValue type = message->ApplicationProperties.at("type"); + Azure::Core::Amqp::Models::AmqpValue name = message->ApplicationProperties.at("name"); // If we're processing a put-token message, then we should get a "type" and "name" // value. EXPECT_EQ(operation.GetType(), Azure::Core::Amqp::Models::AmqpValueType::String); @@ -317,7 +317,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { EXPECT_EQ(type.GetType(), Azure::Core::Amqp::Models::AmqpValueType::String); EXPECT_EQ(name.GetType(), Azure::Core::Amqp::Models::AmqpValueType::String); // The body of a put-token operation MUST be an AMQP AmqpValue. - EXPECT_EQ(message.BodyType, Azure::Core::Amqp::Models::MessageBodyType::Value); + EXPECT_EQ(message->BodyType, Azure::Core::Amqp::Models::MessageBodyType::Value); // Respond to the operation. Azure::Core::Amqp::Models::AmqpMessage response; @@ -327,10 +327,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { // MUST be the correlation-id from the request message (if present), else the // message-id from the request message. Azure::Nullable requestCorrelationId - = message.Properties.CorrelationId; - if (!message.Properties.CorrelationId.HasValue()) + = message->Properties.CorrelationId; + if (!message->Properties.CorrelationId.HasValue()) { - requestCorrelationId = message.Properties.MessageId.Value(); + requestCorrelationId = message->Properties.MessageId.Value(); } response.Properties.CorrelationId = requestCorrelationId; @@ -378,10 +378,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { // MUST be the correlation-id from the request message (if present), else the // message-id from the request message. Azure::Nullable requestCorrelationId - = message.Properties.CorrelationId; - if (!message.Properties.CorrelationId.HasValue()) + = message->Properties.CorrelationId; + if (!message->Properties.CorrelationId.HasValue()) { - requestCorrelationId = message.Properties.MessageId; + requestCorrelationId = message->Properties.MessageId; } response.Properties.CorrelationId = requestCorrelationId; response.ApplicationProperties["status-code"] = 200; @@ -413,6 +413,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { transport, nullptr)}; Azure::Core::Amqp::_internal::ConnectionOptions options; options.ContainerId = m_connectionId; + options.IdleTimeout = std::chrono::minutes(2); options.EnableTrace = true; m_connection = std::make_shared( amqpTransport, options, this); @@ -531,11 +532,10 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests { } Azure::Core::Amqp::Models::AmqpValue OnMessageReceived( Azure::Core::Amqp::_internal::MessageReceiver const& receiver, - Azure::Core::Amqp::Models::AmqpMessage const& message) override + std::shared_ptr const& message) override { GTEST_LOG_(INFO) << "Received a message " << message; - m_linkMessageQueues[receiver.GetSourceName()].MessageQueue.CompleteOperation( - std::make_unique(message)); + m_linkMessageQueues[receiver.GetSourceName()].MessageQueue.CompleteOperation(message); return Azure::Core::Amqp::Models::_internal::Messaging::DeliveryAccepted(); } diff --git a/sdk/core/azure-core-amqp/test/ut_uamqp/amqp_error_tests.cpp b/sdk/core/azure-core-amqp/test/ut_uamqp/amqp_error_tests.cpp index 391a7a30d4..c60e999fc8 100644 --- a/sdk/core/azure-core-amqp/test/ut_uamqp/amqp_error_tests.cpp +++ b/sdk/core/azure-core-amqp/test/ut_uamqp/amqp_error_tests.cpp @@ -38,7 +38,7 @@ TEST_F(TestError, SimpleCreate) AmqpValue value{AmqpErrorFactory::ToAmqp(error)}; GTEST_LOG_(INFO) << value; - AMQP_VALUE amqpValue = static_cast(value); + AMQP_VALUE amqpValue = _detail::AmqpValueFactory::ToUamqp(value); ERROR_HANDLE errorHandle{}; ASSERT_EQ(0, amqpvalue_get_error(amqpValue, &errorHandle)); AmqpError error2 = AmqpErrorFactory::FromUamqp(errorHandle); diff --git a/sdk/core/azure-core-amqp/vendor/azure-uamqp-c/CMakeLists.txt b/sdk/core/azure-core-amqp/vendor/azure-uamqp-c/CMakeLists.txt index 50a073619a..74c05d44ae 100644 --- a/sdk/core/azure-core-amqp/vendor/azure-uamqp-c/CMakeLists.txt +++ b/sdk/core/azure-core-amqp/vendor/azure-uamqp-c/CMakeLists.txt @@ -13,6 +13,7 @@ option(use_installed_dependencies "set use_installed_dependencies to ON to use i option(memory_trace "set memory_trace to ON if memory usage is to be used, set to OFF to not use it" OFF) option(use_custom_heap "use externally defined heap functions instead of the malloc family" OFF) option(build_as_object_library "produce cmake object library and skip install steps" OFF) +option(atomic_refcount "use atomic reference counting" OFF) if(${use_custom_heap}) add_definitions(-DGB_USE_CUSTOM_HEAP) @@ -100,9 +101,12 @@ if(MACOSX AND NOT ${use_openssl}) set(use_socketio OFF) endif() +if (${atomic_refcount}) +add_definitions(-DREFCOUNT_USE_STD_ATOMIC) +else() add_definitions(-DREFCOUNT_ATOMIC_DONTCARE) add_definitions(-D__STDC_NO_ATOMICS__=1) - +endif() include_directories(${CMAKE_CURRENT_LIST_DIR}/inc) diff --git a/sdk/core/azure-core/inc/azure/core/uuid.hpp b/sdk/core/azure-core/inc/azure/core/uuid.hpp index d2acb48496..af79f66250 100644 --- a/sdk/core/azure-core/inc/azure/core/uuid.hpp +++ b/sdk/core/azure-core/inc/azure/core/uuid.hpp @@ -25,7 +25,7 @@ namespace Azure { namespace Core { private: static constexpr size_t UuidSize = 16; - std::array m_uuid; + std::array m_uuid{}; private: Uuid(uint8_t const uuid[UuidSize]) { std::memcpy(m_uuid.data(), uuid, UuidSize); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/CHANGELOG.md b/sdk/eventhubs/azure-messaging-eventhubs/CHANGELOG.md index c8efa58ad3..993c242558 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/CHANGELOG.md +++ b/sdk/eventhubs/azure-messaging-eventhubs/CHANGELOG.md @@ -6,6 +6,8 @@ ### Breaking Changes +- EventHub `ConsumerClient` and `ProcessorClient` objects now return pointers to `EventData` objects instead of `EventData` objects by value. + ### Bugs Fixed ### Other Changes diff --git a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/event_data_batch.hpp b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/event_data_batch.hpp index 39dc51f8d2..8cf89a7816 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/event_data_batch.hpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/event_data_batch.hpp @@ -116,7 +116,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { * * @returns true if the message was added to the batch, false otherwise. */ - bool TryAddMessage(Azure::Core::Amqp::Models::AmqpMessage const& message) + bool TryAddMessage(std::shared_ptr const& message) { return TryAddAmqpMessage(message); } @@ -146,7 +146,8 @@ namespace Azure { namespace Messaging { namespace EventHubs { Azure::Core::Amqp::Models::AmqpMessage ToAmqpMessage() const; private: - bool TryAddAmqpMessage(Azure::Core::Amqp::Models::AmqpMessage message); + bool TryAddAmqpMessage( + std::shared_ptr const& message); size_t CalculateActualSizeForPayload(std::vector const& payload) { @@ -161,11 +162,11 @@ namespace Azure { namespace Messaging { namespace EventHubs { } Azure::Core::Amqp::Models::AmqpMessage CreateBatchEnvelope( - Azure::Core::Amqp::Models::AmqpMessage const& message) + std::shared_ptr const& message) { // Create the batch envelope from the prototype message. This copies all the attributes // *except* the body attribute to the batch envelope. - Azure::Core::Amqp::Models::AmqpMessage batchEnvelope{message}; + Azure::Core::Amqp::Models::AmqpMessage batchEnvelope{*message}; batchEnvelope.BodyType = Azure::Core::Amqp::Models::MessageBodyType::None; batchEnvelope.MessageFormat = BatchedMessageFormat; return batchEnvelope; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/models/event_data.hpp b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/models/event_data.hpp index cdd2623dfc..f014fd5a3a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/models/event_data.hpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/models/event_data.hpp @@ -53,7 +53,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { * * @param message - AMQP message to construct the EventData from. */ - EventData(Azure::Core::Amqp::Models::AmqpMessage const& message); + EventData(std::shared_ptr const& message); /** @brief Construct a new EventData object from an initializer list of bytes * @@ -100,11 +100,11 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { * from the service. * */ - virtual Azure::Core::Amqp::Models::AmqpMessage const GetRawAmqpMessage() const; + virtual std::shared_ptr GetRawAmqpMessage() const; protected: /** The incoming AMQP message, if one was received. */ - Azure::Core::Amqp::Models::AmqpMessage m_message; + std::shared_ptr m_message; }; std::ostream& operator<<(std::ostream&, EventData const&); @@ -153,7 +153,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { * * This constructor is used internally during the receive operation. */ - ReceivedEventData(Azure::Core::Amqp::Models::AmqpMessage const& message); + ReceivedEventData(std::shared_ptr const& message); // Destructor ~ReceivedEventData() = default; @@ -179,7 +179,10 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { * * Returns the underlying AMQP message that was received from the Event Hubs service. */ - Azure::Core::Amqp::Models::AmqpMessage const GetRawAmqpMessage() const { return m_message; } + std::shared_ptr GetRawAmqpMessage() const override + { + return m_message; + } }; std::ostream& operator<<(std::ostream&, ReceivedEventData const&); }}}} // namespace Azure::Messaging::EventHubs::Models diff --git a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/partition_client.hpp b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/partition_client.hpp index ff49d6a17e..d10642d244 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/partition_client.hpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/partition_client.hpp @@ -55,7 +55,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { * This type is instantiated from the [ConsumerClient] type, using * [ConsumerClient.CreatePartitionClient]. */ - class PartitionClient final : private Azure::Core::Amqp::_internal::MessageReceiverEvents { + class PartitionClient final { public: /// Create a PartitionClient from another PartitionClient @@ -79,7 +79,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { * @return A vector of received events. * */ - std::vector ReceiveEvents( + std::vector> ReceiveEvents( uint32_t maxMessages, Core::Context const& context = {}); @@ -113,18 +113,8 @@ namespace Azure { namespace Messaging { namespace EventHubs { PartitionClient( Azure::Core::Amqp::_internal::MessageReceiver const& messageReceiver, PartitionClientOptions options, - Azure::Core::Http::Policies::RetryOptions retryOptions); + Core::Http::Policies::RetryOptions retryOptions); std::string GetStartExpression(Models::StartPosition const& startPosition); - - virtual void OnMessageReceiverStateChanged( - Azure::Core::Amqp::_internal::MessageReceiver const& receiver, - Azure::Core::Amqp::_internal::MessageReceiverState newState, - Azure::Core::Amqp::_internal::MessageReceiverState oldState); - virtual Azure::Core::Amqp::Models::AmqpValue OnMessageReceived( - Azure::Core::Amqp::_internal::MessageReceiver const& receiver, - Azure::Core::Amqp::Models::AmqpMessage const& message); - virtual void OnMessageReceiverDisconnected( - Azure::Core::Amqp::Models::_internal::AmqpError const& error); }; }}} // namespace Azure::Messaging::EventHubs diff --git a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/processor_partition_client.hpp b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/processor_partition_client.hpp index 576835dbc7..e451bb21ca 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/processor_partition_client.hpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/inc/azure/messaging/eventhubs/processor_partition_client.hpp @@ -36,7 +36,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { * @param maxBatchSize The maximum number of events to receive in a single call to the service. * @param context The context to pass to the update checkpoint operation. */ - std::vector ReceiveEvents( + std::vector> ReceiveEvents( uint32_t maxBatchSize, Core::Context const& context = {}) { @@ -52,7 +52,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { * @param context The context to pass to the update checkpoint operation. */ void UpdateCheckpoint( - Models::ReceivedEventData const& eventData, + std::shared_ptr const& eventData, Core::Context const& context = {}); /// Returns the partition ID associated with this ProcessorPartitionClient. diff --git a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp index 5b781bbdbe..555fa5caf4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp @@ -73,12 +73,12 @@ int main() Azure::Messaging::EventHubs::PartitionClient partitionClient{consumerClient.CreatePartitionClient( eventhubProperties.PartitionIds[0], partitionClientOptions)}; - std::vector events + std::vector> events = partitionClient.ReceiveEvents(4); // Dump the contents of each event received. for (const auto& event : events) { - std::cout << "Event: " << event << std::endl; + std::cout << "Event: " << *event << std::endl; } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp index 7c68271aad..502f609e83 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp @@ -64,12 +64,12 @@ int main() Azure::Messaging::EventHubs::PartitionClient partitionClient{consumerClient.CreatePartitionClient( eventhubProperties.PartitionIds[0], partitionClientOptions)}; - std::vector events + std::vector> events = partitionClient.ReceiveEvents(4); // Dump the contents of each event received. for (const auto& event : events) { - std::cout << "Event: " << event << std::endl; + std::cout << "Event: " << *event << std::endl; } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/event_data.cpp b/sdk/eventhubs/azure-messaging-eventhubs/src/event_data.cpp index 35df65c3fa..a9f9d1be3b 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/event_data.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/event_data.cpp @@ -18,18 +18,18 @@ using namespace Azure::Core::Diagnostics; namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { - EventData::EventData(Azure::Core::Amqp::Models::AmqpMessage const& message) + EventData::EventData(std::shared_ptr const& message) : // Promote the specific message properties into ReceivedEventData. - ContentType{message.Properties.ContentType}, - CorrelationId{message.Properties.CorrelationId}, MessageId{message.Properties.MessageId}, - Properties{message.ApplicationProperties}, m_message{message} + ContentType{message->Properties.ContentType}, + CorrelationId{message->Properties.CorrelationId}, MessageId{message->Properties.MessageId}, + Properties{message->ApplicationProperties}, m_message{message} { // If the message's body type is a single binary value, capture it in the // EventData.Body. Otherwise we can't express the message body as a single value, so // we'll leave EventData.Body as null. - if (message.BodyType == Azure::Core::Amqp::Models::MessageBodyType::Data) + if (message->BodyType == Azure::Core::Amqp::Models::MessageBodyType::Data) { - auto& binaryData = message.GetBodyAsBinary(); + auto& binaryData = message->GetBodyAsBinary(); if (binaryData.size() == 1) { Body = std::vector(binaryData[0]); @@ -37,13 +37,14 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { } } - ReceivedEventData::ReceivedEventData(Azure::Core::Amqp::Models::AmqpMessage const& message) + ReceivedEventData::ReceivedEventData( + std::shared_ptr const& message) : EventData(message) { // Copy the message annotations into the ReceivedEventData.SystemProperties. There are 3 // eventhubs specific annotations which are promoted in the ReceivedEventData, so promote them // as well. - for (auto const& item : message.MessageAnnotations) + for (auto const& item : message->MessageAnnotations) { // Ignore any annotations where the key isn't an Amqp Symbols. if ((item.first.GetType() != Azure::Core::Amqp::Models::AmqpValueType::Symbol)) @@ -104,7 +105,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { } } - Azure::Core::Amqp::Models::AmqpMessage const EventData::GetRawAmqpMessage() const + std::shared_ptr EventData::GetRawAmqpMessage() const { // If the underlying message is already populated, return it. This will typically happen when a // client attempts to send a raw AMQP message. @@ -112,15 +113,16 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Models { { return m_message; } - Azure::Core::Amqp::Models::AmqpMessage rv; - rv.Properties.ContentType = ContentType; - rv.Properties.CorrelationId = CorrelationId; - rv.Properties.MessageId = MessageId; + std::shared_ptr rv{ + std::make_shared()}; + rv->Properties.ContentType = ContentType; + rv->Properties.CorrelationId = CorrelationId; + rv->Properties.MessageId = MessageId; - rv.ApplicationProperties = Properties; + rv->ApplicationProperties = Properties; if (!Body.empty()) { - rv.SetBody(Body); + rv->SetBody(Body); } return rv; } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/event_data_batch.cpp b/sdk/eventhubs/azure-messaging-eventhubs/src/event_data_batch.cpp index c3439d4edd..80bc51f0ee 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/event_data_batch.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/event_data_batch.cpp @@ -45,23 +45,27 @@ namespace Azure { namespace Messaging { namespace EventHubs { return returnValue; } - bool EventDataBatch::TryAddAmqpMessage(Azure::Core::Amqp::Models::AmqpMessage message) + bool EventDataBatch::TryAddAmqpMessage( + std::shared_ptr const& message) { - std::lock_guard lock(m_rwMutex); + Azure::Core::Amqp::Models::AmqpMessage messageToSend{*message}; - if (!message.Properties.MessageId.HasValue()) + // Fix up some properties in the message to send if they have not been already set. + if (!message->Properties.MessageId.HasValue()) { - message.Properties.MessageId + messageToSend.Properties.MessageId = Azure::Core::Amqp::Models::AmqpValue(Azure::Core::Uuid::CreateUuid().ToString()); } if (!m_partitionKey.empty()) { - message.MessageAnnotations.emplace( + messageToSend.MessageAnnotations.emplace( _detail::PartitionKeyAnnotation, Azure::Core::Amqp::Models::AmqpValue(m_partitionKey)); } - auto serializedMessage = Azure::Core::Amqp::Models::AmqpMessage::Serialize(message); + auto serializedMessage = Azure::Core::Amqp::Models::AmqpMessage::Serialize(messageToSend); + + std::lock_guard lock(m_rwMutex); if (m_marshalledMessages.size() == 0) { diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/partition_client.cpp b/sdk/eventhubs/azure-messaging-eventhubs/src/partition_client.cpp index 431184e0d2..264b96aee5 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/partition_client.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/partition_client.cpp @@ -156,10 +156,17 @@ namespace Azure { namespace Messaging { namespace EventHubs { return PartitionClient(std::move(messageReceiver), std::move(options), std::move(retryOptions)); } + /** Creates a new PartitionClient + * + * @param messageReceiver Message Receiver for the partition client. + * @param options options used to create the PartitionClient. + * @param retryOptions controls how many times we should retry an operation in response to being + * throttled or encountering a transient error. + */ PartitionClient::PartitionClient( Azure::Core::Amqp::_internal::MessageReceiver const& messageReceiver, PartitionClientOptions options, - Azure::Core::Http::Policies::RetryOptions retryOptions) + Core::Http::Policies::RetryOptions retryOptions) : m_receiver{messageReceiver}, m_partitionOptions{options}, m_retryOptions{retryOptions} { } @@ -178,24 +185,24 @@ namespace Azure { namespace Messaging { namespace EventHubs { * @return A vector of received events. * */ - std::vector PartitionClient::ReceiveEvents( + std::vector> PartitionClient::ReceiveEvents( uint32_t maxMessages, Core::Context const& context) { - std::vector messages; + std::vector> messages; while (messages.size() < maxMessages && !context.IsCancelled()) { std::pair< - Azure::Nullable, + std::shared_ptr, Azure::Core::Amqp::Models::_internal::AmqpError> result; // TryPeekForIncomingMessage will return two empty values if there is no data available. result = m_receiver.TryWaitForIncomingMessage(); - if (result.first.HasValue()) + if (result.first) { - messages.push_back(Models::ReceivedEventData{result.first.Value()}); + messages.push_back(std::make_shared(result.first)); } else if (result.second) { @@ -209,11 +216,11 @@ namespace Azure { namespace Messaging { namespace EventHubs { else { result = m_receiver.WaitForIncomingMessage(context); - if (result.first.HasValue()) + if (result.first) { Log::Stream(Logger::Level::Verbose) << "Received message. Message count now " << messages.size(); - messages.push_back(Models::ReceivedEventData{result.first.Value()}); + messages.push_back(std::make_shared(result.first)); } else { @@ -226,26 +233,4 @@ namespace Azure { namespace Messaging { namespace EventHubs { return messages; } - void PartitionClient::OnMessageReceiverStateChanged( - Azure::Core::Amqp::_internal::MessageReceiver const& receiver, - Azure::Core::Amqp::_internal::MessageReceiverState newState, - Azure::Core::Amqp::_internal::MessageReceiverState oldState) - { - (void)receiver; - (void)newState; - (void)oldState; - } - Azure::Core::Amqp::Models::AmqpValue PartitionClient::OnMessageReceived( - Azure::Core::Amqp::_internal::MessageReceiver const& receiver, - Azure::Core::Amqp::Models::AmqpMessage const& message) - { - (void)receiver; - (void)message; - return Azure::Core::Amqp::Models::_internal::Messaging::DeliveryAccepted(); - } - void PartitionClient::OnMessageReceiverDisconnected( - Azure::Core::Amqp::Models::_internal::AmqpError const& error) - { - (void)error; - } }}} // namespace Azure::Messaging::EventHubs diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/private/eventhubs_utilities.hpp b/sdk/eventhubs/azure-messaging-eventhubs/src/private/eventhubs_utilities.hpp index 5e5339a391..449d9143c8 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/private/eventhubs_utilities.hpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/private/eventhubs_utilities.hpp @@ -137,7 +137,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace _detail if (result.Status != Azure::Core::Amqp::_internal::ManagementOperationStatus::Ok) { Azure::Core::Diagnostics::_internal::Log::Stream( - Azure::Core::Diagnostics::Logger::Level::Error) + Azure::Core::Diagnostics::Logger::Level::Warning) << "Management operation failed. StatusCode: " << result.StatusCode << " Error: " << result.Error; throw _detail::EventHubsExceptionFactory::CreateEventHubsException( @@ -145,12 +145,12 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace _detail } else { - if (result.Message.BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) + if (result.Message->BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) { throw std::runtime_error("Unexpected body type"); } - auto const& body = result.Message.GetBodyAsAmqpValue(); + auto const& body = result.Message->GetBodyAsAmqpValue(); if (body.GetType() != Azure::Core::Amqp::Models::AmqpValueType::Map) { throw std::runtime_error("Unexpected body type"); @@ -214,12 +214,12 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace _detail } else { - if (result.Message.BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) + if (result.Message->BodyType != Azure::Core::Amqp::Models::MessageBodyType::Value) { throw std::runtime_error("Unexpected body type"); } - auto const& body = result.Message.GetBodyAsAmqpValue(); + auto const& body = result.Message->GetBodyAsAmqpValue(); if (body.GetType() != Azure::Core::Amqp::Models::AmqpValueType::Map) { throw std::runtime_error("Unexpected body type"); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/processor.cpp b/sdk/eventhubs/azure-messaging-eventhubs/src/processor.cpp index 9c4beea63b..8e55ee9759 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/processor.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/processor.cpp @@ -58,7 +58,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { } catch (std::exception& ex) { - Log::Stream(Logger::Level::Error) << "Exception caught running processor: " << ex.what(); + Log::Stream(Logger::Level::Warning) << "Exception caught running processor: " << ex.what(); } }); m_isRunning = true; @@ -111,7 +111,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { } catch (std::exception& ex) { - Log::Stream(Logger::Level::Error) << "Exception caught running processor: " << ex.what(); + Log::Stream(Logger::Level::Warning) << "Exception caught running processor: " << ex.what(); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/processor_partition_client.cpp b/sdk/eventhubs/azure-messaging-eventhubs/src/processor_partition_client.cpp index ed650f4f64..ba8899fd51 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/processor_partition_client.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/processor_partition_client.cpp @@ -65,22 +65,22 @@ namespace Azure { namespace Messaging { namespace EventHubs { } void ProcessorPartitionClient::UpdateCheckpoint( - Models::ReceivedEventData const& eventData, + std::shared_ptr const& eventData, Core::Context const& context) { uint64_t sequenceNumber{}; - if (!eventData.SequenceNumber.HasValue()) + if (!eventData->SequenceNumber.HasValue()) { throw std::runtime_error("Event does not have a sequence number."); } - if (eventData.SequenceNumber.HasValue()) + if (eventData->SequenceNumber.HasValue()) { - sequenceNumber = eventData.SequenceNumber.Value(); + sequenceNumber = eventData->SequenceNumber.Value(); } uint64_t offset{}; - if (!eventData.Offset.HasValue()) + if (!eventData->Offset.HasValue()) { - offset = eventData.Offset.Value(); + offset = eventData->Offset.Value(); } Models::Checkpoint checkpoint; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/consumer_client_test.cpp b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/consumer_client_test.cpp index 28c659ac7f..67b60bedb4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/consumer_client_test.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/consumer_client_test.cpp @@ -106,10 +106,10 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { = client.CreatePartitionClient("1", partitionOptions); auto events = partitionClient.ReceiveEvents(1); EXPECT_EQ(events.size(), 1ul); - GTEST_LOG_(INFO) << "Received message " << events[0].GetRawAmqpMessage(); - EXPECT_TRUE(events[0].EnqueuedTime.HasValue()); - EXPECT_TRUE(events[0].SequenceNumber.HasValue()); - EXPECT_TRUE(events[0].Offset.HasValue()); + GTEST_LOG_(INFO) << "Received message " << events[0]->GetRawAmqpMessage(); + EXPECT_TRUE(events[0]->EnqueuedTime.HasValue()); + EXPECT_TRUE(events[0]->SequenceNumber.HasValue()); + EXPECT_TRUE(events[0]->Offset.HasValue()); } TEST_F(ConsumerClientTest, GetEventHubProperties_LIVEONLY_) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/event_data_test.cpp b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/event_data_test.cpp index 8c64cc1fff..d3cd4134eb 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/event_data_test.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/event_data_test.cpp @@ -21,10 +21,10 @@ TEST_F(EventDataTest, EventDataNew) auto message{eventData.GetRawAmqpMessage()}; - EXPECT_EQ(0ul, message.ApplicationProperties.size()); - EXPECT_FALSE(message.Properties.ContentType.HasValue()); - EXPECT_FALSE(message.Properties.CorrelationId.HasValue()); - EXPECT_FALSE(message.Properties.MessageId.HasValue()); + EXPECT_EQ(0ul, message->ApplicationProperties.size()); + EXPECT_FALSE(message->Properties.ContentType.HasValue()); + EXPECT_FALSE(message->Properties.CorrelationId.HasValue()); + EXPECT_FALSE(message->Properties.MessageId.HasValue()); { EventData newData; @@ -71,11 +71,11 @@ TEST_F(EventDataTest, EventData1) auto message{eventData.GetRawAmqpMessage()}; - EXPECT_EQ(1ul, message.ApplicationProperties.size()); - EXPECT_EQ(eventData.Body, static_cast>(message.GetBodyAsBinary()[0])); - EXPECT_EQ("ct", message.Properties.ContentType.Value()); - EXPECT_EQ(AmqpValue("ci"), message.Properties.CorrelationId.Value()); - EXPECT_TRUE(message.Properties.MessageId.HasValue()); + EXPECT_EQ(1ul, message->ApplicationProperties.size()); + EXPECT_EQ(eventData.Body, static_cast>(message->GetBodyAsBinary()[0])); + EXPECT_EQ("ct", message->Properties.ContentType.Value()); + EXPECT_EQ(AmqpValue("ci"), message->Properties.CorrelationId.Value()); + EXPECT_TRUE(message->Properties.MessageId.HasValue()); Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); EXPECT_EQ(eventData.Body, receivedEventData.Body); @@ -103,11 +103,11 @@ TEST_F(EventDataTest, EventDataStringBody) Azure::Messaging::EventHubs::Models::EventData eventData{"String Body Message."}; auto message{eventData.GetRawAmqpMessage()}; - EXPECT_FALSE(message.Properties.MessageId.HasValue()); - EXPECT_EQ(message.BodyType, Azure::Core::Amqp::Models::MessageBodyType::Data); - EXPECT_EQ(message.GetBodyAsBinary().size(), 1ul); + EXPECT_FALSE(message->Properties.MessageId.HasValue()); + EXPECT_EQ(message->BodyType, Azure::Core::Amqp::Models::MessageBodyType::Data); + EXPECT_EQ(message->GetBodyAsBinary().size(), 1ul); EXPECT_EQ( - message.GetBodyAsBinary()[0], + message->GetBodyAsBinary()[0], std::vector(eventData.Body.begin(), eventData.Body.end())); } @@ -121,8 +121,8 @@ TEST_F(EventDataTest, EventDataBodyTest) auto message{msg.GetRawAmqpMessage()}; - EXPECT_EQ(message.GetBodyAsBinary().size(), 1ul); - EXPECT_EQ(msg.Body, static_cast>(message.GetBodyAsBinary()[0])); + EXPECT_EQ(message->GetBodyAsBinary().size(), 1ul); + EXPECT_EQ(msg.Body, static_cast>(message->GetBodyAsBinary()[0])); } } @@ -131,11 +131,11 @@ TEST_F(EventDataTest, EventDataArrayBody) Azure::Messaging::EventHubs::Models::EventData eventData{1, 3, 5, 7, 9}; auto message{eventData.GetRawAmqpMessage()}; - EXPECT_FALSE(message.Properties.MessageId.HasValue()); - EXPECT_EQ(message.BodyType, Azure::Core::Amqp::Models::MessageBodyType::Data); - EXPECT_EQ(message.GetBodyAsBinary().size(), 1ul); + EXPECT_FALSE(message->Properties.MessageId.HasValue()); + EXPECT_EQ(message->BodyType, Azure::Core::Amqp::Models::MessageBodyType::Data); + EXPECT_EQ(message->GetBodyAsBinary().size(), 1ul); EXPECT_EQ( - message.GetBodyAsBinary()[0], + message->GetBodyAsBinary()[0], std::vector(eventData.Body.begin(), eventData.Body.end())); } @@ -145,21 +145,22 @@ TEST_F(EventDataTest, EventDataVectorBody) Azure::Messaging::EventHubs::Models::EventData eventData{vector}; auto message{eventData.GetRawAmqpMessage()}; - EXPECT_FALSE(message.Properties.MessageId.HasValue()); - EXPECT_EQ(message.BodyType, Azure::Core::Amqp::Models::MessageBodyType::Data); - EXPECT_EQ(message.GetBodyAsBinary().size(), 1ul); + EXPECT_FALSE(message->Properties.MessageId.HasValue()); + EXPECT_EQ(message->BodyType, Azure::Core::Amqp::Models::MessageBodyType::Data); + EXPECT_EQ(message->GetBodyAsBinary().size(), 1ul); EXPECT_EQ( - message.GetBodyAsBinary()[0], + message->GetBodyAsBinary()[0], std::vector(eventData.Body.begin(), eventData.Body.end())); } TEST_F(EventDataTest, ReceivedEventData) { { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::PartitionKeyAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = "PartitionKey"; Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); ASSERT_TRUE(receivedEventData.PartitionKey); @@ -169,16 +170,17 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.SequenceNumber); } { - Azure::Core::Amqp::Models::AmqpMessage message; + std::shared_ptr message{ + std::make_shared()}; Azure::DateTime timeNow{ std::chrono::time_point_cast(Azure::DateTime::clock::now())}; GTEST_LOG_(INFO) << "timeNow: " << timeNow.ToString(); - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::EnqueuedTimeAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = Azure::Core::Amqp::Models::AmqpTimestamp{std::chrono::duration_cast< std::chrono::milliseconds>( timeNow.time_since_epoch())} @@ -193,10 +195,11 @@ TEST_F(EventDataTest, ReceivedEventData) } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::SequenceNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = static_cast(235); Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); ASSERT_TRUE(receivedEventData.SequenceNumber); @@ -206,10 +209,11 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.Offset); } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::OffsetNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = 54644; Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); ASSERT_TRUE(receivedEventData.Offset); @@ -219,10 +223,11 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.PartitionKey); } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::OffsetNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = "54644"; Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); ASSERT_TRUE(receivedEventData.Offset); @@ -232,10 +237,11 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.PartitionKey); } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::OffsetNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = static_cast(53); Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); ASSERT_TRUE(receivedEventData.Offset); @@ -245,10 +251,11 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.PartitionKey); } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::OffsetNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = static_cast(57); Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); EXPECT_TRUE(receivedEventData.Offset); @@ -258,10 +265,11 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.PartitionKey); } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::OffsetNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = static_cast(661011); Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); EXPECT_TRUE(receivedEventData.Offset); @@ -271,10 +279,11 @@ TEST_F(EventDataTest, ReceivedEventData) EXPECT_FALSE(receivedEventData.PartitionKey); } { - Azure::Core::Amqp::Models::AmqpMessage message; - message.MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ + std::shared_ptr message{ + std::make_shared()}; + message->MessageAnnotations[Azure::Core::Amqp::Models::AmqpSymbol{ Azure::Messaging::EventHubs::_detail::OffsetNumberAnnotation} - .AsAmqpValue()] + .AsAmqpValue()] = static_cast(1412612); Azure::Messaging::EventHubs::Models::ReceivedEventData receivedEventData(message); EXPECT_TRUE(receivedEventData.Offset); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/processor_test.cpp b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/processor_test.cpp index a90613ec69..40baf3093d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/processor_test.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/processor_test.cpp @@ -335,7 +335,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { GTEST_LOG_(FATAL) << "Exception thrown sending messages" << ex.what(); } #endif - std::vector allEvents; + std::vector> allEvents; while (!context.IsCancelled()) { auto receiveContext @@ -350,7 +350,6 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { allEvents.insert(allEvents.end(), events.begin(), events.end()); GTEST_LOG_(INFO) << "Updating checkpoint for partition " << partitionClient->PartitionId(); - partitionClient->UpdateCheckpoint(events.back(), context); if (allEvents.size() == expectedEventsCount) { @@ -593,9 +592,6 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { processor.Stop(); } - // The processor balanced and greedy tests fail when run on Linux or Mac. The tests run fine on - // Windows. For now, disable the tests on Linux and Mac. -#if !defined(AZ_PLATFORM_LINUX) && !defined(AZ_PLATFORM_MAC) TEST_F(ProcessorTest, Processor_Balanced_LIVEONLY_) { TestWithLoadBalancer(Models::ProcessorStrategy::ProcessorStrategyBalanced); @@ -604,7 +600,9 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { { TestWithLoadBalancer(Models::ProcessorStrategy::ProcessorStrategyGreedy); } -#endif + + // The processor balanced_acquisitiononly tests are multi-threaded and until the half-closed + // message sender/message receiver bug is fixed, they cannot be run. #if 0 TEST_F(ProcessorTest, Processor_Balanced_AcquisitionOnly_LIVEONLY_) { diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/producer_client_test.cpp b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/producer_client_test.cpp index c8c5fe837e..360a4132c9 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/producer_client_test.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/producer_client_test.cpp @@ -59,9 +59,9 @@ TEST_F(ProducerClientTest, SendMessage_LIVEONLY_) Azure::Messaging::EventHubs::ProducerClient client{connString, eventHubName, producerOptions}; - Azure::Core::Amqp::Models::AmqpMessage message2; + auto message2{std::make_shared()}; Azure::Messaging::EventHubs::Models::EventData message1; - message2.SetBody(Azure::Core::Amqp::Models::AmqpValue("Hello7")); + message2->SetBody(Azure::Core::Amqp::Models::AmqpValue("Hello7")); message1.Body = {'H', 'e', 'l', 'l', 'o', '2'}; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/round_trip_test.cpp b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/round_trip_test.cpp index e1648d6a74..fd888ca2b6 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/test/ut/round_trip_test.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/test/ut/round_trip_test.cpp @@ -46,7 +46,7 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { ASSERT_EQ(1ul, receivedEvents.size()); std::vector expected{'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!'}; - EXPECT_EQ(expected, receivedEvents[0].Body); + EXPECT_EQ(expected, receivedEvents[0]->Body); } } @@ -84,14 +84,14 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { for (auto const& event : receivedEvents) { GTEST_LOG_(INFO) << "Event: " << event; - EXPECT_TRUE(event.EnqueuedTime); - EXPECT_TRUE(event.Offset); - EXPECT_TRUE(event.SequenceNumber); + EXPECT_TRUE(event->EnqueuedTime); + EXPECT_TRUE(event->Offset); + EXPECT_TRUE(event->SequenceNumber); } std::vector expected{1, 2, 3, 4, 5}; - EXPECT_EQ(expected, receivedEvents[0].Body); + EXPECT_EQ(expected, receivedEvents[0]->Body); } } @@ -138,17 +138,17 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test { for (auto const& event : receivedEvents) { GTEST_LOG_(INFO) << "Event: " << event; - EXPECT_TRUE(event.EnqueuedTime); - EXPECT_TRUE(event.Offset); - EXPECT_TRUE(event.SequenceNumber); + EXPECT_TRUE(event->EnqueuedTime); + EXPECT_TRUE(event->Offset); + EXPECT_TRUE(event->SequenceNumber); } std::vector expected{1, 2, 3, 4, 5, 6, 7}; - EXPECT_EQ(expected, receivedEvents[0].Body); - ASSERT_TRUE(receivedEvents[0].ContentType); - EXPECT_EQ("application/binary", receivedEvents[0].ContentType.Value()); - ASSERT_TRUE(receivedEvents[0].MessageId); - EXPECT_EQ("Test Message Id", static_cast(receivedEvents[0].MessageId.Value())); + EXPECT_EQ(expected, receivedEvents[0]->Body); + ASSERT_TRUE(receivedEvents[0]->ContentType); + EXPECT_EQ("application/binary", receivedEvents[0]->ContentType.Value()); + ASSERT_TRUE(receivedEvents[0]->MessageId); + EXPECT_EQ("Test Message Id", static_cast(receivedEvents[0]->MessageId.Value())); } }