From 31c2234ee8c0740570c3992b29dafa6ee33e4840 Mon Sep 17 00:00:00 2001 From: JinmingHu Date: Fri, 26 Feb 2021 14:19:38 +0800 Subject: [PATCH] Operation for copy API (#1747) --- .../azure-storage-files-shares/CHANGELOG.md | 4 + .../azure-storage-files-shares/CMakeLists.txt | 1 + .../files/shares/share_file_client.hpp | 5 +- .../storage/files/shares/share_responses.hpp | 376 ++++++++++-------- .../src/share_file_client.cpp | 13 +- .../src/share_responses.cpp | 63 +++ .../test/share_file_client_test.cpp | 13 +- 7 files changed, 299 insertions(+), 176 deletions(-) create mode 100644 sdk/storage/azure-storage-files-shares/src/share_responses.cpp diff --git a/sdk/storage/azure-storage-files-shares/CHANGELOG.md b/sdk/storage/azure-storage-files-shares/CHANGELOG.md index 60d201146..701f8bd0c 100644 --- a/sdk/storage/azure-storage-files-shares/CHANGELOG.md +++ b/sdk/storage/azure-storage-files-shares/CHANGELOG.md @@ -6,6 +6,10 @@ - Added support for customized application ID. +### Breaking Changes + +- Changed the return type of `StartCopy` API from a `Response` to the particular `Operation` type called `StartCopyShareFileOperation` directly. + ## 12.0.0-beta.8 (2021-02-12) ### New Features diff --git a/sdk/storage/azure-storage-files-shares/CMakeLists.txt b/sdk/storage/azure-storage-files-shares/CMakeLists.txt index e71190a82..7bf5bccda 100644 --- a/sdk/storage/azure-storage-files-shares/CMakeLists.txt +++ b/sdk/storage/azure-storage-files-shares/CMakeLists.txt @@ -51,6 +51,7 @@ set( src/share_file_attributes.cpp src/share_file_client.cpp src/share_lease_client.cpp + src/share_responses.cpp src/share_rest_client.cpp src/share_sas_builder.cpp src/share_service_client.cpp diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp index 7169773f4..c29c12239 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp @@ -197,10 +197,9 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { * snapshot can also be specified as a copy source. * @param options Optional parameters to copy the content of this file. * @param context Context for cancelling long running operations. - * @return Azure::Core::Response containing the copy related - * information. + * @return StartCopyBlobOperation containing the copy related information. */ - Azure::Core::Response StartCopy( + StartCopyShareFileOperation StartCopy( std::string copySource, const StartCopyShareFileOptions& options = StartCopyShareFileOptions(), const Azure::Core::Context& context = Azure::Core::Context()) const; diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp index ace95c63e..2400cbd34 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp @@ -6,175 +6,217 @@ #include "azure/storage/files/shares/protocol/share_rest_client.hpp" #include "azure/storage/files/shares/share_constants.hpp" -namespace Azure { namespace Storage { namespace Files { namespace Shares { namespace Models { +#include - // ServiceClient models: +namespace Azure { namespace Storage { namespace Files { namespace Shares { - using ListSharesSinglePageResult = Details::ServiceListSharesSinglePageResult; - using SetServicePropertiesResult = Details::ServiceSetPropertiesResult; - using GetServicePropertiesResult = FileServiceProperties; + class ShareFileClient; - // ShareClient models: - struct CreateShareResult - { - bool Created = true; + namespace Models { + + // ServiceClient models: + + using ListSharesSinglePageResult = Details::ServiceListSharesSinglePageResult; + using SetServicePropertiesResult = Details::ServiceSetPropertiesResult; + using GetServicePropertiesResult = FileServiceProperties; + + // ShareClient models: + struct CreateShareResult + { + bool Created = true; + Azure::Core::ETag ETag; + Core::DateTime LastModified; + std::string RequestId; + }; + + struct DeleteShareResult + { + bool Deleted = true; + std::string RequestId; + }; + using CreateShareSnapshotResult = Details::ShareCreateSnapshotResult; + using GetSharePropertiesResult = Details::ShareGetPropertiesResult; + using SetSharePropertiesResult = Details::ShareSetPropertiesResult; + using SetShareMetadataResult = Details::ShareSetMetadataResult; + using SetShareAccessPolicyResult = Details::ShareSetAccessPolicyResult; + using GetShareStatisticsResult = Details::ShareGetStatisticsResult; + using CreateSharePermissionResult = Details::ShareCreatePermissionResult; + using GetShareAccessPolicyResult = Details::ShareGetAccessPolicyResult; + using GetSharePermissionResult = Details::ShareGetPermissionResult; + using AcquireShareLeaseResult = Details::ShareAcquireLeaseResult; + using RenewShareLeaseResult = Details::ShareRenewLeaseResult; + using ReleaseShareLeaseResult = Details::ShareReleaseLeaseResult; + using BreakShareLeaseResult = Details::ShareBreakLeaseResult; + using ChangeShareLeaseResult = Details::ShareChangeLeaseResult; + + // DirectoryClient models: + + struct CreateShareDirectoryResult + { + Core::ETag ETag; + Core::DateTime LastModified; + std::string RequestId; + bool IsServerEncrypted = bool(); + FileSmbProperties SmbProperties; + std::string ParentFileId; + bool Created = false; + }; + + struct DeleteShareDirectoryResult + { + bool Deleted = true; + std::string RequestId; + }; + + using GetShareDirectoryPropertiesResult = Details::DirectoryGetPropertiesResult; + using SetShareDirectoryPropertiesResult = Details::DirectorySetPropertiesResult; + using SetShareDirectoryMetadataResult = Details::DirectorySetMetadataResult; + using ForceCloseAllShareDirectoryHandlesSinglePageResult + = Details::DirectoryForceCloseHandlesResult; + + struct ForceCloseShareDirectoryHandleResult + { + std::string RequestId; + }; + + struct ListFilesAndDirectoriesSinglePageResult + { + std::string ServiceEndpoint; + std::string ShareName; + std::string ShareSnapshot; + std::string DirectoryPath; + std::string Prefix; + int32_t PageSizeHint = int32_t(); + Azure::Core::Nullable ContinuationToken; + std::vector DirectoryItems; + std::vector FileItems; + std::string RequestId; + }; + + struct ListShareDirectoryHandlesSinglePageResult + { + std::vector Handles; + Azure::Core::Nullable ContinuationToken; + std::string RequestId; + }; + + // FileClient models: + struct CreateShareFileResult + { + bool Created = true; + Azure::Core::ETag ETag; + Core::DateTime LastModified; + bool IsServerEncrypted = bool(); + FileSmbProperties SmbProperties; + std::string RequestId; + }; + + struct DeleteShareFileResult + { + bool Deleted = true; + std::string RequestId; + }; + + struct DownloadShareFileDetails + { + Core::DateTime LastModified; + Storage::Metadata Metadata; + Core::ETag ETag; + Azure::Core::Nullable CopyCompletedOn; + Azure::Core::Nullable CopyStatusDescription; + Azure::Core::Nullable CopyId; + Azure::Core::Nullable CopyProgress; + Azure::Core::Nullable CopySource; + Azure::Core::Nullable CopyStatus; + bool IsServerEncrypted = bool(); + FileSmbProperties SmbProperties; + Azure::Core::Nullable LeaseDuration; + Azure::Core::Nullable LeaseState; + Azure::Core::Nullable LeaseStatus; + }; + + struct DownloadShareFileResult + { + std::unique_ptr BodyStream; + Azure::Core::Http::Range ContentRange; + int64_t FileSize = 0; + Azure::Core::Nullable TransactionalContentHash; + FileHttpHeaders HttpHeaders; + DownloadShareFileDetails Details; + std::string RequestId; + }; + + using StartCopyShareFileResult = Details::FileStartCopyResult; + using AbortCopyShareFileResult = Details::FileAbortCopyResult; + using GetShareFilePropertiesResult = Details::FileGetPropertiesResult; + using SetShareFilePropertiesResult = Details::FileSetHttpHeadersResult; + using ResizeFileResult = Details::FileSetHttpHeadersResult; + using SetShareFileMetadataResult = Details::FileSetMetadataResult; + using UploadShareFileRangeResult = Details::FileUploadRangeResult; + struct ClearShareFileRangeResult + { + Core::ETag ETag; + Core::DateTime LastModified; + std::string RequestId; + bool IsServerEncrypted = bool(); + }; + using UploadFileRangeFromUriResult = Details::FileUploadRangeFromUrlResult; + using GetShareFileRangeListResult = Details::FileGetRangeListResult; + using ListShareFileHandlesSinglePageResult = ListShareDirectoryHandlesSinglePageResult; + using ForceCloseAllShareFileHandlesSinglePageResult = Details::FileForceCloseHandlesResult; + + struct DownloadShareFileToResult + { + int64_t FileSize = 0; + Azure::Core::Http::Range ContentRange; + FileHttpHeaders HttpHeaders; + DownloadShareFileDetails Details; + }; + + struct ForceCloseShareFileHandleResult + { + std::string RequestId; + }; + + struct UploadShareFileFromResult + { + bool IsServerEncrypted = false; + }; + + } // namespace Models + + class StartCopyShareFileOperation + : public Azure::Core::Operation { + public: + std::string RequestId; Azure::Core::ETag ETag; - Core::DateTime LastModified; - std::string RequestId; + Azure::Core::DateTime LastModified; + std::string CopyId; + Models::CopyStatusType CopyStatus; + Azure::Core::Nullable VersionId; + + public: + Models::GetShareFilePropertiesResult Value() const override { return m_pollResult; } + + ~StartCopyShareFileOperation() override {} + + private: + std::string GetResumeToken() const override + { + // Not supported + std::abort(); + } + + std::unique_ptr PollInternal( + Azure::Core::Context& context) override; + + Azure::Core::Response PollUntilDoneInternal( + Azure::Core::Context& context, + std::chrono::milliseconds period) override; + + std::shared_ptr m_fileClient; + Models::GetShareFilePropertiesResult m_pollResult; + + friend class ShareFileClient; }; - - struct DeleteShareResult - { - bool Deleted = true; - std::string RequestId; - }; - using CreateShareSnapshotResult = Details::ShareCreateSnapshotResult; - using GetSharePropertiesResult = Details::ShareGetPropertiesResult; - using SetSharePropertiesResult = Details::ShareSetPropertiesResult; - using SetShareMetadataResult = Details::ShareSetMetadataResult; - using SetShareAccessPolicyResult = Details::ShareSetAccessPolicyResult; - using GetShareStatisticsResult = Details::ShareGetStatisticsResult; - using CreateSharePermissionResult = Details::ShareCreatePermissionResult; - using GetShareAccessPolicyResult = Details::ShareGetAccessPolicyResult; - using GetSharePermissionResult = Details::ShareGetPermissionResult; - using AcquireShareLeaseResult = Details::ShareAcquireLeaseResult; - using RenewShareLeaseResult = Details::ShareRenewLeaseResult; - using ReleaseShareLeaseResult = Details::ShareReleaseLeaseResult; - using BreakShareLeaseResult = Details::ShareBreakLeaseResult; - using ChangeShareLeaseResult = Details::ShareChangeLeaseResult; - - // DirectoryClient models: - - struct CreateShareDirectoryResult - { - Core::ETag ETag; - Core::DateTime LastModified; - std::string RequestId; - bool IsServerEncrypted = bool(); - FileSmbProperties SmbProperties; - std::string ParentFileId; - bool Created = false; - }; - - struct DeleteShareDirectoryResult - { - bool Deleted = true; - std::string RequestId; - }; - - using GetShareDirectoryPropertiesResult = Details::DirectoryGetPropertiesResult; - using SetShareDirectoryPropertiesResult = Details::DirectorySetPropertiesResult; - using SetShareDirectoryMetadataResult = Details::DirectorySetMetadataResult; - using ForceCloseAllShareDirectoryHandlesSinglePageResult - = Details::DirectoryForceCloseHandlesResult; - - struct ForceCloseShareDirectoryHandleResult - { - std::string RequestId; - }; - - struct ListFilesAndDirectoriesSinglePageResult - { - std::string ServiceEndpoint; - std::string ShareName; - std::string ShareSnapshot; - std::string DirectoryPath; - std::string Prefix; - int32_t PageSizeHint = int32_t(); - Azure::Core::Nullable ContinuationToken; - std::vector DirectoryItems; - std::vector FileItems; - std::string RequestId; - }; - - struct ListShareDirectoryHandlesSinglePageResult - { - std::vector Handles; - Azure::Core::Nullable ContinuationToken; - std::string RequestId; - }; - - // FileClient models: - struct CreateShareFileResult - { - bool Created = true; - Azure::Core::ETag ETag; - Core::DateTime LastModified; - bool IsServerEncrypted = bool(); - FileSmbProperties SmbProperties; - std::string RequestId; - }; - - struct DeleteShareFileResult - { - bool Deleted = true; - std::string RequestId; - }; - - struct DownloadShareFileDetails - { - Core::DateTime LastModified; - Storage::Metadata Metadata; - Core::ETag ETag; - Azure::Core::Nullable CopyCompletedOn; - Azure::Core::Nullable CopyStatusDescription; - Azure::Core::Nullable CopyId; - Azure::Core::Nullable CopyProgress; - Azure::Core::Nullable CopySource; - Azure::Core::Nullable CopyStatus; - bool IsServerEncrypted = bool(); - FileSmbProperties SmbProperties; - Azure::Core::Nullable LeaseDuration; - Azure::Core::Nullable LeaseState; - Azure::Core::Nullable LeaseStatus; - }; - - struct DownloadShareFileResult - { - std::unique_ptr BodyStream; - Azure::Core::Http::Range ContentRange; - int64_t FileSize = 0; - Azure::Core::Nullable TransactionalContentHash; - FileHttpHeaders HttpHeaders; - DownloadShareFileDetails Details; - std::string RequestId; - }; - - using StartCopyShareFileResult = Details::FileStartCopyResult; - using AbortCopyShareFileResult = Details::FileAbortCopyResult; - using GetShareFilePropertiesResult = Details::FileGetPropertiesResult; - using SetShareFilePropertiesResult = Details::FileSetHttpHeadersResult; - using ResizeFileResult = Details::FileSetHttpHeadersResult; - using SetShareFileMetadataResult = Details::FileSetMetadataResult; - using UploadShareFileRangeResult = Details::FileUploadRangeResult; - struct ClearShareFileRangeResult - { - Core::ETag ETag; - Core::DateTime LastModified; - std::string RequestId; - bool IsServerEncrypted = bool(); - }; - using UploadFileRangeFromUriResult = Details::FileUploadRangeFromUrlResult; - using GetShareFileRangeListResult = Details::FileGetRangeListResult; - using ListShareFileHandlesSinglePageResult = ListShareDirectoryHandlesSinglePageResult; - using ForceCloseAllShareFileHandlesSinglePageResult = Details::FileForceCloseHandlesResult; - - struct DownloadShareFileToResult - { - int64_t FileSize = 0; - Azure::Core::Http::Range ContentRange; - FileHttpHeaders HttpHeaders; - DownloadShareFileDetails Details; - }; - - struct ForceCloseShareFileHandleResult - { - std::string RequestId; - }; - - struct UploadShareFileFromResult - { - bool IsServerEncrypted = false; - }; - -}}}}} // namespace Azure::Storage::Files::Shares::Models +}}}} // namespace Azure::Storage::Files::Shares diff --git a/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp b/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp index c64842ba4..e16248e47 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp @@ -310,7 +310,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { std::move(ret), downloadResponse.ExtractRawResponse()); } - Azure::Core::Response ShareFileClient::StartCopy( + StartCopyShareFileOperation ShareFileClient::StartCopy( std::string copySource, const StartCopyShareFileOptions& options, const Azure::Core::Context& context) const @@ -367,8 +367,17 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { protocolLayerOptions.FileCopyIgnoreReadOnly = options.IgnoreReadOnly; protocolLayerOptions.FileCopySetArchiveAttribute = options.SetArchiveAttribute; protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId; - return Details::ShareRestClient::File::StartCopy( + auto response = Details::ShareRestClient::File::StartCopy( m_shareFileUrl, *m_pipeline, context, protocolLayerOptions); + + StartCopyShareFileOperation res; + res.RequestId = std::move(response->RequestId); + res.ETag = std::move(response->ETag); + res.LastModified = std::move(response->LastModified); + res.CopyId = std::move(response->CopyId); + res.CopyStatus = std::move(response->CopyStatus); + res.m_fileClient = std::make_shared(*this); + return res; } Azure::Core::Response ShareFileClient::AbortCopy( diff --git a/sdk/storage/azure-storage-files-shares/src/share_responses.cpp b/sdk/storage/azure-storage-files-shares/src/share_responses.cpp new file mode 100644 index 000000000..2803d781e --- /dev/null +++ b/sdk/storage/azure-storage-files-shares/src/share_responses.cpp @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include "azure/storage/files/shares/share_responses.hpp" + +#include + +#include "azure/storage/files/shares/share_file_client.hpp" + +namespace Azure { namespace Storage { namespace Files { namespace Shares { + + std::unique_ptr StartCopyShareFileOperation::PollInternal( + Azure::Core::Context& context) + { + (void)context; + + auto response = m_fileClient->GetProperties(); + if (!response->CopyStatus.HasValue()) + { + m_status = Azure::Core::OperationStatus::Failed; + } + else if (response->CopyStatus.GetValue() == Models::CopyStatusType::Pending) + { + m_status = Azure::Core::OperationStatus::Running; + } + else if (response->CopyStatus.GetValue() == Models::CopyStatusType::Success) + { + m_status = Azure::Core::OperationStatus::Succeeded; + } + else + { + m_status = Azure::Core::OperationStatus::Failed; + } + m_pollResult = *response; + return response.ExtractRawResponse(); + } + + Azure::Core::Response StartCopyShareFileOperation:: + PollUntilDoneInternal(Azure::Core::Context& context, std::chrono::milliseconds period) + { + while (true) + { + auto rawResponse = PollInternal(context); + + if (m_status == Azure::Core::OperationStatus::Succeeded) + { + return Azure::Core::Response( + m_pollResult, std::move(rawResponse)); + } + else if (m_status == Azure::Core::OperationStatus::Failed) + { + throw Azure::Core::RequestFailedException("Operation failed"); + } + else if (m_status == Azure::Core::OperationStatus::Cancelled) + { + throw Azure::Core::RequestFailedException("Operation was cancelled"); + } + + std::this_thread::sleep_for(period); + }; + } + +}}}} // namespace Azure::Storage::Files::Shares diff --git a/sdk/storage/azure-storage-files-shares/test/share_file_client_test.cpp b/sdk/storage/azure-storage-files-shares/test/share_file_client_test.cpp index b63dd5e8a..f3847356c 100644 --- a/sdk/storage/azure-storage-files-shares/test/share_file_client_test.cpp +++ b/sdk/storage/azure-storage-files-shares/test/share_file_client_test.cpp @@ -680,10 +680,15 @@ namespace Azure { namespace Storage { namespace Test { auto destFileClient = m_shareClient->GetRootDirectoryClient().GetFileClient(LowercaseRandomString(10)); - Files::Shares::Models::StartCopyShareFileResult result; - EXPECT_NO_THROW(result = destFileClient.StartCopy(fileClient.GetUrl()).ExtractValue()); - EXPECT_EQ(Files::Shares::Models::CopyStatusType::Success, result.CopyStatus); - EXPECT_FALSE(result.CopyId.empty()); + auto copyOperation = destFileClient.StartCopy(fileClient.GetUrl()); + EXPECT_FALSE(copyOperation.RequestId.empty()); + EXPECT_TRUE(copyOperation.ETag.HasValue()); + EXPECT_TRUE(IsValidTime(copyOperation.LastModified)); + EXPECT_FALSE(copyOperation.CopyId.empty()); + EXPECT_FALSE(copyOperation.CopyStatus.Get().empty()); + auto fileProperties = *copyOperation.PollUntilDone(std::chrono::milliseconds(1000)); + EXPECT_EQ( + fileProperties.CopyStatus.GetValue(), Files::Shares::Models::CopyStatusType::Success); } {