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?
This commit is contained in:
JinmingHu 2020-12-29 14:50:49 +08:00 committed by GitHub
parent 3a29494989
commit e6a072e7b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 210 additions and 328 deletions

View File

@ -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<int64_t, int64_t>` with `Azure::Core::Http::Range` to denote blob ranges.
- Move version strings into `Details` namespace.
## 12.0.0-beta.5 (2020-11-13)

View File

@ -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<int64_t> Offset;
/**
* @brief Returns at most this number of bytes of the blob from the offset. Null means
* download until the end.
*/
Azure::Core::Nullable<int64_t> Length;
Azure::Core::Nullable<Core::Http::Range> 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<int64_t> Offset;
/**
* @brief Returns at most this number of bytes of the blob from the offset. Null means
* download until the end.
*/
Azure::Core::Nullable<int64_t> Length;
Azure::Core::Nullable<Core::Http::Range> 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<int64_t> SourceOffset;
/**
* @brief Uploads this number of bytes of the source blob from the offset. Null means
* upload until the end.
*/
Azure::Core::Nullable<int64_t> SourceLength;
Azure::Core::Nullable<Core::Http::Range> 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<int64_t> SourceOffset;
/**
* @brief Uploads this number of bytes of the source blob from the offset. Null means
* upload until the end.
*/
Azure::Core::Nullable<int64_t> SourceLength;
Azure::Core::Nullable<Core::Http::Range> 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<int64_t> Offset;
/**
* @brief Optionally specifies the length of range over which to list ranges. The length must be
* a modulus of 512.
*/
Azure::Core::Nullable<int64_t> Length;
Azure::Core::Nullable<Core::Http::Range> Range;
/**
* @brief Optional conditions that must be met to perform this operation.

View File

@ -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<PageRange> PageRanges;
std::vector<PageRange> ClearRanges;
};
}}}} // namespace Azure::Storage::Blobs::Models

View File

@ -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<Models::UploadPageBlobPagesFromUriResult> 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<Models::ClearPageBlobPagesResult> ClearPages(
int64_t offset,
int64_t length,
Azure::Core::Http::Range range,
const ClearPageBlobPagesOptions& options = ClearPageBlobPagesOptions()) const;
/**

View File

@ -289,14 +289,14 @@ namespace Azure { namespace Storage { namespace Blobs {
std::map<std::string, std::string> Tags;
}; // struct GetBlobTagsResult
struct GetPageBlobPageRangesResultInternal
struct GetPageBlobPageRangesResult
{
std::string ETag;
Azure::Core::DateTime LastModified;
int64_t BlobContentLength = 0;
std::vector<std::pair<int64_t, int64_t>> PageRanges;
std::vector<std::pair<int64_t, int64_t>> ClearRanges;
}; // struct GetPageBlobPageRangesResultInternal
std::vector<Azure::Core::Http::Range> PageRanges;
std::vector<Azure::Core::Http::Range> ClearRanges;
}; // struct GetPageBlobPageRangesResult
struct GetUserDelegationKeyResult
{
@ -5345,7 +5345,7 @@ namespace Azure { namespace Storage { namespace Blobs {
struct DownloadBlobOptions
{
Azure::Core::Nullable<int32_t> Timeout;
Azure::Core::Nullable<std::pair<int64_t, int64_t>> Range;
Azure::Core::Nullable<Azure::Core::Http::Range> Range;
Azure::Core::Nullable<std::string> EncryptionKey;
Azure::Core::Nullable<std::vector<uint8_t>> EncryptionKeySha256;
Azure::Core::Nullable<EncryptionAlgorithmType> 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<decltype(endOffset)>::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<int32_t> Timeout;
std::string BlockId;
std::string SourceUri;
Azure::Core::Nullable<std::pair<int64_t, int64_t>> SourceRange;
Azure::Core::Nullable<Azure::Core::Http::Range> SourceRange;
Azure::Core::Nullable<ContentHash> TransactionalContentHash;
Azure::Core::Nullable<std::string> LeaseId;
Azure::Core::Nullable<std::string> 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<decltype(endOffset)>::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<int32_t> Timeout;
std::pair<int64_t, int64_t> Range;
Azure::Core::Http::Range Range;
Azure::Core::Nullable<ContentHash> TransactionalContentHash;
Azure::Core::Nullable<std::string> LeaseId;
Azure::Core::Nullable<int64_t> 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<int32_t> Timeout;
std::string SourceUri;
std::pair<int64_t, int64_t> SourceRange;
std::pair<int64_t, int64_t> Range;
Azure::Core::Http::Range SourceRange;
Azure::Core::Http::Range Range;
Azure::Core::Nullable<ContentHash> TransactionalContentHash;
Azure::Core::Nullable<std::string> LeaseId;
Azure::Core::Nullable<int64_t> 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<int32_t> Timeout;
std::pair<int64_t, int64_t> Range;
Azure::Core::Http::Range Range;
Azure::Core::Nullable<std::string> LeaseId;
Azure::Core::Nullable<int64_t> IfSequenceNumberLessThanOrEqualTo;
Azure::Core::Nullable<int64_t> 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<int32_t> Timeout;
Azure::Core::Nullable<std::string> PreviousSnapshot;
Azure::Core::Nullable<std::string> PreviousSnapshotUrl;
Azure::Core::Nullable<std::pair<int64_t, int64_t>> Range;
Azure::Core::Nullable<Azure::Core::Http::Range> Range;
Azure::Core::Nullable<std::string> LeaseId;
Azure::Core::Nullable<Azure::Core::DateTime> IfModifiedSince;
Azure::Core::Nullable<Azure::Core::DateTime> IfUnmodifiedSince;
@ -8936,7 +8949,7 @@ namespace Azure { namespace Storage { namespace Blobs {
Azure::Core::Nullable<std::string> IfTags;
}; // struct GetPageBlobPageRangesOptions
static Azure::Core::Response<GetPageBlobPageRangesResultInternal> GetPageRanges(
static Azure::Core::Response<GetPageBlobPageRangesResult> 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<decltype(endOffset)>::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<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
httpResponse.GetStatusCode());
@ -9020,7 +9029,7 @@ namespace Azure { namespace Storage { namespace Blobs {
const auto& httpResponseBody = httpResponse.GetBody();
Storage::Details::XmlReader reader(
reinterpret_cast<const char*>(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<GetPageBlobPageRangesResultInternal>(
return Azure::Core::Response<GetPageBlobPageRangesResult>(
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<int64_t, int64_t> 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<int64_t, int64_t> 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<int32_t> Timeout;
std::string SourceUri;
Azure::Core::Nullable<std::pair<int64_t, int64_t>> SourceRange;
Azure::Core::Nullable<Azure::Core::Http::Range> SourceRange;
Azure::Core::Nullable<ContentHash> TransactionalContentHash;
Azure::Core::Nullable<std::string> LeaseId;
Azure::Core::Nullable<int64_t> 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<decltype(endOffset)>::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())
{

View File

@ -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<decltype(options.SourceOffset.GetValue())>>::max());
}
protocolLayerOptions.SourceRange = options.SourceRange;
protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash;
protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId;
protocolLayerOptions.MaxSize = options.AccessConditions.IfMaxSizeLessThanOrEqual;

View File

@ -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<std::remove_reference_t<decltype(options.Offset.GetValue())>>::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)

View File

@ -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<decltype(options.SourceOffset.GetValue())>>::max());
}
protocolLayerOptions.SourceRange = options.SourceRange;
protocolLayerOptions.TransactionalContentHash = options.TransactionalContentHash;
protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId;
protocolLayerOptions.SourceIfModifiedSince = options.SourceConditions.IfModifiedSince;

View File

@ -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<Models::ClearPageBlobPagesResult> 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<Models::GetPageBlobPageRangesResult>(
std::move(ret),
std::make_unique<Azure::Core::Http::RawResponse>(
std::move(protocolLayerResponse.GetRawResponse())));
}
Azure::Core::Response<Models::GetPageBlobPageRangesResult> 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<Models::GetPageBlobPageRangesResult>(
std::move(ret),
std::make_unique<Azure::Core::Http::RawResponse>(
std::move(protocolLayerResponse.GetRawResponse())));
}
Azure::Core::Response<Models::GetPageBlobPageRangesResult>
@ -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<Models::GetPageBlobPageRangesResult>(
std::move(ret),
std::make_unique<Azure::Core::Http::RawResponse>(
std::move(protocolLayerResponse.GetRawResponse())));
}
Azure::Core::Response<Models::StartCopyPageBlobIncrementalResult>

View File

@ -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<int64_t>(blobContent.size())}));
EXPECT_NO_THROW(pageBlob.UploadPagesFromUri(
0, copySourceBlob.GetUrl() + GetSas(), 0, blobContent.size()));
0, copySourceBlob.GetUrl() + GetSas(), {0, static_cast<int64_t>(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));
}
{

View File

@ -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<uint8_t>(
m_blobContent.begin() + static_cast<std::size_t>(options.Offset.GetValue()),
m_blobContent.begin() + static_cast<std::size_t>(options.Range.GetValue().Offset),
m_blobContent.begin()
+ static_cast<std::size_t>(options.Offset.GetValue() + options.Length.GetValue())));
+ static_cast<std::size_t>(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<std::size_t>(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<uint8_t> downloadBuffer;
downloadBuffer.resize(static_cast<std::size_t>(length - 1));
options.Length = length;
options.Range.GetValue().Length = length;
EXPECT_THROW(
m_blockBlobClient->DownloadTo(
downloadBuffer.data(), static_cast<std::size_t>(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<std::size_t>(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<std::size_t>(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<std::size_t>(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<std::size_t>(8_MB), options),
StorageException);

View File

@ -87,7 +87,7 @@ namespace Azure { namespace Storage { namespace Test {
// |_|_|x|x| |x|x|_|_|
blobContent.insert(blobContent.begin(), static_cast<std::size_t>(2_KB), '\x00');
blobContent.resize(static_cast<std::size_t>(8_KB), '\x00');
pageBlobClient.ClearPages(2_KB, 1_KB);
pageBlobClient.ClearPages({2_KB, 1_KB});
// |_|_|_|x| |x|x|_|_|
std::fill(
blobContent.begin() + static_cast<std::size_t>(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<uint64_t>(pageRanges.PageRanges[0].Offset), 3_KB);
EXPECT_EQ(static_cast<uint64_t>(pageRanges.PageRanges[0].Length), 3_KB);
EXPECT_EQ(static_cast<uint64_t>(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<uint64_t>(pageRanges.PageRanges[0].Offset), 4_KB);
EXPECT_EQ(static_cast<uint64_t>(pageRanges.PageRanges[0].Length), 1_KB);
EXPECT_EQ(static_cast<uint64_t>(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<std::size_t>(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<uint64_t>(pageRanges.PageRanges[0].Length), 1_KB);
EXPECT_EQ(static_cast<uint64_t>(pageRanges.PageRanges[0].Length.GetValue()), 1_KB);
EXPECT_EQ(static_cast<uint64_t>(pageRanges.ClearRanges[0].Offset), 3_KB);
EXPECT_EQ(static_cast<uint64_t>(pageRanges.ClearRanges[0].Length), 1_KB);
EXPECT_EQ(static_cast<uint64_t>(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<int64_t>(m_blobContent.size())});
}
TEST_F(PageBlobClientTest, StartCopyIncremental)

View File

@ -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;