From c4b88f933ee74e45bc0539544f7d07c050d16ef1 Mon Sep 17 00:00:00 2001 From: JinmingHu Date: Fri, 16 Jul 2021 15:43:51 +0800 Subject: [PATCH] Fixed a bug where sequence number access conditions didn't work for page blob operations (#2643) * PageBlobClient::Resize doesn't support sequence number access conditions * PageBlobClient::UpdateSequenceNumber doesn't support seq access conditions * Fixed a bug where sequence number access conditions didn't work for page blob operations --- sdk/storage/azure-storage-blobs/CHANGELOG.md | 1 + .../blobs/protocol/blob_rest_client.hpp | 42 ------- .../src/page_blob_client.cpp | 15 +++ .../test/ut/page_blob_client_test.cpp | 111 ++++++++++++++++++ 4 files changed, 127 insertions(+), 42 deletions(-) diff --git a/sdk/storage/azure-storage-blobs/CHANGELOG.md b/sdk/storage/azure-storage-blobs/CHANGELOG.md index 68b6a64bb..c54fac5ad 100644 --- a/sdk/storage/azure-storage-blobs/CHANGELOG.md +++ b/sdk/storage/azure-storage-blobs/CHANGELOG.md @@ -16,6 +16,7 @@ ### Bugs Fixed - Fixed a bug where lease ID didn't work for `BlobContainerClient::GetAccessPolicy()`. +- Fixed a bug where sequence number access conditions didn't work for page blob operations. - Fixed a bug where `BlobItemDetails::EncryptionKeySha256` was always null because it wasn't correctly parsed from xml. ### Other Changes 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 d9b776969..74a950b9a 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 @@ -10270,9 +10270,6 @@ namespace Azure { namespace Storage { namespace Blobs { Azure::Nullable Timeout; int64_t BlobSize = -1; Azure::Nullable LeaseId; - Azure::Nullable IfSequenceNumberLessThanOrEqualTo; - Azure::Nullable IfSequenceNumberLessThan; - Azure::Nullable IfSequenceNumberEqualTo; Azure::Nullable IfModifiedSince; Azure::Nullable IfUnmodifiedSince; Azure::ETag IfMatch; @@ -10301,24 +10298,6 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - if (options.IfSequenceNumberLessThanOrEqualTo.HasValue()) - { - request.SetHeader( - "x-ms-if-sequence-number-le", - std::to_string(options.IfSequenceNumberLessThanOrEqualTo.Value())); - } - if (options.IfSequenceNumberLessThan.HasValue()) - { - request.SetHeader( - "x-ms-if-sequence-number-lt", - std::to_string(options.IfSequenceNumberLessThan.Value())); - } - if (options.IfSequenceNumberEqualTo.HasValue()) - { - request.SetHeader( - "x-ms-if-sequence-number-eq", - std::to_string(options.IfSequenceNumberEqualTo.Value())); - } if (options.IfModifiedSince.HasValue()) { request.SetHeader( @@ -10368,9 +10347,6 @@ namespace Azure { namespace Storage { namespace Blobs { SequenceNumberAction Action; Azure::Nullable SequenceNumber; Azure::Nullable LeaseId; - Azure::Nullable IfSequenceNumberLessThanOrEqualTo; - Azure::Nullable IfSequenceNumberLessThan; - Azure::Nullable IfSequenceNumberEqualTo; Azure::Nullable IfModifiedSince; Azure::Nullable IfUnmodifiedSince; Azure::ETag IfMatch; @@ -10398,24 +10374,6 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - if (options.IfSequenceNumberLessThanOrEqualTo.HasValue()) - { - request.SetHeader( - "x-ms-if-sequence-number-le", - std::to_string(options.IfSequenceNumberLessThanOrEqualTo.Value())); - } - if (options.IfSequenceNumberLessThan.HasValue()) - { - request.SetHeader( - "x-ms-if-sequence-number-lt", - std::to_string(options.IfSequenceNumberLessThan.Value())); - } - if (options.IfSequenceNumberEqualTo.HasValue()) - { - request.SetHeader( - "x-ms-if-sequence-number-eq", - std::to_string(options.IfSequenceNumberEqualTo.Value())); - } if (options.IfModifiedSince.HasValue()) { request.SetHeader( 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 cf3dbea91..2077b9386 100644 --- a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp @@ -145,6 +145,11 @@ namespace Azure { namespace Storage { namespace Blobs { protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch; protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch; protocolLayerOptions.IfTags = options.AccessConditions.TagConditions; + protocolLayerOptions.IfSequenceNumberLessThanOrEqualTo + = options.AccessConditions.IfSequenceNumberLessThanOrEqual; + protocolLayerOptions.IfSequenceNumberLessThan + = options.AccessConditions.IfSequenceNumberLessThan; + protocolLayerOptions.IfSequenceNumberEqualTo = options.AccessConditions.IfSequenceNumberEqual; if (m_customerProvidedKey.HasValue()) { protocolLayerOptions.EncryptionKey = m_customerProvidedKey.Value().Key; @@ -175,6 +180,11 @@ namespace Azure { namespace Storage { namespace Blobs { protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch; protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch; protocolLayerOptions.IfTags = options.AccessConditions.TagConditions; + protocolLayerOptions.IfSequenceNumberLessThanOrEqualTo + = options.AccessConditions.IfSequenceNumberLessThanOrEqual; + protocolLayerOptions.IfSequenceNumberLessThan + = options.AccessConditions.IfSequenceNumberLessThan; + protocolLayerOptions.IfSequenceNumberEqualTo = options.AccessConditions.IfSequenceNumberEqual; protocolLayerOptions.SourceIfModifiedSince = options.SourceAccessConditions.IfModifiedSince; protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceAccessConditions.IfUnmodifiedSince; protocolLayerOptions.SourceIfMatch = options.SourceAccessConditions.IfMatch; @@ -203,6 +213,11 @@ namespace Azure { namespace Storage { namespace Blobs { protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch; protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch; protocolLayerOptions.IfTags = options.AccessConditions.TagConditions; + protocolLayerOptions.IfSequenceNumberLessThanOrEqualTo + = options.AccessConditions.IfSequenceNumberLessThanOrEqual; + protocolLayerOptions.IfSequenceNumberLessThan + = options.AccessConditions.IfSequenceNumberLessThan; + protocolLayerOptions.IfSequenceNumberEqualTo = options.AccessConditions.IfSequenceNumberEqual; if (m_customerProvidedKey.HasValue()) { protocolLayerOptions.EncryptionKey = m_customerProvidedKey.Value().Key; diff --git a/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp index b456a43a5..6ddb48821 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp @@ -442,4 +442,115 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ(blobClient.GetProperties().Value.HttpHeaders.ContentType, headers.ContentType); } + TEST_F(PageBlobClientTest, PageBlobAccessConditions) + { + auto blobClient = Azure::Storage::Blobs::PageBlobClient::CreateFromConnectionString( + StandardStorageConnectionString(), m_containerName, RandomString()); + blobClient.Create(1024); + Blobs::UpdatePageBlobSequenceNumberOptions updateSequenceNumberOptions; + updateSequenceNumberOptions.SequenceNumber = 100; + blobClient.UpdateSequenceNumber( + Blobs::Models::SequenceNumberAction::Update, updateSequenceNumberOptions); + + enum class AccessConditionType + { + Eq, + Lt, + LtOrEq, + }; + enum class Operation + { + Upload, + UploadFromUri, + Clear, + }; + for (auto o : {Operation::Upload, Operation::UploadFromUri, Operation::Clear}) + { + + for (auto willSuccess : {true, false}) + { + for (auto t : + {AccessConditionType::Eq, AccessConditionType::Lt, AccessConditionType::LtOrEq}) + { + Blobs::PageBlobAccessConditions accessConditions; + if (t == AccessConditionType::Eq) + { + accessConditions.IfSequenceNumberEqual + = blobClient.GetProperties().Value.SequenceNumber.Value(); + if (!willSuccess) + { + accessConditions.IfSequenceNumberEqual.Value()++; + } + } + else if (t == AccessConditionType::Lt) + { + accessConditions.IfSequenceNumberLessThan + = blobClient.GetProperties().Value.SequenceNumber.Value(); + if (willSuccess) + { + accessConditions.IfSequenceNumberLessThan.Value()++; + } + } + else if (t == AccessConditionType::LtOrEq) + { + accessConditions.IfSequenceNumberLessThanOrEqual + = blobClient.GetProperties().Value.SequenceNumber.Value(); + if (!willSuccess) + { + accessConditions.IfSequenceNumberLessThanOrEqual.Value()--; + } + } + + if (o == Operation::Upload) + { + std::vector pageContent(512); + auto pageContentStream + = Azure::Core::IO::MemoryBodyStream(pageContent.data(), pageContent.size()); + + Blobs::UploadPagesOptions options; + options.AccessConditions = accessConditions; + if (willSuccess) + { + EXPECT_NO_THROW(blobClient.UploadPages(0, pageContentStream, options)); + } + else + { + EXPECT_THROW(blobClient.UploadPages(0, pageContentStream, options), StorageException); + } + } + else if (o == Operation::UploadFromUri) + { + Blobs::UploadPagesFromUriOptions options; + options.AccessConditions = accessConditions; + if (willSuccess) + { + EXPECT_NO_THROW(blobClient.UploadPagesFromUri( + 512, blobClient.GetUrl() + GetSas(), {0, 512}, options)); + } + else + { + EXPECT_THROW( + blobClient.UploadPagesFromUri( + 512, blobClient.GetUrl() + GetSas(), {0, 512}, options), + StorageException); + } + } + else if (o == Operation::Clear) + { + Blobs::ClearPagesOptions options; + options.AccessConditions = accessConditions; + if (willSuccess) + { + EXPECT_NO_THROW(blobClient.ClearPages({0, 512}, options)); + } + else + { + EXPECT_THROW(blobClient.ClearPages({0, 512}, options), StorageException); + } + } + } + } + } + } + }}} // namespace Azure::Storage::Test