Blob batch improvement (#3790)
This commit is contained in:
parent
e7e7db6d79
commit
9aeefefbbc
@ -3,14 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <azure/core/nullable.hpp>
|
||||
#include <azure/core/url.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "azure/storage/blobs/blob_client.hpp"
|
||||
#include "azure/storage/blobs/blob_container_client.hpp"
|
||||
@ -20,7 +15,8 @@
|
||||
namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
namespace _detail {
|
||||
extern const Core::Context::Key s_batchKey;
|
||||
extern const Core::Context::Key s_serviceBatchKey;
|
||||
extern const Core::Context::Key s_containerBatchKey;
|
||||
|
||||
class StringBodyStream final : public Core::IO::BodyStream {
|
||||
public:
|
||||
@ -55,7 +51,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
BatchSubrequestType Type;
|
||||
};
|
||||
|
||||
struct BlobBatchAccessHelper;
|
||||
class BlobBatchAccessHelper;
|
||||
|
||||
std::shared_ptr<Azure::Core::Http::_internal::HttpPipeline> ConstructBatchRequestPolicy(
|
||||
const std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>>&
|
||||
@ -72,16 +68,15 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
/**
|
||||
* @brief A batch object allows you to batch multiple operations in a single request via
|
||||
* #Azure::Storage::Blobs::BlobServiceClient::SubmitBatch or
|
||||
* #Azure::Storage::Blobs::BlobContainerClient::SubmitBatch.
|
||||
* #Azure::Storage::Blobs::BlobServiceClient::SubmitBatch.
|
||||
*/
|
||||
class BlobBatch final {
|
||||
class BlobServiceBatch final {
|
||||
public:
|
||||
/**
|
||||
* @brief Adds a delete subrequest into batch object.
|
||||
*
|
||||
* @param blobContainerName Container name of the blob to delete.
|
||||
* @param blobName Blob name of the blob to delete.
|
||||
* @param blobName Name of the blob to delete.
|
||||
* @param options Optional parameters to execute the delete operation.
|
||||
* @return A deferred response which can produce a Response<DeleteBlobResult> after batch object
|
||||
* is submitted.
|
||||
@ -99,7 +94,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
* @return A deferred response which can produce a Response<DeleteBlobResult> after batch object
|
||||
* is submitted.
|
||||
*/
|
||||
DeferredResponse<Models::DeleteBlobResult> DeleteBlob(
|
||||
DeferredResponse<Models::DeleteBlobResult> DeleteBlobUrl(
|
||||
const std::string& blobUrl,
|
||||
const DeleteBlobOptions& options = DeleteBlobOptions());
|
||||
|
||||
@ -107,7 +102,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
* @brief Adds a change tier subrequest into batch object.
|
||||
*
|
||||
* @param blobContainerName Container name of the blob to delete.
|
||||
* @param blobName Blob name of the blob to delete.
|
||||
* @param blobName Name of the blob to delete.
|
||||
* @param accessTier Indicates the tier to be set on the blob.
|
||||
* @param options Optional parameters to execute the delete operation.
|
||||
* @return A deferred response which can produce a Response<SetBlobAccessTierResult> after batch
|
||||
@ -128,27 +123,95 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
* @return A deferred response which can produce a Response<SetBlobAccessTierResult> after batch
|
||||
* object is submitted.
|
||||
*/
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> SetBlobAccessTier(
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> SetBlobAccessTierUrl(
|
||||
const std::string& blobUrl,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options = SetBlobAccessTierOptions());
|
||||
|
||||
private:
|
||||
explicit BlobBatch(BlobServiceClient blobServiceClient);
|
||||
explicit BlobBatch(BlobContainerClient blobContainerClient);
|
||||
explicit BlobServiceBatch(BlobServiceClient blobServiceClient);
|
||||
|
||||
BlobClient GetBlobClientForSubrequest(Core::Url url) const;
|
||||
|
||||
private:
|
||||
Core::Url m_url;
|
||||
Nullable<BlobServiceClient> m_blobServiceClient;
|
||||
Nullable<BlobContainerClient> m_blobContainerClient;
|
||||
BlobServiceClient m_blobServiceClient;
|
||||
|
||||
std::vector<std::shared_ptr<_detail::BatchSubrequest>> m_subrequests;
|
||||
|
||||
friend class BlobServiceClient;
|
||||
friend class _detail::BlobBatchAccessHelper;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A batch object allows you to batch multiple operations in a single request via
|
||||
* #Azure::Storage::Blobs::BlobContainerClient::SubmitBatch.
|
||||
*/
|
||||
class BlobContainerBatch final {
|
||||
public:
|
||||
/**
|
||||
* @brief Adds a delete subrequest into batch object.
|
||||
*
|
||||
* @param blobName Name of the blob to delete.
|
||||
* @param options Optional parameters to execute the delete operation.
|
||||
* @return A deferred response which can produce a Response<DeleteBlobResult> after batch object
|
||||
* is submitted.
|
||||
*/
|
||||
DeferredResponse<Models::DeleteBlobResult> DeleteBlob(
|
||||
const std::string& blobName,
|
||||
const DeleteBlobOptions& options = DeleteBlobOptions());
|
||||
|
||||
/**
|
||||
* @brief Adds a delete subrequest into batch object.
|
||||
*
|
||||
* @param blobUrl Url of the blob to delete.
|
||||
* @param options Optional parameters to execute the delete operation.
|
||||
* @return A deferred response which can produce a Response<DeleteBlobResult> after batch object
|
||||
* is submitted.
|
||||
*/
|
||||
DeferredResponse<Models::DeleteBlobResult> DeleteBlobUrl(
|
||||
const std::string& blobUrl,
|
||||
const DeleteBlobOptions& options = DeleteBlobOptions());
|
||||
|
||||
/**
|
||||
* @brief Adds a change tier subrequest into batch object.
|
||||
*
|
||||
* @param blobName Name of the blob to delete.
|
||||
* @param accessTier Indicates the tier to be set on the blob.
|
||||
* @param options Optional parameters to execute the delete operation.
|
||||
* @return A deferred response which can produce a Response<SetBlobAccessTierResult> after batch
|
||||
* object is submitted.
|
||||
*/
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> SetBlobAccessTier(
|
||||
const std::string& blobName,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options = SetBlobAccessTierOptions());
|
||||
|
||||
/**
|
||||
* @brief Adds a change tier subrequest into batch object.
|
||||
*
|
||||
* @param blobUrl Url of the blob to delete.
|
||||
* @param accessTier Indicates the tier to be set on the blob.
|
||||
* @param options Optional parameters to execute the delete operation.
|
||||
* @return A deferred response which can produce a Response<SetBlobAccessTierResult> after batch
|
||||
* object is submitted.
|
||||
*/
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> SetBlobAccessTierUrl(
|
||||
const std::string& blobUrl,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options = SetBlobAccessTierOptions());
|
||||
|
||||
private:
|
||||
explicit BlobContainerBatch(BlobContainerClient blobContainerClient);
|
||||
|
||||
BlobClient GetBlobClientForSubrequest(Core::Url url) const;
|
||||
|
||||
private:
|
||||
BlobContainerClient m_blobContainerClient;
|
||||
|
||||
std::vector<std::shared_ptr<_detail::BatchSubrequest>> m_subrequests;
|
||||
|
||||
friend class BlobContainerClient;
|
||||
friend struct _detail::BlobBatchAccessHelper;
|
||||
friend class _detail::BlobBatchAccessHelper;
|
||||
};
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -431,6 +431,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
friend class Files::DataLake::DataLakeDirectoryClient;
|
||||
friend class Files::DataLake::DataLakeFileClient;
|
||||
friend class BlobLeaseClient;
|
||||
friend class BlobBatch;
|
||||
friend class BlobServiceBatch;
|
||||
friend class BlobContainerBatch;
|
||||
};
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
class BlobLeaseClient;
|
||||
class BlobBatch;
|
||||
class BlobContainerBatch;
|
||||
|
||||
/**
|
||||
* The BlobContainerClient allows you to manipulate Azure Storage containers and their
|
||||
@ -291,7 +291,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
*
|
||||
* @return A new batch object.
|
||||
*/
|
||||
BlobBatch CreateBatch();
|
||||
BlobContainerBatch CreateBatch();
|
||||
|
||||
/**
|
||||
* @brief Submits a batch of subrequests.
|
||||
@ -304,7 +304,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
* (parent request).
|
||||
*/
|
||||
Response<Models::SubmitBlobBatchResult> SubmitBatch(
|
||||
const BlobBatch& batch,
|
||||
const BlobContainerBatch& batch,
|
||||
const SubmitBlobBatchOptions& options = SubmitBlobBatchOptions(),
|
||||
const Core::Context& context = Core::Context()) const;
|
||||
|
||||
@ -319,7 +319,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
friend class BlobServiceClient;
|
||||
friend class BlobLeaseClient;
|
||||
friend class BlobBatch;
|
||||
friend class BlobContainerBatch;
|
||||
};
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
class BlobBatch;
|
||||
class BlobServiceBatch;
|
||||
|
||||
/**
|
||||
* The BlobServiceClient allows you to manipulate Azure Storage service resources and blob
|
||||
@ -251,7 +251,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
*
|
||||
* @return A new batch object.
|
||||
*/
|
||||
BlobBatch CreateBatch();
|
||||
BlobServiceBatch CreateBatch();
|
||||
|
||||
/**
|
||||
* @brief Submits a batch of subrequests.
|
||||
@ -264,7 +264,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
* (parent request).
|
||||
*/
|
||||
Response<Models::SubmitBlobBatchResult> SubmitBatch(
|
||||
const BlobBatch& batch,
|
||||
const BlobServiceBatch& batch,
|
||||
const SubmitBlobBatchOptions& options = SubmitBlobBatchOptions(),
|
||||
const Core::Context& context = Core::Context()) const;
|
||||
|
||||
@ -277,6 +277,6 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::shared_ptr<Azure::Core::Http::_internal::HttpPipeline> m_batchRequestPipeline;
|
||||
std::shared_ptr<Azure::Core::Http::_internal::HttpPipeline> m_batchSubrequestPipeline;
|
||||
|
||||
friend class BlobBatch;
|
||||
friend class BlobServiceBatch;
|
||||
};
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -9,8 +9,9 @@
|
||||
|
||||
namespace Azure { namespace Storage {
|
||||
namespace Blobs {
|
||||
class BlobBatch;
|
||||
}
|
||||
class BlobServiceBatch;
|
||||
class BlobContainerBatch;
|
||||
} // namespace Blobs
|
||||
/**
|
||||
* @brief Base type for a deferred response.
|
||||
*/
|
||||
@ -37,6 +38,7 @@ namespace Azure { namespace Storage {
|
||||
private:
|
||||
std::function<Response<T>()> m_func;
|
||||
|
||||
friend class Blobs::BlobBatch;
|
||||
friend class Blobs::BlobServiceBatch;
|
||||
friend class Blobs::BlobContainerBatch;
|
||||
};
|
||||
}} // namespace Azure::Storage
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <azure/core/azure_assert.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
@ -22,19 +21,24 @@
|
||||
|
||||
namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
const Core::Context::Key _detail::s_batchKey;
|
||||
const Core::Context::Key _detail::s_serviceBatchKey;
|
||||
const Core::Context::Key _detail::s_containerBatchKey;
|
||||
|
||||
namespace _detail {
|
||||
|
||||
struct BlobBatchAccessHelper
|
||||
{
|
||||
explicit BlobBatchAccessHelper(const BlobBatch& batch) : m_batch(&batch) {}
|
||||
class BlobBatchAccessHelper final {
|
||||
public:
|
||||
explicit BlobBatchAccessHelper(const BlobServiceBatch& batch) : m_serviceBatch(&batch) {}
|
||||
explicit BlobBatchAccessHelper(const BlobContainerBatch& batch) : m_containerBatch(&batch) {}
|
||||
|
||||
const std::vector<std::shared_ptr<BatchSubrequest>>& Subrequests() const
|
||||
{
|
||||
return m_batch->m_subrequests;
|
||||
return m_serviceBatch ? m_serviceBatch->m_subrequests : m_containerBatch->m_subrequests;
|
||||
}
|
||||
const BlobBatch* m_batch;
|
||||
|
||||
private:
|
||||
const BlobServiceBatch* m_serviceBatch = nullptr;
|
||||
const BlobContainerBatch* m_containerBatch = nullptr;
|
||||
};
|
||||
|
||||
} // namespace _detail
|
||||
@ -263,21 +267,29 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
struct DeleteBlobSubrequest final : public _detail::BatchSubrequest
|
||||
{
|
||||
DeleteBlobSubrequest() : BatchSubrequest(_detail::BatchSubrequestType::DeleteBlob) {}
|
||||
DeleteBlobSubrequest(Blobs::BlobClient blobClient, DeleteBlobOptions options)
|
||||
: BatchSubrequest(_detail::BatchSubrequestType::DeleteBlob),
|
||||
Client(std::move(blobClient)), Options(std::move(options))
|
||||
{
|
||||
}
|
||||
|
||||
Nullable<Blobs::BlobClient> Client;
|
||||
Blobs::BlobClient Client;
|
||||
DeleteBlobOptions Options;
|
||||
std::promise<Nullable<Response<Models::DeleteBlobResult>>> Promise;
|
||||
};
|
||||
|
||||
struct SetBlobAccessTierSubrequest final : public _detail::BatchSubrequest
|
||||
{
|
||||
SetBlobAccessTierSubrequest()
|
||||
: BatchSubrequest(_detail::BatchSubrequestType::SetBlobAccessTier)
|
||||
SetBlobAccessTierSubrequest(
|
||||
Blobs::BlobClient blobClient,
|
||||
Models::AccessTier tier,
|
||||
SetBlobAccessTierOptions options)
|
||||
: BatchSubrequest(_detail::BatchSubrequestType::SetBlobAccessTier),
|
||||
Client(std::move(blobClient)), Tier(std::move(tier)), Options(std::move(options))
|
||||
{
|
||||
}
|
||||
|
||||
Nullable<Blobs::BlobClient> Client;
|
||||
Blobs::BlobClient Client;
|
||||
Models::AccessTier Tier;
|
||||
SetBlobAccessTierOptions Options;
|
||||
std::promise<Nullable<Response<Models::SetBlobAccessTierResult>>> Promise;
|
||||
@ -298,17 +310,32 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
std::string requestBody;
|
||||
|
||||
const BlobBatch* batch = nullptr;
|
||||
context.TryGetValue(_detail::s_batchKey, batch);
|
||||
std::unique_ptr<_detail::BlobBatchAccessHelper> batchAccessHelper;
|
||||
{
|
||||
const BlobServiceBatch* batch = nullptr;
|
||||
context.TryGetValue(_detail::s_serviceBatchKey, batch);
|
||||
if (batch)
|
||||
{
|
||||
batchAccessHelper = std::make_unique<_detail::BlobBatchAccessHelper>(*batch);
|
||||
}
|
||||
}
|
||||
{
|
||||
const BlobContainerBatch* batch = nullptr;
|
||||
context.TryGetValue(_detail::s_containerBatchKey, batch);
|
||||
if (batch)
|
||||
{
|
||||
batchAccessHelper = std::make_unique<_detail::BlobBatchAccessHelper>(*batch);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& subrequestPtr : _detail::BlobBatchAccessHelper(*batch).Subrequests())
|
||||
for (const auto& subrequestPtr : batchAccessHelper->Subrequests())
|
||||
{
|
||||
if (subrequestPtr->Type == _detail::BatchSubrequestType::DeleteBlob)
|
||||
{
|
||||
auto& subrequest = *static_cast<DeleteBlobSubrequest*>(subrequestPtr.get());
|
||||
requestBody += getBatchBoundary();
|
||||
std::string subrequestText;
|
||||
subrequest.Client.Value().Delete(
|
||||
subrequest.Client.Delete(
|
||||
subrequest.Options, Core::Context().WithValue(s_subrequestKey, &subrequestText));
|
||||
requestBody += subrequestText;
|
||||
}
|
||||
@ -318,7 +345,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
requestBody += getBatchBoundary();
|
||||
|
||||
std::string subrequestText;
|
||||
subrequest.Client.Value().SetAccessTier(
|
||||
subrequest.Client.SetAccessTier(
|
||||
subrequest.Tier,
|
||||
subrequest.Options,
|
||||
Core::Context().WithValue(s_subrequestKey, &subrequestText));
|
||||
@ -391,18 +418,33 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
}
|
||||
}
|
||||
|
||||
const BlobBatch* batch = nullptr;
|
||||
context.TryGetValue(_detail::s_batchKey, batch);
|
||||
std::unique_ptr<_detail::BlobBatchAccessHelper> batchAccessHelper;
|
||||
{
|
||||
const BlobServiceBatch* batch = nullptr;
|
||||
context.TryGetValue(_detail::s_serviceBatchKey, batch);
|
||||
if (batch)
|
||||
{
|
||||
batchAccessHelper = std::make_unique<_detail::BlobBatchAccessHelper>(*batch);
|
||||
}
|
||||
}
|
||||
{
|
||||
const BlobContainerBatch* batch = nullptr;
|
||||
context.TryGetValue(_detail::s_containerBatchKey, batch);
|
||||
if (batch)
|
||||
{
|
||||
batchAccessHelper = std::make_unique<_detail::BlobBatchAccessHelper>(*batch);
|
||||
}
|
||||
}
|
||||
|
||||
size_t subresponseCounter = 0;
|
||||
for (const auto& subrequestPtr : _detail::BlobBatchAccessHelper(*batch).Subrequests())
|
||||
for (const auto& subrequestPtr : batchAccessHelper->Subrequests())
|
||||
{
|
||||
if (subrequestPtr->Type == _detail::BatchSubrequestType::DeleteBlob)
|
||||
{
|
||||
auto& subrequest = *static_cast<DeleteBlobSubrequest*>(subrequestPtr.get());
|
||||
try
|
||||
{
|
||||
auto response = subrequest.Client.Value().Delete(
|
||||
auto response = subrequest.Client.Delete(
|
||||
subrequest.Options,
|
||||
Core::Context().WithValue(s_subresponseKey, &subresponses[subresponseCounter++]));
|
||||
subrequest.Promise.set_value(std::move(response));
|
||||
@ -417,7 +459,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
auto& subrequest = *static_cast<SetBlobAccessTierSubrequest*>(subrequestPtr.get());
|
||||
try
|
||||
{
|
||||
auto response = subrequest.Client.Value().SetAccessTier(
|
||||
auto response = subrequest.Client.SetAccessTier(
|
||||
subrequest.Tier,
|
||||
subrequest.Options,
|
||||
Core::Context().WithValue(s_subresponseKey, &subresponses[subresponseCounter++]));
|
||||
@ -518,108 +560,141 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
}
|
||||
} // namespace _detail
|
||||
|
||||
BlobBatch::BlobBatch(BlobServiceClient blobServiceClient)
|
||||
BlobServiceBatch::BlobServiceBatch(BlobServiceClient blobServiceClient)
|
||||
: m_blobServiceClient(std::move(blobServiceClient))
|
||||
{
|
||||
m_url = m_blobServiceClient.Value().m_serviceUrl;
|
||||
}
|
||||
|
||||
BlobBatch::BlobBatch(BlobContainerClient blobContainerClient)
|
||||
BlobClient BlobServiceBatch::GetBlobClientForSubrequest(Core::Url url) const
|
||||
{
|
||||
auto blobClient = m_blobServiceClient.GetBlobContainerClient("$").GetBlobClient("$");
|
||||
blobClient.m_blobUrl = std::move(url);
|
||||
blobClient.m_pipeline = m_blobServiceClient.m_batchSubrequestPipeline;
|
||||
return blobClient;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::DeleteBlobResult> BlobServiceBatch::DeleteBlob(
|
||||
const std::string& blobContainerName,
|
||||
const std::string& blobName,
|
||||
const DeleteBlobOptions& options)
|
||||
{
|
||||
auto blobUrl = m_blobServiceClient.m_serviceUrl;
|
||||
blobUrl.AppendPath(_internal::UrlEncodePath(blobContainerName));
|
||||
blobUrl.AppendPath(_internal::UrlEncodePath(blobName));
|
||||
auto op = std::make_shared<DeleteBlobSubrequest>(
|
||||
GetBlobClientForSubrequest(std::move(blobUrl)), options);
|
||||
DeferredResponse<Models::DeleteBlobResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::DeleteBlobResult> BlobServiceBatch::DeleteBlobUrl(
|
||||
const std::string& blobUrl,
|
||||
const DeleteBlobOptions& options)
|
||||
{
|
||||
auto op = std::make_shared<DeleteBlobSubrequest>(
|
||||
GetBlobClientForSubrequest(Core::Url(blobUrl)), options);
|
||||
DeferredResponse<Models::DeleteBlobResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> BlobServiceBatch::SetBlobAccessTier(
|
||||
const std::string& blobContainerName,
|
||||
const std::string& blobName,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options)
|
||||
{
|
||||
auto blobUrl = m_blobServiceClient.m_serviceUrl;
|
||||
blobUrl.AppendPath(_internal::UrlEncodePath(blobContainerName));
|
||||
blobUrl.AppendPath(_internal::UrlEncodePath(blobName));
|
||||
auto op = std::make_shared<SetBlobAccessTierSubrequest>(
|
||||
GetBlobClientForSubrequest(std::move(blobUrl)), std::move(accessTier), options);
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> BlobServiceBatch::SetBlobAccessTierUrl(
|
||||
const std::string& blobUrl,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options)
|
||||
{
|
||||
auto op = std::make_shared<SetBlobAccessTierSubrequest>(
|
||||
GetBlobClientForSubrequest(Core::Url(blobUrl)), std::move(accessTier), options);
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
BlobContainerBatch::BlobContainerBatch(BlobContainerClient blobContainerClient)
|
||||
: m_blobContainerClient(std::move(blobContainerClient))
|
||||
{
|
||||
auto serviceUrl = m_blobContainerClient.Value().m_blobContainerUrl;
|
||||
auto path = serviceUrl.GetPath();
|
||||
if (!path.empty() && path.back() == '/')
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
auto slash_pos = path.rfind('/');
|
||||
path = path.substr(0, slash_pos == std::string::npos ? 0 : (slash_pos + 1));
|
||||
serviceUrl.SetPath(path);
|
||||
m_url = std::move(serviceUrl);
|
||||
}
|
||||
|
||||
BlobClient BlobBatch::GetBlobClientForSubrequest(Core::Url url) const
|
||||
BlobClient BlobContainerBatch::GetBlobClientForSubrequest(Core::Url url) const
|
||||
{
|
||||
if (m_blobServiceClient.HasValue())
|
||||
{
|
||||
auto blobClient = m_blobServiceClient.Value().GetBlobContainerClient("$").GetBlobClient("$");
|
||||
blobClient.m_blobUrl = std::move(url);
|
||||
blobClient.m_pipeline = m_blobServiceClient.Value().m_batchSubrequestPipeline;
|
||||
return blobClient;
|
||||
}
|
||||
else if (m_blobContainerClient.HasValue())
|
||||
{
|
||||
auto blobClient = m_blobContainerClient->GetBlobClient("$");
|
||||
blobClient.m_blobUrl = std::move(url);
|
||||
blobClient.m_pipeline = m_blobContainerClient.Value().m_batchSubrequestPipeline;
|
||||
return blobClient;
|
||||
}
|
||||
AZURE_UNREACHABLE_CODE();
|
||||
auto blobClient = m_blobContainerClient.GetBlobClient("$");
|
||||
blobClient.m_blobUrl = std::move(url);
|
||||
blobClient.m_pipeline = m_blobContainerClient.m_batchSubrequestPipeline;
|
||||
return blobClient;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::DeleteBlobResult> BlobBatch::DeleteBlob(
|
||||
const std::string& blobContainerName,
|
||||
DeferredResponse<Models::DeleteBlobResult> BlobContainerBatch::DeleteBlob(
|
||||
const std::string& blobName,
|
||||
const DeleteBlobOptions& options)
|
||||
{
|
||||
auto blobUrl = m_url;
|
||||
blobUrl.AppendPath(blobContainerName);
|
||||
blobUrl.AppendPath(blobName);
|
||||
auto op = std::make_shared<DeleteBlobSubrequest>();
|
||||
op->Client = GetBlobClientForSubrequest(std::move(blobUrl));
|
||||
op->Options = options;
|
||||
auto blobUrl = m_blobContainerClient.m_blobContainerUrl;
|
||||
blobUrl.AppendPath(_internal::UrlEncodePath(blobName));
|
||||
auto op = std::make_shared<DeleteBlobSubrequest>(
|
||||
GetBlobClientForSubrequest(std::move(blobUrl)), options);
|
||||
DeferredResponse<Models::DeleteBlobResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::DeleteBlobResult> BlobBatch::DeleteBlob(
|
||||
DeferredResponse<Models::DeleteBlobResult> BlobContainerBatch::DeleteBlobUrl(
|
||||
const std::string& blobUrl,
|
||||
const DeleteBlobOptions& options)
|
||||
{
|
||||
auto op = std::make_shared<DeleteBlobSubrequest>();
|
||||
op->Client = GetBlobClientForSubrequest(Core::Url(blobUrl));
|
||||
op->Options = options;
|
||||
auto op = std::make_shared<DeleteBlobSubrequest>(
|
||||
GetBlobClientForSubrequest(Core::Url(blobUrl)), options);
|
||||
DeferredResponse<Models::DeleteBlobResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> BlobBatch::SetBlobAccessTier(
|
||||
const std::string& blobContainerName,
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> BlobContainerBatch::SetBlobAccessTier(
|
||||
const std::string& blobName,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options)
|
||||
{
|
||||
auto blobUrl = m_url;
|
||||
blobUrl.AppendPath(blobContainerName);
|
||||
blobUrl.AppendPath(blobName);
|
||||
auto op = std::make_shared<SetBlobAccessTierSubrequest>();
|
||||
op->Client = GetBlobClientForSubrequest(std::move(blobUrl));
|
||||
op->Tier = accessTier;
|
||||
op->Options = options;
|
||||
auto blobUrl = m_blobContainerClient.m_blobContainerUrl;
|
||||
blobUrl.AppendPath(_internal::UrlEncodePath(blobName));
|
||||
auto op = std::make_shared<SetBlobAccessTierSubrequest>(
|
||||
GetBlobClientForSubrequest(std::move(blobUrl)), std::move(accessTier), options);
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> BlobBatch::SetBlobAccessTier(
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> BlobContainerBatch::SetBlobAccessTierUrl(
|
||||
const std::string& blobUrl,
|
||||
Models::AccessTier accessTier,
|
||||
const SetBlobAccessTierOptions& options)
|
||||
{
|
||||
auto op = std::make_shared<SetBlobAccessTierSubrequest>();
|
||||
op->Client = GetBlobClientForSubrequest(Core::Url(blobUrl));
|
||||
op->Tier = accessTier;
|
||||
op->Options = options;
|
||||
auto op = std::make_shared<SetBlobAccessTierSubrequest>(
|
||||
GetBlobClientForSubrequest(Core::Url(blobUrl)), std::move(accessTier), options);
|
||||
DeferredResponse<Models::SetBlobAccessTierResult> deferredResponse(
|
||||
CreateDeferredResponseFunc(op->Promise));
|
||||
m_subrequests.push_back(std::move(op));
|
||||
return deferredResponse;
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -467,20 +467,15 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::move(blockBlobClient), std::move(response.RawResponse));
|
||||
}
|
||||
|
||||
BlobBatch BlobContainerClient::CreateBatch() { return BlobBatch(*this); }
|
||||
BlobContainerBatch BlobContainerClient::CreateBatch() { return BlobContainerBatch(*this); }
|
||||
|
||||
Response<Models::SubmitBlobBatchResult> BlobContainerClient::SubmitBatch(
|
||||
const BlobBatch& batch,
|
||||
const BlobContainerBatch& batch,
|
||||
const SubmitBlobBatchOptions& options,
|
||||
const Core::Context& context) const
|
||||
{
|
||||
(void)options;
|
||||
|
||||
if (!batch.m_blobContainerClient.HasValue())
|
||||
{
|
||||
throw std::runtime_error("Batch is not container-scoped.");
|
||||
}
|
||||
|
||||
_detail::BlobContainerClient::SubmitBlobContainerBatchOptions protocolLayerOptions;
|
||||
_detail::StringBodyStream bodyStream(std::string{});
|
||||
auto response = _detail::BlobContainerClient::SubmitBatch(
|
||||
@ -488,7 +483,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
m_blobContainerUrl,
|
||||
bodyStream,
|
||||
protocolLayerOptions,
|
||||
context.WithValue(_detail::s_batchKey, &batch));
|
||||
context.WithValue(_detail::s_containerBatchKey, &batch));
|
||||
return Azure::Response<Models::SubmitBlobBatchResult>(
|
||||
Models::SubmitBlobBatchResult(), std::move(response.RawResponse));
|
||||
}
|
||||
|
||||
@ -310,20 +310,15 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::move(blobContainerClient), std::move(response.RawResponse));
|
||||
}
|
||||
|
||||
BlobBatch BlobServiceClient::CreateBatch() { return BlobBatch(*this); }
|
||||
BlobServiceBatch BlobServiceClient::CreateBatch() { return BlobServiceBatch(*this); }
|
||||
|
||||
Response<Models::SubmitBlobBatchResult> BlobServiceClient::SubmitBatch(
|
||||
const BlobBatch& batch,
|
||||
const BlobServiceBatch& batch,
|
||||
const SubmitBlobBatchOptions& options,
|
||||
const Core::Context& context) const
|
||||
{
|
||||
(void)options;
|
||||
|
||||
if (!batch.m_blobServiceClient.HasValue())
|
||||
{
|
||||
throw std::runtime_error("Batch is container-scoped.");
|
||||
}
|
||||
|
||||
_detail::ServiceClient::SubmitServiceBatchOptions protocolLayerOptions;
|
||||
_detail::StringBodyStream bodyStream(std::string{});
|
||||
auto response = _detail::ServiceClient::SubmitBatch(
|
||||
@ -331,7 +326,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
m_serviceUrl,
|
||||
bodyStream,
|
||||
protocolLayerOptions,
|
||||
context.WithValue(_detail::s_batchKey, &batch));
|
||||
context.WithValue(_detail::s_serviceBatchKey, &batch));
|
||||
return Azure::Response<Models::SubmitBlobBatchResult>(
|
||||
Models::SubmitBlobBatchResult(), std::move(response.RawResponse));
|
||||
}
|
||||
|
||||
@ -56,11 +56,11 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
blob3Client.CreateSnapshot();
|
||||
|
||||
auto batch = serviceClient.CreateBatch();
|
||||
auto delete1Response = batch.DeleteBlob(blob1Client.GetUrl());
|
||||
auto delete1Response = batch.DeleteBlobUrl(blob1Client.GetUrl());
|
||||
auto delete2Response = batch.DeleteBlob(containerName1, blob2Name);
|
||||
Blobs::DeleteBlobOptions deleteOptions;
|
||||
deleteOptions.DeleteSnapshots = Blobs::Models::DeleteSnapshotsOption::OnlySnapshots;
|
||||
auto delete3Response = batch.DeleteBlob(blob3Client.GetUrl(), deleteOptions);
|
||||
auto delete3Response = batch.DeleteBlobUrl(blob3Client.GetUrl(), deleteOptions);
|
||||
auto submitBatchResponse = serviceClient.SubmitBatch(batch);
|
||||
|
||||
EXPECT_TRUE(delete1Response.GetResponse().Value.Deleted);
|
||||
@ -104,10 +104,8 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
blob2Client.UploadFrom(nullptr, 0);
|
||||
|
||||
auto batch = containerClient.CreateBatch();
|
||||
auto setTier1Response
|
||||
= batch.SetBlobAccessTier(containerName, blob1Name, Blobs::Models::AccessTier::Cool);
|
||||
auto setTier2Response
|
||||
= batch.SetBlobAccessTier(blob2Client.GetUrl(), Blobs::Models::AccessTier::Archive);
|
||||
auto setTier1Response = batch.SetBlobAccessTier(blob1Name, Blobs::Models::AccessTier::Cool);
|
||||
auto setTier2Response = batch.SetBlobAccessTier(blob2Name, Blobs::Models::AccessTier::Archive);
|
||||
auto submitBatchResponse = containerClient.SubmitBatch(batch);
|
||||
|
||||
EXPECT_NO_THROW(setTier1Response.GetResponse());
|
||||
@ -141,7 +139,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
blobClient.Create();
|
||||
|
||||
auto batch = containerClient.CreateBatch();
|
||||
auto delete1Response = batch.DeleteBlob(blobClient.GetUrl());
|
||||
auto delete1Response = batch.DeleteBlobUrl(blobClient.GetUrl());
|
||||
auto submitBatchResponse = containerClient.SubmitBatch(batch);
|
||||
|
||||
EXPECT_TRUE(delete1Response.GetResponse().Value.Deleted);
|
||||
@ -185,9 +183,8 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
// Partial failure
|
||||
{
|
||||
auto r1 = batch.SetBlobAccessTier(blobClient.GetUrl(), Blobs::Models::AccessTier::Hot);
|
||||
auto r2 = batch.SetBlobAccessTier(
|
||||
containerName, "BlobNameNotExists", Blobs::Models::AccessTier::Hot);
|
||||
auto r1 = batch.SetBlobAccessTierUrl(blobClient.GetUrl(), Blobs::Models::AccessTier::Hot);
|
||||
auto r2 = batch.SetBlobAccessTier("BlobNameNotExists", Blobs::Models::AccessTier::Hot);
|
||||
EXPECT_NO_THROW(containerClient.SubmitBatch(batch));
|
||||
EXPECT_NO_THROW(r1.GetResponse());
|
||||
EXPECT_THROW(r2.GetResponse(), StorageException);
|
||||
@ -195,8 +192,8 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
// Mixed operations
|
||||
auto batch2 = containerClient.CreateBatch();
|
||||
batch2.SetBlobAccessTier(blobClient.GetUrl(), Blobs::Models::AccessTier::Cool);
|
||||
batch2.DeleteBlob(blobClient.GetUrl());
|
||||
batch2.SetBlobAccessTierUrl(blobClient.GetUrl(), Blobs::Models::AccessTier::Cool);
|
||||
batch2.DeleteBlobUrl(blobClient.GetUrl());
|
||||
|
||||
try
|
||||
{
|
||||
@ -239,7 +236,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
auto containerSasClient = Blobs::BlobContainerClient(
|
||||
serviceClient.GetBlobContainerClient(containerName).GetUrl() + containerExpiredSasToken);
|
||||
auto batch3 = containerSasClient.CreateBatch();
|
||||
batch3.DeleteBlob(blobClient.GetUrl() + containerSasToken);
|
||||
batch3.DeleteBlobUrl(blobClient.GetUrl() + containerSasToken);
|
||||
try
|
||||
{
|
||||
containerSasClient.SubmitBatch(batch3);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user