diff --git a/include/network/message_result.hpp b/include/network/message_result.hpp index 3e3829c..7c7d114 100644 --- a/include/network/message_result.hpp +++ b/include/network/message_result.hpp @@ -67,6 +67,8 @@ class MessageResult { uint64_t size; /// The offset of the result; the start after the message header uint64_t offset; + /// The error response + const MessageResult* originError; /// The failure code uint16_t failureCode; /// The state @@ -96,8 +98,10 @@ class MessageResult { [[nodiscard]] uint64_t getOffset() const; /// Get the state [[nodiscard]] MessageState getState() const; - /// Get the original message + /// Get the failure code [[nodiscard]] uint16_t getFailureCode() const; + /// Get the error response (incl. header) + [[nodiscard]] std::string_view getError() const; /// Is the data owned by this object [[nodiscard]] bool owned() const; /// Was the request successful diff --git a/include/network/transaction.hpp b/include/network/transaction.hpp index dfa9086..0d79402 100644 --- a/include/network/transaction.hpp +++ b/include/network/transaction.hpp @@ -56,6 +56,8 @@ class Transaction { std::atomic outstanding; /// The state std::atomic state; + /// The error message id + std::atomic errorMessageId; /// The constructor explicit MultipartUpload(int parts) : messages(parts + 1), eTags(parts), outstanding(parts), state(State::Default) {} @@ -179,23 +181,28 @@ class Transaction { for (auto i = 1ull; i <= parts; i++) { auto finishMultipart = [&callback, &initalRequestResult, position, remotePath, traceId, i, parts, this](network::MessageResult& result) { if (!result.success()) [[unlikely]] { + _multipartUploads[position].errorMessageId = i - 1; _multipartUploads[position].state = MultipartUpload::State::Aborted; } else { _multipartUploads[position].eTags[i - 1] = _provider->getETag(std::string_view(reinterpret_cast(result.getData()), result.getOffset())); } if (_multipartUploads[position].outstanding.fetch_sub(1) == 1) { if (_multipartUploads[position].state != MultipartUpload::State::Aborted) [[likely]] { - auto finished = [&callback, &initalRequestResult, this](network::MessageResult& result) { - if (!result.success()) + auto finished = [&callback, &initalRequestResult, position, this](network::MessageResult& result) { + if (!result.success()) { + _multipartUploads[position].errorMessageId = _multipartUploads[position].messages.size() - 1; initalRequestResult.state = network::MessageState::Cancelled; + initalRequestResult.originError = &result; + } _completedMultiparts++; std::forward(callback)(initalRequestResult); }; auto originalMsg = makeCallbackMessage(std::move(finished), _provider->completeMultiPartRequest(remotePath, _multipartUploads[position].uploadId, _multipartUploads[position].eTags), _provider->getAddress(), _provider->getPort(), nullptr, 0, traceId); _multipartUploads[position].messages[parts] = std::move(originalMsg); } else { - auto finished = [&callback, &initalRequestResult, this](network::MessageResult& /*result*/) { + auto finished = [&callback, &initalRequestResult, position, this](network::MessageResult& /*result*/) { initalRequestResult.state = network::MessageState::Cancelled; + initalRequestResult.originError = &_multipartUploads[position].messages[_multipartUploads[position].errorMessageId]->result; _completedMultiparts++; std::forward(callback)(initalRequestResult); }; diff --git a/src/network/message_result.cpp b/src/network/message_result.cpp index d436071..455f4ea 100644 --- a/src/network/message_result.cpp +++ b/src/network/message_result.cpp @@ -13,13 +13,13 @@ namespace network { //--------------------------------------------------------------------------- using namespace std; //--------------------------------------------------------------------------- -MessageResult::MessageResult() : size(), offset(), failureCode(), state(MessageState::Init) +MessageResult::MessageResult() : size(), offset(), originError(), failureCode(), state(MessageState::Init) // The default constructor { dataVector = make_unique>(); } //--------------------------------------------------------------------------- -MessageResult::MessageResult(uint8_t* data, uint64_t size) : size(), offset(), failureCode(), state(MessageState::Init) +MessageResult::MessageResult(uint8_t* data, uint64_t size) : size(), offset(), originError(), failureCode(), state(MessageState::Init) // The constructor with buffer input { if (data) @@ -83,11 +83,20 @@ MessageState MessageResult::getState() const } //--------------------------------------------------------------------------- uint16_t MessageResult::getFailureCode() const -// Get the original message +// Get the failure code { return failureCode; } //--------------------------------------------------------------------------- +std::string_view MessageResult::getError() const +// Get the error header +{ + if (!originError) + return originError->getError(); + else + return string_view(reinterpret_cast(dataVector->data()), offset + size); +} +//--------------------------------------------------------------------------- bool MessageResult::owned() const // Is the data onwed by this {