From e6a072e7b6c7c22b5a9a6e7deecea0413928bd46 Mon Sep 17 00:00:00 2001 From: JinmingHu Date: Tue, 29 Dec 2020 14:50:49 +0800 Subject: [PATCH] Integrate `Http::Range` into blob service (#1247) # Pull Request Checklist Please leverage this checklist as a reminder to address commonly occurring feedback when submitting a pull request to make sure your PR can be reviewed quickly: See the detailed list in the [contributing guide](https://github.com/Azure/azure-sdk-for-cpp/blob/master/CONTRIBUTING.md#pull-requests). - [x] [C++ Guidelines](https://azure.github.io/azure-sdk/cpp_introduction.html) - [x] Doxygen docs - [x] Unit tests - [x] No unwanted commits/changes - [x] Descriptive title/description - [x] PR is single purpose - [x] Related issue listed - [x] Comments in source - [x] No typos - [x] Update changelog - [x] Not work-in-progress - [x] External references or docs updated - [x] Self review of PR done - [x] Any breaking changes? --- sdk/storage/azure-storage-blobs/CHANGELOG.md | 1 + .../inc/azure/storage/blobs/blob_options.hpp | 52 ++---- .../azure/storage/blobs/blob_responses.hpp | 15 -- .../azure/storage/blobs/page_blob_client.hpp | 22 +-- .../blobs/protocol/blob_rest_client.hpp | 168 ++++++++++-------- .../src/append_blob_client.cpp | 14 +- .../azure-storage-blobs/src/blob_client.cpp | 74 ++++---- .../src/block_blob_client.cpp | 14 +- .../src/page_blob_client.cpp | 93 ++-------- .../test/blob_container_client_test.cpp | 12 +- .../test/block_blob_client_test.cpp | 46 +++-- .../test/page_blob_client_test.cpp | 19 +- .../src/datalake_file_client.cpp | 8 +- 13 files changed, 210 insertions(+), 328 deletions(-) diff --git a/sdk/storage/azure-storage-blobs/CHANGELOG.md b/sdk/storage/azure-storage-blobs/CHANGELOG.md index 8889c7ab1..1fabe2635 100644 --- a/sdk/storage/azure-storage-blobs/CHANGELOG.md +++ b/sdk/storage/azure-storage-blobs/CHANGELOG.md @@ -59,6 +59,7 @@ - `FindBlobsByTags` is renamed to `FindBlobsByTagsSinglePage`. - `MaxResults` in list APIs are renamed to `PageSizeHint`. - All date time related strings are now changed to `Azure::Core::DateTime` type. +- Replace `std::pair` with `Azure::Core::Http::Range` to denote blob ranges. - Move version strings into `Details` namespace. ## 12.0.0-beta.5 (2020-11-13) diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp index a39ab95bf..a1e63f745 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp @@ -675,15 +675,9 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief Downloads only the bytes of the blob from this offset. + * @brief Downloads only the bytes of the blob in the specified range. */ - Azure::Core::Nullable Offset; - - /** - * @brief Returns at most this number of bytes of the blob from the offset. Null means - * download until the end. - */ - Azure::Core::Nullable Length; + Azure::Core::Nullable Range; /** * @brief Optional conditions that must be met to perform this operation. @@ -702,15 +696,9 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief Downloads only the bytes of the blob from this offset. + * @brief Downloads only the bytes of the blob in the specified range. */ - Azure::Core::Nullable Offset; - - /** - * @brief Returns at most this number of bytes of the blob from the offset. Null means - * download until the end. - */ - Azure::Core::Nullable Length; + Azure::Core::Nullable Range; /** * @brief The size of the first range request in bytes. Blobs smaller than this limit will be @@ -1017,15 +1005,9 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief Uploads only the bytes of the source blob from this offset. + * @brief Uploads only the bytes of the source blob in the specified range. */ - Azure::Core::Nullable SourceOffset; - - /** - * @brief Uploads this number of bytes of the source blob from the offset. Null means - * upload until the end. - */ - Azure::Core::Nullable SourceLength; + Azure::Core::Nullable SourceRange; /** * @brief Hash of the blob content. This hash is used to verify the integrity of @@ -1162,15 +1144,9 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief Uploads only the bytes of the source blob from this offset. + * @brief Uploads only the bytes of the source blob in the specified range. */ - Azure::Core::Nullable SourceOffset; - - /** - * @brief Uploads this number of bytes of the source blob from the offset. Null means - * upload until the end. - */ - Azure::Core::Nullable SourceLength; + Azure::Core::Nullable SourceRange; /** * @brief Hash of the blob content. This hash is used to verify the integrity of @@ -1327,16 +1303,10 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Context Context; /** - * @brief Optionally specifies the offset of range over which to list ranges. This offset must - * be a modulus of 512. + * @brief Optionally specifies the range of bytes over which to list ranges, inclusively. If + * omitted, then all ranges for the blob are returned. */ - Azure::Core::Nullable Offset; - - /** - * @brief Optionally specifies the length of range over which to list ranges. The length must be - * a modulus of 512. - */ - Azure::Core::Nullable Length; + Azure::Core::Nullable Range; /** * @brief Optional conditions that must be met to perform this operation. diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp index 4417c1086..f12477546 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_responses.hpp @@ -27,19 +27,4 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Models { using UploadBlockBlobFromResult = UploadBlockBlobResult; - struct PageRange - { - int64_t Offset; - int64_t Length; - }; - - struct GetPageBlobPageRangesResult - { - std::string ETag; - Azure::Core::DateTime LastModified; - int64_t BlobContentLength = 0; - std::vector PageRanges; - std::vector ClearRanges; - }; - }}}} // namespace Azure::Storage::Blobs::Models diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/page_blob_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/page_blob_client.hpp index 3a1233b38..787b4a4b5 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/page_blob_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/page_blob_client.hpp @@ -158,34 +158,30 @@ namespace Azure { namespace Storage { namespace Blobs { * uri of up to 2 KB in length that specifies a blob. The source blob must either be public or * must be authenticated via a shared access signature. If the source blob is public, no * authentication is required to perform the operation. - * @param sourceOffset Only upload a part of the blob in the sourceUri from the specified - * offset. This offset doesn't need to be a modulus of 512. - * @param sourceLength Only upload specified length of the blob in the sourceUri. This length - * must be a modulus of 512. + * @param sourceRange Only upload the bytes of the blob in the sourceUri in the specified range. * @param options Optional parameters to execute this function. * @return A UploadPageBlobPagesFromUriResult describing the state of the updated pages. */ Azure::Core::Response UploadPagesFromUri( int64_t destinationOffset, std::string sourceUri, - int64_t sourceOffset, - int64_t sourceLength, + Azure::Core::Http::Range sourceRange, const UploadPageBlobPagesFromUriOptions& options = UploadPageBlobPagesFromUriOptions()) const; /** - * @brief Clears one or more pages from the page blob, as specificed by offset and length. + * @brief Clears one or more pages from the page blob, as specificed by range. * - * @param offset Specifies the starting offset for the content to be cleared. Given that pages - * must be aligned with 512-byte boundaries, the start offset must be a modulus of 512. - * @param length Specifies the length of the content to be cleared. The length must be a modulus - * of 512. + * @param range Specifies the range of bytes to be cleared. Both the start and end of the range + * must be specified. For a page clear operation, the page range can be up to the value of the + * blob's full size. Given that pages must be aligned with 512-byte boundaries, the start of the + * range must be a modulus of 512 and the end of the range must be a modulus of 512 – 1. + * Examples of valid byte ranges are 0-511, 512-1023, etc. * @param options Optional parameters to execute this function. * @return A ClearPageBlobPagesResult describing the state of the updated pages. */ Azure::Core::Response ClearPages( - int64_t offset, - int64_t length, + Azure::Core::Http::Range range, const ClearPageBlobPagesOptions& options = ClearPageBlobPagesOptions()) const; /** diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp index 294bc702f..ae5a177c0 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp @@ -289,14 +289,14 @@ namespace Azure { namespace Storage { namespace Blobs { std::map Tags; }; // struct GetBlobTagsResult - struct GetPageBlobPageRangesResultInternal + struct GetPageBlobPageRangesResult { std::string ETag; Azure::Core::DateTime LastModified; int64_t BlobContentLength = 0; - std::vector> PageRanges; - std::vector> ClearRanges; - }; // struct GetPageBlobPageRangesResultInternal + std::vector PageRanges; + std::vector ClearRanges; + }; // struct GetPageBlobPageRangesResult struct GetUserDelegationKeyResult { @@ -5345,7 +5345,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct DownloadBlobOptions { Azure::Core::Nullable Timeout; - Azure::Core::Nullable> Range; + Azure::Core::Nullable Range; Azure::Core::Nullable EncryptionKey; Azure::Core::Nullable> EncryptionKeySha256; Azure::Core::Nullable EncryptionAlgorithm; @@ -5373,18 +5373,14 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.Range.HasValue()) { - auto startOffset = options.Range.GetValue().first; - auto endOffset = options.Range.GetValue().second; - if (endOffset != std::numeric_limits::max()) + std::string headerValue + = "bytes=" + std::to_string(options.Range.GetValue().Offset) + "-"; + if (options.Range.GetValue().Length.HasValue()) { - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); - } - else - { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(startOffset) + "-"); + headerValue += std::to_string( + options.Range.GetValue().Offset + options.Range.GetValue().Length.GetValue() - 1); } + request.AddHeader("x-ms-range", std::move(headerValue)); } if (options.EncryptionKey.HasValue()) { @@ -7609,7 +7605,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; std::string BlockId; std::string SourceUri; - Azure::Core::Nullable> SourceRange; + Azure::Core::Nullable SourceRange; Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable EncryptionKey; @@ -7643,18 +7639,15 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-copy-source", options.SourceUri); if (options.SourceRange.HasValue()) { - auto startOffset = options.SourceRange.GetValue().first; - auto endOffset = options.SourceRange.GetValue().second; - if (endOffset != std::numeric_limits::max()) + std::string headerValue + = "bytes=" + std::to_string(options.SourceRange.GetValue().Offset) + "-"; + if (options.SourceRange.GetValue().Length.HasValue()) { - request.AddHeader( - "x-ms-source_range", - "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); - } - else - { - request.AddHeader("x-ms-source_range", "bytes=" + std::to_string(startOffset) + "-"); + headerValue += std::to_string( + options.SourceRange.GetValue().Offset + + options.SourceRange.GetValue().Length.GetValue() - 1); } + request.AddHeader("x-ms-source_range", std::move(headerValue)); } if (options.TransactionalContentHash.HasValue()) { @@ -8313,7 +8306,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct UploadPageBlobPagesOptions { Azure::Core::Nullable Timeout; - std::pair Range; + Azure::Core::Http::Range Range; Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; @@ -8348,10 +8341,15 @@ namespace Azure { namespace Storage { namespace Blobs { request.GetUrl().AppendQueryParameter( "timeout", std::to_string(options.Timeout.GetValue())); } - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + { + std::string headerValue = "bytes=" + std::to_string(options.Range.Offset) + "-"; + if (options.Range.Length.HasValue()) + { + headerValue + += std::to_string(options.Range.Offset + options.Range.Length.GetValue() - 1); + } + request.AddHeader("x-ms-range", std::move(headerValue)); + } if (options.TransactionalContentHash.HasValue()) { if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) @@ -8492,8 +8490,8 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string SourceUri; - std::pair SourceRange; - std::pair Range; + Azure::Core::Http::Range SourceRange; + Azure::Core::Http::Range Range; Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; @@ -8526,15 +8524,25 @@ namespace Azure { namespace Storage { namespace Blobs { request.GetUrl().AppendQueryParameter( "timeout", std::to_string(options.Timeout.GetValue())); } - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + { + std::string headerValue = "bytes=" + std::to_string(options.Range.Offset) + "-"; + if (options.Range.Length.HasValue()) + { + headerValue + += std::to_string(options.Range.Offset + options.Range.Length.GetValue() - 1); + } + request.AddHeader("x-ms-range", std::move(headerValue)); + } request.AddHeader("x-ms-copy-source", options.SourceUri); - request.AddHeader( - "x-ms-source-range", - "bytes=" + std::to_string(options.SourceRange.first) + "-" - + std::to_string(options.SourceRange.second)); + { + std::string headerValue = "bytes=" + std::to_string(options.SourceRange.Offset) + "-"; + if (options.SourceRange.Length.HasValue()) + { + headerValue += std::to_string( + options.SourceRange.Offset + options.SourceRange.Length.GetValue() - 1); + } + request.AddHeader("x-ms-source-range", std::move(headerValue)); + } if (options.TransactionalContentHash.HasValue()) { if (options.TransactionalContentHash.GetValue().Algorithm == HashAlgorithm::Md5) @@ -8675,7 +8683,7 @@ namespace Azure { namespace Storage { namespace Blobs { struct ClearPageBlobPagesOptions { Azure::Core::Nullable Timeout; - std::pair Range; + Azure::Core::Http::Range Range; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfSequenceNumberLessThanOrEqualTo; Azure::Core::Nullable IfSequenceNumberLessThan; @@ -8707,10 +8715,15 @@ namespace Azure { namespace Storage { namespace Blobs { request.GetUrl().AppendQueryParameter( "timeout", std::to_string(options.Timeout.GetValue())); } - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(options.Range.first) + "-" - + std::to_string(options.Range.second)); + { + std::string headerValue = "bytes=" + std::to_string(options.Range.Offset) + "-"; + if (options.Range.Length.HasValue()) + { + headerValue + += std::to_string(options.Range.Offset + options.Range.Length.GetValue() - 1); + } + request.AddHeader("x-ms-range", std::move(headerValue)); + } request.AddHeader("x-ms-page-write", "clear"); if (options.LeaseId.HasValue()) { @@ -8927,7 +8940,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable Timeout; Azure::Core::Nullable PreviousSnapshot; Azure::Core::Nullable PreviousSnapshotUrl; - Azure::Core::Nullable> Range; + Azure::Core::Nullable Range; Azure::Core::Nullable LeaseId; Azure::Core::Nullable IfModifiedSince; Azure::Core::Nullable IfUnmodifiedSince; @@ -8936,7 +8949,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Nullable IfTags; }; // struct GetPageBlobPageRangesOptions - static Azure::Core::Response GetPageRanges( + static Azure::Core::Response GetPageRanges( const Azure::Core::Context& context, Azure::Core::Http::HttpPipeline& pipeline, const Azure::Core::Http::Url& url, @@ -8959,18 +8972,14 @@ namespace Azure { namespace Storage { namespace Blobs { } if (options.Range.HasValue()) { - auto startOffset = options.Range.GetValue().first; - auto endOffset = options.Range.GetValue().second; - if (endOffset != std::numeric_limits::max()) + std::string headerValue + = "bytes=" + std::to_string(options.Range.GetValue().Offset) + "-"; + if (options.Range.GetValue().Length.HasValue()) { - request.AddHeader( - "x-ms-range", - "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); - } - else - { - request.AddHeader("x-ms-range", "bytes=" + std::to_string(startOffset) + "-"); + headerValue += std::to_string( + options.Range.GetValue().Offset + options.Range.GetValue().Length.GetValue() - 1); } + request.AddHeader("x-ms-range", std::move(headerValue)); } if (options.LeaseId.HasValue()) { @@ -9008,7 +9017,7 @@ namespace Azure { namespace Storage { namespace Blobs { } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; - GetPageBlobPageRangesResultInternal response; + GetPageBlobPageRangesResult response; auto http_status_code = static_cast::type>( httpResponse.GetStatusCode()); @@ -9020,7 +9029,7 @@ namespace Azure { namespace Storage { namespace Blobs { const auto& httpResponseBody = httpResponse.GetBody(); Storage::Details::XmlReader reader( reinterpret_cast(httpResponseBody.data()), httpResponseBody.size()); - response = GetPageBlobPageRangesResultInternalFromXml(reader); + response = GetPageBlobPageRangesResultFromXml(reader); } response.ETag = httpResponse.GetHeaders().at("etag"); response.LastModified = Azure::Core::DateTime::Parse( @@ -9028,7 +9037,7 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::DateTime::DateFormat::Rfc1123); response.BlobContentLength = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-content-length")); - return Azure::Core::Response( + return Azure::Core::Response( std::move(response), std::move(pHttpResponse)); } @@ -9113,10 +9122,10 @@ namespace Azure { namespace Storage { namespace Blobs { } private: - static GetPageBlobPageRangesResultInternal GetPageBlobPageRangesResultInternalFromXml( + static GetPageBlobPageRangesResult GetPageBlobPageRangesResultFromXml( Storage::Details::XmlReader& reader) { - GetPageBlobPageRangesResultInternal ret; + GetPageBlobPageRangesResult ret; enum class XmlTagName { k_PageList, @@ -9182,7 +9191,7 @@ namespace Azure { namespace Storage { namespace Blobs { return ret; } - static std::pair ClearRangesFromXml(Storage::Details::XmlReader& reader) + static Azure::Core::Http::Range ClearRangesFromXml(Storage::Details::XmlReader& reader) { int depth = 0; bool is_start = false; @@ -9231,10 +9240,13 @@ namespace Azure { namespace Storage { namespace Blobs { } } } - return std::make_pair(start, end); + Azure::Core::Http::Range ret; + ret.Offset = start; + ret.Length = end - start + 1; + return ret; } - static std::pair PageRangesFromXml(Storage::Details::XmlReader& reader) + static Azure::Core::Http::Range PageRangesFromXml(Storage::Details::XmlReader& reader) { int depth = 0; bool is_start = false; @@ -9283,7 +9295,10 @@ namespace Azure { namespace Storage { namespace Blobs { } } } - return std::make_pair(start, end); + Azure::Core::Http::Range ret; + ret.Offset = start; + ret.Length = end - start + 1; + return ret; } }; // class PageBlob @@ -9609,7 +9624,7 @@ namespace Azure { namespace Storage { namespace Blobs { { Azure::Core::Nullable Timeout; std::string SourceUri; - Azure::Core::Nullable> SourceRange; + Azure::Core::Nullable SourceRange; Azure::Core::Nullable TransactionalContentHash; Azure::Core::Nullable LeaseId; Azure::Core::Nullable MaxSize; @@ -9644,18 +9659,15 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-copy-source", options.SourceUri); if (options.SourceRange.HasValue()) { - auto startOffset = options.SourceRange.GetValue().first; - auto endOffset = options.SourceRange.GetValue().second; - if (endOffset != std::numeric_limits::max()) + std::string headerValue + = "bytes=" + std::to_string(options.SourceRange.GetValue().Offset) + "-"; + if (options.SourceRange.GetValue().Length.HasValue()) { - request.AddHeader( - "x-ms-source-range", - "bytes=" + std::to_string(startOffset) + "-" + std::to_string(endOffset)); - } - else - { - request.AddHeader("x-ms-source-range", "bytes=" + std::to_string(startOffset) + "-"); + headerValue += std::to_string( + options.SourceRange.GetValue().Offset + + options.SourceRange.GetValue().Length.GetValue() - 1); } + request.AddHeader("x-ms-source-range", std::move(headerValue)); } if (options.TransactionalContentHash.HasValue()) { diff --git a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp index e16d8ad8b..da21d1773 100644 --- a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp @@ -147,19 +147,7 @@ namespace Azure { namespace Storage { namespace Blobs { { Details::BlobRestClient::AppendBlob::AppendBlockFromUriOptions protocolLayerOptions; protocolLayerOptions.SourceUri = sourceUri; - if (options.SourceOffset.HasValue() && options.SourceLength.HasValue()) - { - protocolLayerOptions.SourceRange = std::make_pair( - options.SourceOffset.GetValue(), - options.SourceOffset.GetValue() + options.SourceLength.GetValue() - 1); - } - else if (options.SourceOffset.HasValue()) - { - protocolLayerOptions.SourceRange = std::make_pair( - options.SourceOffset.GetValue(), - std::numeric_limits< - std::remove_reference_t>::max()); - } + protocolLayerOptions.SourceRange = options.SourceRange; protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.MaxSize = options.AccessConditions.IfMaxSizeLessThanOrEqual; diff --git a/sdk/storage/azure-storage-blobs/src/blob_client.cpp b/sdk/storage/azure-storage-blobs/src/blob_client.cpp index 6a296a852..250fae18d 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_client.cpp @@ -160,17 +160,7 @@ namespace Azure { namespace Storage { namespace Blobs { const DownloadBlobOptions& options) const { Details::BlobRestClient::Blob::DownloadBlobOptions protocolLayerOptions; - if (options.Offset.HasValue() && options.Length.HasValue()) - { - protocolLayerOptions.Range = std::make_pair( - options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); - } - else if (options.Offset.HasValue()) - { - protocolLayerOptions.Range = std::make_pair( - options.Offset.GetValue(), - std::numeric_limits>::max()); - } + protocolLayerOptions.Range = options.Range; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; @@ -198,12 +188,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(context); DownloadBlobOptions newOptions = options; - newOptions.Offset - = (options.Offset.HasValue() ? options.Offset.GetValue() : 0) + retryInfo.Offset; - newOptions.Length = options.Length; - if (newOptions.Length.HasValue()) + newOptions.Range = Core::Http::Range(); + newOptions.Range.GetValue().Offset + = (options.Range.HasValue() ? options.Range.GetValue().Offset : 0) + retryInfo.Offset; + if (options.Range.HasValue() && options.Range.GetValue().Length.HasValue()) { - newOptions.Length = options.Length.GetValue() - retryInfo.Offset; + newOptions.Range.GetValue().Length = options.Range.GetValue().Length.GetValue() - retryInfo.Offset; } if (!newOptions.AccessConditions.IfMatch.HasValue()) { @@ -230,37 +220,37 @@ namespace Azure { namespace Storage { namespace Blobs { // Just start downloading using an initial chunk. If it's a small blob, we'll get the whole // thing in one shot. If it's a large blob, we'll get its full size in Content-Range and can // keep downloading it in chunks. - int64_t firstChunkOffset = options.Offset.HasValue() ? options.Offset.GetValue() : 0; + int64_t firstChunkOffset = options.Range.HasValue() ? options.Range.GetValue().Offset : 0; int64_t firstChunkLength = DefaultChunkSize; if (options.InitialChunkSize.HasValue()) { firstChunkLength = options.InitialChunkSize.GetValue(); } - if (options.Length.HasValue()) + if (options.Range.HasValue() && options.Range.GetValue().Length.HasValue()) { - firstChunkLength = std::min(firstChunkLength, options.Length.GetValue()); + firstChunkLength = std::min(firstChunkLength, options.Range.GetValue().Length.GetValue()); } DownloadBlobOptions firstChunkOptions; firstChunkOptions.Context = options.Context; - firstChunkOptions.Offset = options.Offset; - if (firstChunkOptions.Offset.HasValue()) + firstChunkOptions.Range = options.Range; + if (firstChunkOptions.Range.HasValue()) { - firstChunkOptions.Length = firstChunkLength; + firstChunkOptions.Range.GetValue().Length = firstChunkLength; } auto firstChunk = Download(firstChunkOptions); int64_t blobSize; int64_t blobRangeSize; - if (firstChunkOptions.Offset.HasValue()) + if (firstChunkOptions.Range.HasValue()) { blobSize = std::stoll(firstChunk->ContentRange.GetValue().substr( firstChunk->ContentRange.GetValue().find('/') + 1)); blobRangeSize = blobSize - firstChunkOffset; - if (options.Length.HasValue()) + if (options.Range.HasValue() && options.Range.GetValue().Length.HasValue()) { - blobRangeSize = std::min(blobRangeSize, options.Length.GetValue()); + blobRangeSize = std::min(blobRangeSize, options.Range.GetValue().Length.GetValue()); } } else @@ -304,8 +294,9 @@ namespace Azure { namespace Storage { namespace Blobs { = [&](int64_t offset, int64_t length, int64_t chunkId, int64_t numChunks) { DownloadBlobOptions chunkOptions; chunkOptions.Context = options.Context; - chunkOptions.Offset = offset; - chunkOptions.Length = length; + chunkOptions.Range = Core::Http::Range(); + chunkOptions.Range.GetValue().Offset = offset; + chunkOptions.Range.GetValue().Length = length; if (!chunkOptions.AccessConditions.IfMatch.HasValue()) { chunkOptions.AccessConditions.IfMatch = firstChunk->ETag; @@ -315,8 +306,8 @@ namespace Azure { namespace Storage { namespace Blobs { chunkOptions.Context, *(chunk->BodyStream), buffer + (offset - firstChunkOffset), - chunkOptions.Length.GetValue()); - if (bytesRead != chunkOptions.Length.GetValue()) + chunkOptions.Range.GetValue().Length.GetValue()); + if (bytesRead != chunkOptions.Range.GetValue().Length.GetValue()) { throw std::runtime_error("error when reading body stream"); } @@ -357,23 +348,23 @@ namespace Azure { namespace Storage { namespace Blobs { // Just start downloading using an initial chunk. If it's a small blob, we'll get the whole // thing in one shot. If it's a large blob, we'll get its full size in Content-Range and can // keep downloading it in chunks. - int64_t firstChunkOffset = options.Offset.HasValue() ? options.Offset.GetValue() : 0; + int64_t firstChunkOffset = options.Range.HasValue() ? options.Range.GetValue().Offset : 0; int64_t firstChunkLength = DefaultChunkSize; if (options.InitialChunkSize.HasValue()) { firstChunkLength = options.InitialChunkSize.GetValue(); } - if (options.Length.HasValue()) + if (options.Range.HasValue() && options.Range.GetValue().Length.HasValue()) { - firstChunkLength = std::min(firstChunkLength, options.Length.GetValue()); + firstChunkLength = std::min(firstChunkLength, options.Range.GetValue().Length.GetValue()); } DownloadBlobOptions firstChunkOptions; firstChunkOptions.Context = options.Context; - firstChunkOptions.Offset = options.Offset; - if (firstChunkOptions.Offset.HasValue()) + firstChunkOptions.Range = options.Range; + if (firstChunkOptions.Range.HasValue()) { - firstChunkOptions.Length = firstChunkLength; + firstChunkOptions.Range.GetValue().Length = firstChunkLength; } Storage::Details::FileWriter fileWriter(fileName); @@ -382,14 +373,14 @@ namespace Azure { namespace Storage { namespace Blobs { int64_t blobSize; int64_t blobRangeSize; - if (firstChunkOptions.Offset.HasValue()) + if (firstChunkOptions.Range.HasValue()) { blobSize = std::stoll(firstChunk->ContentRange.GetValue().substr( firstChunk->ContentRange.GetValue().find('/') + 1)); blobRangeSize = blobSize - firstChunkOffset; - if (options.Length.HasValue()) + if (options.Range.HasValue() && options.Range.GetValue().Length.HasValue()) { - blobRangeSize = std::min(blobRangeSize, options.Length.GetValue()); + blobRangeSize = std::min(blobRangeSize, options.Range.GetValue().Length.GetValue()); } } else @@ -445,8 +436,9 @@ namespace Azure { namespace Storage { namespace Blobs { = [&](int64_t offset, int64_t length, int64_t chunkId, int64_t numChunks) { DownloadBlobOptions chunkOptions; chunkOptions.Context = options.Context; - chunkOptions.Offset = offset; - chunkOptions.Length = length; + chunkOptions.Range = Core::Http::Range(); + chunkOptions.Range.GetValue().Offset = offset; + chunkOptions.Range.GetValue().Length = length; if (!chunkOptions.AccessConditions.IfMatch.HasValue()) { chunkOptions.AccessConditions.IfMatch = firstChunk->ETag; @@ -456,7 +448,7 @@ namespace Azure { namespace Storage { namespace Blobs { *(chunk->BodyStream), fileWriter, offset - firstChunkOffset, - chunkOptions.Length.GetValue(), + chunkOptions.Range.GetValue().Length.GetValue(), chunkOptions.Context); if (chunkId == numChunks - 1) diff --git a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp index a18a675ff..386cf404b 100644 --- a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp @@ -289,19 +289,7 @@ namespace Azure { namespace Storage { namespace Blobs { Details::BlobRestClient::BlockBlob::StageBlockFromUriOptions protocolLayerOptions; protocolLayerOptions.BlockId = blockId; protocolLayerOptions.SourceUri = sourceUri; - if (options.SourceOffset.HasValue() && options.SourceLength.HasValue()) - { - protocolLayerOptions.SourceRange = std::make_pair( - options.SourceOffset.GetValue(), - options.SourceOffset.GetValue() + options.SourceLength.GetValue() - 1); - } - else if (options.SourceOffset.HasValue()) - { - protocolLayerOptions.SourceRange = std::make_pair( - options.SourceOffset.GetValue(), - std::numeric_limits< - std::remove_reference_t>::max()); - } + protocolLayerOptions.SourceRange = options.SourceRange; protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.SourceIfModifiedSince = options.SourceConditions.IfModifiedSince; diff --git a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp index 67a2199b8..8940f83a2 100644 --- a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp @@ -129,7 +129,8 @@ namespace Azure { namespace Storage { namespace Blobs { const UploadPageBlobPagesOptions& options) const { Details::BlobRestClient::PageBlob::UploadPageBlobPagesOptions protocolLayerOptions; - protocolLayerOptions.Range = std::make_pair(offset, offset + content->Length() - 1); + protocolLayerOptions.Range.Offset = offset; + protocolLayerOptions.Range.Length = content->Length(); protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; @@ -152,16 +153,14 @@ namespace Azure { namespace Storage { namespace Blobs { PageBlobClient::UploadPagesFromUri( int64_t destinationOffset, std::string sourceUri, - int64_t sourceOffset, - int64_t sourceLength, + Azure::Core::Http::Range sourceRange, const UploadPageBlobPagesFromUriOptions& options) const { Details::BlobRestClient::PageBlob::UploadPageBlobPagesFromUriOptions protocolLayerOptions; protocolLayerOptions.SourceUri = sourceUri; - protocolLayerOptions.SourceRange - = std::make_pair(sourceOffset, sourceOffset + sourceLength - 1); - protocolLayerOptions.Range - = std::make_pair(destinationOffset, destinationOffset + sourceLength - 1); + protocolLayerOptions.Range.Offset = destinationOffset; + protocolLayerOptions.Range.Length = sourceRange.Length.GetValue(); + protocolLayerOptions.SourceRange = std::move(sourceRange); protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; @@ -181,12 +180,11 @@ namespace Azure { namespace Storage { namespace Blobs { } Azure::Core::Response PageBlobClient::ClearPages( - int64_t offset, - int64_t length, + Azure::Core::Http::Range range, const ClearPageBlobPagesOptions& options) const { Details::BlobRestClient::PageBlob::ClearPageBlobPagesOptions protocolLayerOptions; - protocolLayerOptions.Range = std::make_pair(offset, offset + length - 1); + protocolLayerOptions.Range = std::move(range); protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; @@ -231,36 +229,15 @@ namespace Azure { namespace Storage { namespace Blobs { const GetPageBlobPageRangesOptions& options) const { Details::BlobRestClient::PageBlob::GetPageBlobPageRangesOptions protocolLayerOptions; - if (options.Offset.HasValue() && options.Length.HasValue()) - { - protocolLayerOptions.Range = std::make_pair( - options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); - } + protocolLayerOptions.Range = options.Range; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch; protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch; protocolLayerOptions.IfTags = options.AccessConditions.TagConditions; - auto protocolLayerResponse = Details::BlobRestClient::PageBlob::GetPageRanges( + return Details::BlobRestClient::PageBlob::GetPageRanges( options.Context, *m_pipeline, m_blobUrl, protocolLayerOptions); - - Models::GetPageBlobPageRangesResult ret; - ret.ETag = std::move(protocolLayerResponse->ETag); - ret.LastModified = std::move(protocolLayerResponse->LastModified); - ret.BlobContentLength = protocolLayerResponse->BlobContentLength; - for (const auto& range : protocolLayerResponse->PageRanges) - { - ret.PageRanges.emplace_back(Models::PageRange{range.first, range.second - range.first + 1}); - } - for (const auto& range : protocolLayerResponse->ClearRanges) - { - ret.ClearRanges.emplace_back(Models::PageRange{range.first, range.second - range.first + 1}); - } - return Azure::Core::Response( - std::move(ret), - std::make_unique( - std::move(protocolLayerResponse.GetRawResponse()))); } Azure::Core::Response PageBlobClient::GetPageRangesDiff( @@ -269,36 +246,15 @@ namespace Azure { namespace Storage { namespace Blobs { { Details::BlobRestClient::PageBlob::GetPageBlobPageRangesOptions protocolLayerOptions; protocolLayerOptions.PreviousSnapshot = previousSnapshot; - if (options.Offset.HasValue() && options.Length.HasValue()) - { - protocolLayerOptions.Range = std::make_pair( - options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); - } + protocolLayerOptions.Range = options.Range; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch; protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch; protocolLayerOptions.IfTags = options.AccessConditions.TagConditions; - auto protocolLayerResponse = Details::BlobRestClient::PageBlob::GetPageRanges( + return Details::BlobRestClient::PageBlob::GetPageRanges( options.Context, *m_pipeline, m_blobUrl, protocolLayerOptions); - - Models::GetPageBlobPageRangesResult ret; - ret.ETag = std::move(protocolLayerResponse->ETag); - ret.LastModified = std::move(protocolLayerResponse->LastModified); - ret.BlobContentLength = protocolLayerResponse->BlobContentLength; - for (const auto& range : protocolLayerResponse->PageRanges) - { - ret.PageRanges.emplace_back(Models::PageRange{range.first, range.second - range.first + 1}); - } - for (const auto& range : protocolLayerResponse->ClearRanges) - { - ret.ClearRanges.emplace_back(Models::PageRange{range.first, range.second - range.first + 1}); - } - return Azure::Core::Response( - std::move(ret), - std::make_unique( - std::move(protocolLayerResponse.GetRawResponse()))); } Azure::Core::Response @@ -308,36 +264,15 @@ namespace Azure { namespace Storage { namespace Blobs { { Details::BlobRestClient::PageBlob::GetPageBlobPageRangesOptions protocolLayerOptions; protocolLayerOptions.PreviousSnapshotUrl = previousSnapshotUrl; - if (options.Offset.HasValue() && options.Length.HasValue()) - { - protocolLayerOptions.Range = std::make_pair( - options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); - } + protocolLayerOptions.Range = options.Range; protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince; protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince; protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch; protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch; protocolLayerOptions.IfTags = options.AccessConditions.TagConditions; - auto protocolLayerResponse = Details::BlobRestClient::PageBlob::GetPageRanges( + return Details::BlobRestClient::PageBlob::GetPageRanges( options.Context, *m_pipeline, m_blobUrl, protocolLayerOptions); - - Models::GetPageBlobPageRangesResult ret; - ret.ETag = std::move(protocolLayerResponse->ETag); - ret.LastModified = std::move(protocolLayerResponse->LastModified); - ret.BlobContentLength = protocolLayerResponse->BlobContentLength; - for (const auto& range : protocolLayerResponse->PageRanges) - { - ret.PageRanges.emplace_back(Models::PageRange{range.first, range.second - range.first + 1}); - } - for (const auto& range : protocolLayerResponse->ClearRanges) - { - ret.ClearRanges.emplace_back(Models::PageRange{range.first, range.second - range.first + 1}); - } - return Azure::Core::Response( - std::move(ret), - std::make_unique( - std::move(protocolLayerResponse.GetRawResponse()))); } Azure::Core::Response diff --git a/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp index 5c1e71791..f5d175a2b 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_container_client_test.cpp @@ -611,9 +611,9 @@ namespace Azure { namespace Storage { namespace Test { bodyStream.Rewind(); EXPECT_NO_THROW(pageBlob.Resize(blobContent.size())); EXPECT_NO_THROW(pageBlob.UploadPages(0, &bodyStream)); - EXPECT_NO_THROW(pageBlob.ClearPages(0, blobContent.size())); + EXPECT_NO_THROW(pageBlob.ClearPages({0, static_cast(blobContent.size())})); EXPECT_NO_THROW(pageBlob.UploadPagesFromUri( - 0, copySourceBlob.GetUrl() + GetSas(), 0, blobContent.size())); + 0, copySourceBlob.GetUrl() + GetSas(), {0, static_cast(blobContent.size())})); auto pageBlobClientWithoutEncryptionKey = Azure::Storage::Blobs::PageBlobClient::CreateFromConnectionString( @@ -998,17 +998,17 @@ namespace Azure { namespace Storage { namespace Test { Blobs::UploadPageBlobPagesFromUriOptions options; options.AccessConditions.TagConditions = failWhereExpression; EXPECT_THROW( - pageBlobClient.UploadPagesFromUri(0, url, 0, contentSize, options), StorageException); + pageBlobClient.UploadPagesFromUri(0, url, {0, contentSize}, options), StorageException); options.AccessConditions.TagConditions = successWhereExpression; - EXPECT_NO_THROW(pageBlobClient.UploadPagesFromUri(0, url, 0, contentSize, options)); + EXPECT_NO_THROW(pageBlobClient.UploadPagesFromUri(0, url, {0, contentSize}, options)); } { Blobs::ClearPageBlobPagesOptions options; options.AccessConditions.TagConditions = failWhereExpression; - EXPECT_THROW(pageBlobClient.ClearPages(0, contentSize, options), StorageException); + EXPECT_THROW(pageBlobClient.ClearPages({0, contentSize}, options), StorageException); options.AccessConditions.TagConditions = successWhereExpression; - EXPECT_NO_THROW(pageBlobClient.ClearPages(0, contentSize, options)); + EXPECT_NO_THROW(pageBlobClient.ClearPages({0, contentSize}, options)); } { diff --git a/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp index 630bfe7ff..7bd28586b 100644 --- a/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/block_blob_client_test.cpp @@ -90,15 +90,14 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ(res->Metadata, m_blobUploadOptions.Metadata); EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); Azure::Storage::Blobs::DownloadBlobOptions options; - options.Offset = 1_MB; - options.Length = 2_MB; + options.Range = {1_MB, 2_MB}; res = m_blockBlobClient->Download(options); EXPECT_EQ( ReadBodyStream(res->BodyStream), std::vector( - m_blobContent.begin() + static_cast(options.Offset.GetValue()), + m_blobContent.begin() + static_cast(options.Range.GetValue().Offset), m_blobContent.begin() - + static_cast(options.Offset.GetValue() + options.Length.GetValue()))); + + static_cast(options.Range.GetValue().Offset + options.Range.GetValue().Length.GetValue()))); EXPECT_FALSE(res->ContentRange.GetValue().empty()); } @@ -160,9 +159,10 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ(res->BlobType, Azure::Storage::Blobs::Models::BlobType::BlockBlob); Azure::Storage::Blobs::DownloadBlobOptions options; - options.Offset = 0; + options.Range = Core::Http::Range(); + options.Range.GetValue().Offset = 0; EXPECT_THROW(blockBlobClient.Download(options), StorageException); - options.Length = 1; + options.Range.GetValue().Length = 1; EXPECT_THROW(blockBlobClient.Download(options), StorageException); } @@ -358,8 +358,12 @@ namespace Azure { namespace Storage { namespace Test { downloadBuffer.resize(static_cast(downloadSize), '\x00'); Blobs::DownloadBlobToOptions options; options.Concurrency = concurrency; - options.Offset = offset; - options.Length = length; + if (offset.HasValue() || length.HasValue()) + { + options.Range = Core::Http::Range(); + options.Range.GetValue().Offset = offset.GetValue(); + options.Range.GetValue().Length = length; + } options.InitialChunkSize = initialChunkSize; options.ChunkSize = chunkSize; if (actualDownloadSize > 0) @@ -418,8 +422,12 @@ namespace Azure { namespace Storage { namespace Test { } Blobs::DownloadBlobToOptions options; options.Concurrency = concurrency; - options.Offset = offset; - options.Length = length; + if (offset.HasValue() || length.HasValue()) + { + options.Range = Core::Http::Range(); + options.Range.GetValue().Offset = offset.GetValue(); + options.Range.GetValue().Length = length; + } options.InitialChunkSize = initialChunkSize; options.ChunkSize = chunkSize; if (actualDownloadSize > 0) @@ -493,12 +501,13 @@ namespace Azure { namespace Storage { namespace Test { // buffer not big enough Blobs::DownloadBlobToOptions options; options.Concurrency = c; - options.Offset = 1; + options.Range = Core::Http::Range(); + options.Range.GetValue().Offset = 1; for (int64_t length : {1ULL, 2ULL, 4_KB, 5_KB, 8_KB, 11_KB, 20_KB}) { std::vector downloadBuffer; downloadBuffer.resize(static_cast(length - 1)); - options.Length = length; + options.Range.GetValue().Length = length; EXPECT_THROW( m_blockBlobClient->DownloadTo( downloadBuffer.data(), static_cast(length - 1), options), @@ -624,27 +633,28 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_TRUE(ReadFile(tempFilename).empty()); DeleteFile(tempFilename); - options.Offset = 0; + options.Range = Core::Http::Range(); + options.Range.GetValue().Offset = 0; EXPECT_THROW( blockBlobClient.DownloadTo(emptyContent.data(), static_cast(8_MB), options), StorageException); EXPECT_THROW(blockBlobClient.DownloadTo(tempFilename, options), StorageException); - options.Offset = 1; + options.Range.GetValue().Offset = 1; EXPECT_THROW( blockBlobClient.DownloadTo(emptyContent.data(), static_cast(8_MB), options), StorageException); EXPECT_THROW(blockBlobClient.DownloadTo(tempFilename, options), StorageException); - options.Offset = 0; - options.Length = 1; + options.Range.GetValue().Offset = 0; + options.Range.GetValue().Length = 1; EXPECT_THROW( blockBlobClient.DownloadTo(emptyContent.data(), static_cast(8_MB), options), StorageException); EXPECT_THROW(blockBlobClient.DownloadTo(tempFilename, options), StorageException); - options.Offset = 100; - options.Length = 100; + options.Range.GetValue().Offset = 100; + options.Range.GetValue().Length = 100; EXPECT_THROW( blockBlobClient.DownloadTo(emptyContent.data(), static_cast(8_MB), options), StorageException); diff --git a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp index 41878985e..3326e943a 100644 --- a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp @@ -87,7 +87,7 @@ namespace Azure { namespace Storage { namespace Test { // |_|_|x|x| |x|x|_|_| blobContent.insert(blobContent.begin(), static_cast(2_KB), '\x00'); blobContent.resize(static_cast(8_KB), '\x00'); - pageBlobClient.ClearPages(2_KB, 1_KB); + pageBlobClient.ClearPages({2_KB, 1_KB}); // |_|_|_|x| |x|x|_|_| std::fill( blobContent.begin() + static_cast(2_KB), @@ -101,32 +101,33 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_TRUE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Offset), 3_KB); - EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length), 3_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length.GetValue()), 3_KB); Azure::Storage::Blobs::GetPageBlobPageRangesOptions options; - options.Offset = 4_KB; - options.Length = 1_KB; + options.Range = Core::Http::Range(); + options.Range.GetValue().Offset = 4_KB; + options.Range.GetValue().Length = 1_KB; pageRanges = *pageBlobClient.GetPageRanges(options); EXPECT_TRUE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Offset), 4_KB); - EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length), 1_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length.GetValue()), 1_KB); auto snapshot = pageBlobClient.CreateSnapshot()->Snapshot; // |_|_|_|x| |x|x|_|_| This is what's in snapshot blobContent.resize(static_cast(1_KB)); auto pageClient = Azure::Core::Http::MemoryBodyStream(blobContent.data(), blobContent.size()); pageBlobClient.UploadPages(0, &pageClient); - pageBlobClient.ClearPages(3_KB, 1_KB); + pageBlobClient.ClearPages({3_KB, 1_KB}); // |x|_|_|_| |x|x|_|_| pageRanges = *pageBlobClient.GetPageRangesDiff(snapshot); ASSERT_FALSE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); EXPECT_EQ(pageRanges.PageRanges[0].Offset, 0); - EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length), 1_KB); + EXPECT_EQ(static_cast(pageRanges.PageRanges[0].Length.GetValue()), 1_KB); EXPECT_EQ(static_cast(pageRanges.ClearRanges[0].Offset), 3_KB); - EXPECT_EQ(static_cast(pageRanges.ClearRanges[0].Length), 1_KB); + EXPECT_EQ(static_cast(pageRanges.ClearRanges[0].Length.GetValue()), 1_KB); } TEST_F(PageBlobClientTest, UploadFromUri) @@ -135,7 +136,7 @@ namespace Azure { namespace Storage { namespace Test { StandardStorageConnectionString(), m_containerName, RandomString()); pageBlobClient.Create(m_blobContent.size(), m_blobUploadOptions); pageBlobClient.UploadPagesFromUri( - 0, m_pageBlobClient->GetUrl() + GetSas(), 0, m_blobContent.size()); + 0, m_pageBlobClient->GetUrl() + GetSas(), {0, static_cast(m_blobContent.size())}); } TEST_F(PageBlobClientTest, StartCopyIncremental) diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp index 64684f732..c2382ca7e 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_file_client.cpp @@ -319,8 +319,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { Blobs::DownloadBlobOptions blobOptions; blobOptions.Context = options.Context; - blobOptions.Offset = options.Offset; - blobOptions.Length = options.Length; + if (options.Offset.HasValue()) + { + blobOptions.Range = Core::Http::Range(); + blobOptions.Range.GetValue().Offset = options.Offset.GetValue(); + blobOptions.Range.GetValue().Length = options.Length; + } blobOptions.AccessConditions.IfMatch = options.AccessConditions.IfMatch; blobOptions.AccessConditions.IfNoneMatch = options.AccessConditions.IfNoneMatch; blobOptions.AccessConditions.IfModifiedSince = options.AccessConditions.IfModifiedSince;