diff --git a/sdk/storage/azure-storage-blobs/CHANGELOG.md b/sdk/storage/azure-storage-blobs/CHANGELOG.md index c2fed0bce..ca07509f8 100644 --- a/sdk/storage/azure-storage-blobs/CHANGELOG.md +++ b/sdk/storage/azure-storage-blobs/CHANGELOG.md @@ -6,6 +6,7 @@ * `CreateIfNotExists` and `DeleteIfExists` for blob containers and blobs. * Add `IsHierarchicalNamespaceEnabled` in `GetAccountInfoResult`. +* New API: `PageBlobClient::GetPageRangesDiff` and `PageBlobClient::GetManagedDiskPageRangesDiff`. ### Breaking Changes @@ -44,6 +45,7 @@ - `ListContainersSegmentResult` to `ListBlobContainersSegmentResult` - `ListContainersSegmentOptions` to `ListBlobContainersSegmentOptions` * API signature for CommitBlockList has changed. `BlockType` doesn't need to be specified anymore. +* `PageBlobClient::GetPageRanges` doesn't support getting difference between current blob and a snapshot anymore. Use `PageBlobClient::GetPageRangesDiff` instead. ## 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 ba87f28f0..52bc17ccd 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 @@ -1372,22 +1372,6 @@ namespace Azure { namespace Storage { namespace Blobs { */ Azure::Core::Context Context; - /** - * @brief Specifies that the response will contain only pages that were changed between - * target blob and previous snapshot. Changed pages include both updated and cleared pages. - * The target blob may be a snapshot, as long as the snapshot specified by PreviousSnapshot is - * the older of the two. - */ - Azure::Core::Nullable PreviousSnapshot; - - /** - * @brief This parameter only works with managed disk storage accounts. Specifies that - * the response will contain only pages that were changed between target blob and previous - * snapshot. Changed pages include both updated and cleared pages. The target blob may be a - * snapshot, as long as the snapshot specified by PreviousSnapshotUrl is the older of the two. - */ - Azure::Core::Nullable PreviousSnapshotUrl; - /** * @brief Optionally specifies the offset of range over which to list ranges. This offset must * be a modulus of 512. 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 92f0ab1c8..054cc7f38 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 @@ -214,6 +214,38 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Core::Response GetPageRanges( const GetPageBlobPageRangesOptions& options = GetPageBlobPageRangesOptions()) const; + /** + * @brief Returns the list of page ranges that differ between a previous snapshot and this page + * blob. Changes include both updated and cleared pages. + * + * @param previousSnapshot Specifies that the response will contain only pages that were changed + * between target blob and previous snapshot. Changed pages include both updated and cleared + * pages. The target blob may be a snapshot, as long as the snapshot specified by + * previousSnapshot is the older of the two. + * @param options Optional parameters to execute this function. + * @return A GetPageBlobPageRangesResult describing the valid page ranges for this blob. + */ + Azure::Core::Response GetPageRangesDiff( + const std::string& previousSnapshot, + const GetPageBlobPageRangesOptions& options = GetPageBlobPageRangesOptions()) const; + + /** + * @brief Returns the list of page ranges that differ between a previous snapshot url and this + * page blob. Changes include both updated and cleared pages. This API only works with managed + * disk storage accounts. + * + * @param previousSnapshotUrl This parameter only works with managed disk storage accounts. + * Specifies that the response will contain only pages that were changed between target blob and + * previous snapshot. Changed pages include both updated and cleared pages. The target blob may + * be a snapshot, as long as the snapshot specified by previousSnapshotUrl is the older of the + * two. + * @param options Optional parameters to execute this function. + * @return A GetPageBlobPageRangesResult describing the valid page ranges for this blob. + */ + Azure::Core::Response GetManagedDiskPageRangesDiff( + const std::string& previousSnapshotUrl, + const GetPageBlobPageRangesOptions& options = GetPageBlobPageRangesOptions()) const; + /** * @brief Starts copying a snapshot of the sourceUri page blob to this page blob. The snapshot * is copied such that only the differential changes between the previously copied snapshot 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 2b428b15a..c685ef1a5 100644 --- a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp @@ -233,8 +233,83 @@ namespace Azure { namespace Storage { namespace Blobs { const GetPageBlobPageRangesOptions& options) const { Details::BlobRestClient::PageBlob::GetPageBlobPageRangesOptions protocolLayerOptions; - protocolLayerOptions.PreviousSnapshot = options.PreviousSnapshot; - protocolLayerOptions.PreviousSnapshotUrl = options.PreviousSnapshotUrl; + if (options.Offset.HasValue() && options.Length.HasValue()) + { + protocolLayerOptions.Range = std::make_pair( + options.Offset.GetValue(), options.Offset.GetValue() + options.Length.GetValue() - 1); + } + 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( + 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( + const std::string& previousSnapshot, + const GetPageBlobPageRangesOptions& options) const + { + 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.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( + 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::GetManagedDiskPageRangesDiff( + const std::string& previousSnapshotUrl, + const GetPageBlobPageRangesOptions& options) const + { + Details::BlobRestClient::PageBlob::GetPageBlobPageRangesOptions protocolLayerOptions; + protocolLayerOptions.PreviousSnapshotUrl = previousSnapshotUrl; if (options.Offset.HasValue() && options.Length.HasValue()) { protocolLayerOptions.Range = std::make_pair( 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 bfabff94e..0675d4d8d 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 @@ -120,9 +120,7 @@ namespace Azure { namespace Storage { namespace Test { pageBlobClient.ClearPages(3_KB, 1_KB); // |x|_|_|_| |x|x|_|_| - options = Azure::Storage::Blobs::GetPageBlobPageRangesOptions(); - options.PreviousSnapshot = snapshot; - pageRanges = *pageBlobClient.GetPageRanges(options); + pageRanges = *pageBlobClient.GetPageRangesDiff(snapshot); ASSERT_FALSE(pageRanges.ClearRanges.empty()); ASSERT_FALSE(pageRanges.PageRanges.empty()); EXPECT_EQ(pageRanges.PageRanges[0].Offset, 0);