[Storage Blob Service] Container Lease and Blob Lease (#402)
* container lease * blob lease
This commit is contained in:
parent
46c0af9a70
commit
355184ef4f
@ -38,6 +38,7 @@ set(AZURE_STORAGE_COMMON_SOURCE
|
||||
src/common/file_io.cpp
|
||||
src/common/reliable_stream.cpp
|
||||
src/common/shared_key_policy.cpp
|
||||
src/common/storage_common.cpp
|
||||
src/common/storage_credential.cpp
|
||||
src/common/storage_error.cpp
|
||||
src/common/storage_uri_builder.cpp
|
||||
|
||||
@ -284,6 +284,76 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Response<UndeleteBlobInfo> Undelete(
|
||||
const UndeleteBlobOptions& options = UndeleteBlobOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Acquires a lease on the blob.
|
||||
*
|
||||
* @param proposedLeaseId
|
||||
* Proposed lease ID, in a GUID string format.
|
||||
* @param duration Specifies the duration of
|
||||
* the lease, in seconds, or Azure::Storage::c_InfiniteLeaseDuration for a lease that never
|
||||
* expires. A non-infinite lease can be between 15 and 60 seconds. A lease duration cannot be
|
||||
* changed using renew or change.
|
||||
* @param options Optional parameters to execute this
|
||||
* function.
|
||||
* @return A BlobLease describing the lease.
|
||||
*/
|
||||
Azure::Core::Response<BlobLease> AcquireLease(
|
||||
const std::string& proposedLeaseId,
|
||||
int32_t duration,
|
||||
const AcquireBlobLeaseOptions& options = AcquireBlobLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Renews the blob's previously-acquired lease.
|
||||
*
|
||||
* @param
|
||||
* leaseId ID of the previously-acquired lease.
|
||||
* @param options Optional parameters to
|
||||
* execute this function.
|
||||
* @return A BlobLease describing the lease.
|
||||
*/
|
||||
Azure::Core::Response<BlobLease> RenewLease(
|
||||
const std::string& leaseId,
|
||||
const RenewBlobLeaseOptions& options = RenewBlobLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Releases the blob's previously-acquired lease.
|
||||
*
|
||||
* @param
|
||||
* leaseId ID of the previously-acquired lease.
|
||||
* @param options Optional parameters to
|
||||
* execute this function.
|
||||
* @return A BlobInfo describing the updated container.
|
||||
*/
|
||||
Azure::Core::Response<BlobInfo> ReleaseLease(
|
||||
const std::string& leaseId,
|
||||
const ReleaseBlobLeaseOptions& options = ReleaseBlobLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Changes the lease of an active lease.
|
||||
*
|
||||
* @param leaseId ID of the
|
||||
* previously-acquired lease.
|
||||
* @param proposedLeaseId Proposed lease ID, in a GUID string
|
||||
* format.
|
||||
* @param options Optional parameters to execute this function.
|
||||
* @return A
|
||||
* BlobLease describing the lease.
|
||||
*/
|
||||
Azure::Core::Response<BlobLease> ChangeLease(
|
||||
const std::string& leaseId,
|
||||
const std::string& proposedLeaseId,
|
||||
const ChangeBlobLeaseOptions& options = ChangeBlobLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Breaks the previously-acquired lease.
|
||||
*
|
||||
* @param options Optional
|
||||
* parameters to execute this function.
|
||||
* @return A BrokenLease describing the broken lease.
|
||||
*/
|
||||
Azure::Core::Response<BrokenLease> BreakLease(
|
||||
const BreakBlobLeaseOptions& options = BreakBlobLeaseOptions()) const;
|
||||
|
||||
protected:
|
||||
UriBuilder m_blobUrl;
|
||||
std::shared_ptr<Azure::Core::Http::HttpPipeline> m_pipeline;
|
||||
|
||||
@ -206,7 +206,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
/**
|
||||
* @brief Gets the permissions for this container. The permissions indicate whether
|
||||
* container data may be accessed publicly.
|
||||
*
|
||||
*
|
||||
* @param options Optional parameters to
|
||||
* execute this function.
|
||||
* @return A BlobContainerAccessPolicy describing the container's
|
||||
@ -219,7 +219,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
/**
|
||||
* @brief Sets the permissions for the specified container. The permissions indicate
|
||||
* whether blob container data may be accessed publicly.
|
||||
*
|
||||
*
|
||||
* @param options Optional
|
||||
* parameters to execute this function.
|
||||
* @return A BlobContainerInfo describing the
|
||||
@ -229,6 +229,76 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
const SetBlobContainerAccessPolicyOptions& options
|
||||
= SetBlobContainerAccessPolicyOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Acquires a lease on the container.
|
||||
*
|
||||
* @param proposedLeaseId
|
||||
* Proposed lease ID, in a GUID string format.
|
||||
* @param duration Specifies the duration of
|
||||
* the lease, in seconds, or Azure::Storage::c_InfiniteLeaseDuration for a lease that never
|
||||
* expires. A non-infinite lease can be between 15 and 60 seconds. A lease duration cannot be
|
||||
* changed using renew or change.
|
||||
* @param options Optional parameters to execute this
|
||||
* function.
|
||||
* @return A BlobLease describing the lease.
|
||||
*/
|
||||
Azure::Core::Response<BlobLease> AcquireLease(
|
||||
const std::string& proposedLeaseId,
|
||||
int32_t duration,
|
||||
const AcquireBlobContainerLeaseOptions& options = AcquireBlobContainerLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Renews the container's previously-acquired lease.
|
||||
*
|
||||
* @param
|
||||
* leaseId ID of the previously-acquired lease.
|
||||
* @param options Optional parameters to
|
||||
* execute this function.
|
||||
* @return A BlobLease describing the lease.
|
||||
*/
|
||||
Azure::Core::Response<BlobLease> RenewLease(
|
||||
const std::string& leaseId,
|
||||
const RenewBlobContainerLeaseOptions& options = RenewBlobContainerLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Releases the container's previously-acquired lease.
|
||||
*
|
||||
* @param
|
||||
* leaseId ID of the previously-acquired lease.
|
||||
* @param options Optional parameters to
|
||||
* execute this function.
|
||||
* @return A BlobContainerInfo describing the updated container.
|
||||
*/
|
||||
Azure::Core::Response<BlobContainerInfo> ReleaseLease(
|
||||
const std::string& leaseId,
|
||||
const ReleaseBlobContainerLeaseOptions& options = ReleaseBlobContainerLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Changes the lease of an active lease.
|
||||
*
|
||||
* @param leaseId ID of the
|
||||
* previously-acquired lease.
|
||||
* @param proposedLeaseId Proposed lease ID, in a GUID string
|
||||
* format.
|
||||
* @param options Optional parameters to execute this function.
|
||||
* @return A
|
||||
* BlobLease describing the lease.
|
||||
*/
|
||||
Azure::Core::Response<BlobLease> ChangeLease(
|
||||
const std::string& leaseId,
|
||||
const std::string& proposedLeaseId,
|
||||
const ChangeBlobContainerLeaseOptions& options = ChangeBlobContainerLeaseOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Breaks the previously-acquired lease.
|
||||
*
|
||||
* @param options Optional
|
||||
* parameters to execute this function.
|
||||
* @return A BrokenLease describing the broken lease.
|
||||
*/
|
||||
Azure::Core::Response<BrokenLease> BreakLease(
|
||||
const BreakBlobContainerLeaseOptions& options = BreakBlobContainerLeaseOptions()) const;
|
||||
|
||||
private:
|
||||
UriBuilder m_containerUrl;
|
||||
std::shared_ptr<Azure::Core::Http::HttpPipeline> m_pipeline;
|
||||
|
||||
@ -350,6 +350,70 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
ContainerAccessConditions AccessConditions;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobContainerClient::AcquireLease.
|
||||
*/
|
||||
struct AcquireBlobContainerLeaseOptions : public LastModifiedTimeAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobContainerClient::RenewLease.
|
||||
*/
|
||||
struct RenewBlobContainerLeaseOptions : public LastModifiedTimeAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobContainerClient::ChangeLease.
|
||||
*/
|
||||
struct ChangeBlobContainerLeaseOptions : public LastModifiedTimeAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobContainerClient::ReleaseLease.
|
||||
*/
|
||||
struct ReleaseBlobContainerLeaseOptions : public LastModifiedTimeAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobContainerClient::BreakLease.
|
||||
*/
|
||||
struct BreakBlobContainerLeaseOptions : public LastModifiedTimeAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
|
||||
/**
|
||||
* @brief Proposed duration the lease should continue before it is broken, in seconds,
|
||||
* between 0 and 60. This break period is only used if it is shorter than the time remaining on
|
||||
* the lease. If longer, the time remaining on the lease is used. A new lease will not be
|
||||
* available before the break period has expired, but the lease may be held for longer than the
|
||||
* break period.
|
||||
*/
|
||||
Azure::Core::Nullable<int32_t> breakPeriod;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Blob client options used to initalize BlobClient.
|
||||
*/
|
||||
@ -642,6 +706,75 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobClient::AcquireLease.
|
||||
*/
|
||||
struct AcquireBlobLeaseOptions : public LastModifiedTimeAccessConditions,
|
||||
public ETagAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobClient::RenewLease.
|
||||
*/
|
||||
struct RenewBlobLeaseOptions : public LastModifiedTimeAccessConditions,
|
||||
public ETagAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobClient::ChangeLease.
|
||||
*/
|
||||
struct ChangeBlobLeaseOptions : public LastModifiedTimeAccessConditions,
|
||||
public ETagAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobClient::ReleaseLease.
|
||||
*/
|
||||
struct ReleaseBlobLeaseOptions : public LastModifiedTimeAccessConditions,
|
||||
public ETagAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobClient::BreakLease.
|
||||
*/
|
||||
struct BreakBlobLeaseOptions : public LastModifiedTimeAccessConditions,
|
||||
public ETagAccessConditions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
|
||||
/**
|
||||
* @brief Proposed duration the lease should continue before it is broken, in seconds,
|
||||
* between 0 and 60. This break period is only used if it is shorter than the time remaining on
|
||||
* the lease. If longer, the time remaining on the lease is used. A new lease will not be
|
||||
* available before the break period has expired, but the lease may be held for longer than the
|
||||
* break period.
|
||||
*/
|
||||
Azure::Core::Nullable<int32_t> breakPeriod;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlockBlobClient::Upload.
|
||||
*/
|
||||
|
||||
@ -382,6 +382,13 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Nullable<int64_t> SequenceNumber;
|
||||
}; // struct BlobInfo
|
||||
|
||||
struct BlobLease
|
||||
{
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
std::string LeaseId;
|
||||
}; // struct BlobLease
|
||||
|
||||
enum class BlobLeaseState
|
||||
{
|
||||
Available,
|
||||
@ -637,6 +644,13 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
throw std::runtime_error("cannot convert " + block_type + " to BlockType");
|
||||
}
|
||||
|
||||
struct BrokenLease
|
||||
{
|
||||
std::string ETag;
|
||||
std::string LastModified;
|
||||
int32_t LeaseTime = 0;
|
||||
}; // struct BrokenLease
|
||||
|
||||
enum class CopyStatus
|
||||
{
|
||||
Unknown,
|
||||
@ -3223,6 +3237,267 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct AcquireLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
int32_t LeaseDuration = -1;
|
||||
Azure::Core::Nullable<std::string> ProposedLeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
}; // struct AcquireLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobLease> AcquireLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const AcquireLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("restype", "container");
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "acquire");
|
||||
request.AddHeader("x-ms-lease-duration", std::to_string(options.LeaseDuration));
|
||||
if (options.ProposedLeaseId.HasValue())
|
||||
{
|
||||
request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId.GetValue());
|
||||
}
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 201))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id");
|
||||
return Azure::Core::Response<BlobLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct RenewLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
std::string LeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
}; // struct RenewLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobLease> RenewLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const RenewLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("restype", "container");
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "renew");
|
||||
request.AddHeader("x-ms-lease-id", options.LeaseId);
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id");
|
||||
return Azure::Core::Response<BlobLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct ChangeLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
std::string LeaseId;
|
||||
std::string ProposedLeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
}; // struct ChangeLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobLease> ChangeLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const ChangeLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("restype", "container");
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "change");
|
||||
request.AddHeader("x-ms-lease-id", options.LeaseId);
|
||||
request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId);
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id");
|
||||
return Azure::Core::Response<BlobLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct ReleaseLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
std::string LeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
}; // struct ReleaseLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobContainerInfo> ReleaseLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const ReleaseLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("restype", "container");
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "release");
|
||||
request.AddHeader("x-ms-lease-id", options.LeaseId);
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobContainerInfo response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
return Azure::Core::Response<BlobContainerInfo>(
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct BreakLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
Azure::Core::Nullable<int32_t> BreakPeriod;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
}; // struct BreakLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BrokenLease> BreakLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const BreakLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("restype", "container");
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "break");
|
||||
if (options.BreakPeriod.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
"x-ms-lease-break-period", std::to_string(options.BreakPeriod.GetValue()));
|
||||
}
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BrokenLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 202))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseTime = std::stoi(httpResponse.GetHeaders().at("x-ms-lease-time"));
|
||||
return Azure::Core::Response<BrokenLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
private:
|
||||
static BlobContainerAccessPolicy BlobContainerAccessPolicyFromXml(XmlReader& reader)
|
||||
{
|
||||
@ -4993,6 +5268,317 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct AcquireLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
int32_t LeaseDuration = -1;
|
||||
Azure::Core::Nullable<std::string> ProposedLeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfMatch;
|
||||
Azure::Core::Nullable<std::string> IfNoneMatch;
|
||||
}; // struct AcquireLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobLease> AcquireLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const AcquireLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "acquire");
|
||||
request.AddHeader("x-ms-lease-duration", std::to_string(options.LeaseDuration));
|
||||
if (options.ProposedLeaseId.HasValue())
|
||||
{
|
||||
request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId.GetValue());
|
||||
}
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Match", options.IfMatch.GetValue());
|
||||
}
|
||||
if (options.IfNoneMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 201))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id");
|
||||
return Azure::Core::Response<BlobLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct RenewLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
std::string LeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfMatch;
|
||||
Azure::Core::Nullable<std::string> IfNoneMatch;
|
||||
}; // struct RenewLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobLease> RenewLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const RenewLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "renew");
|
||||
request.AddHeader("x-ms-lease-id", options.LeaseId);
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Match", options.IfMatch.GetValue());
|
||||
}
|
||||
if (options.IfNoneMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id");
|
||||
return Azure::Core::Response<BlobLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct ChangeLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
std::string LeaseId;
|
||||
std::string ProposedLeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfMatch;
|
||||
Azure::Core::Nullable<std::string> IfNoneMatch;
|
||||
}; // struct ChangeLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobLease> ChangeLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const ChangeLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "change");
|
||||
request.AddHeader("x-ms-lease-id", options.LeaseId);
|
||||
request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId);
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Match", options.IfMatch.GetValue());
|
||||
}
|
||||
if (options.IfNoneMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseId = httpResponse.GetHeaders().at("x-ms-lease-id");
|
||||
return Azure::Core::Response<BlobLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct ReleaseLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
std::string LeaseId;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfMatch;
|
||||
Azure::Core::Nullable<std::string> IfNoneMatch;
|
||||
}; // struct ReleaseLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BlobInfo> ReleaseLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const ReleaseLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "release");
|
||||
request.AddHeader("x-ms-lease-id", options.LeaseId);
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Match", options.IfMatch.GetValue());
|
||||
}
|
||||
if (options.IfNoneMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobInfo response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
auto response_sequence_number_iterator
|
||||
= httpResponse.GetHeaders().find("x-ms-blob-sequence-number");
|
||||
if (response_sequence_number_iterator != httpResponse.GetHeaders().end())
|
||||
{
|
||||
response.SequenceNumber = std::stoll(response_sequence_number_iterator->second);
|
||||
}
|
||||
return Azure::Core::Response<BlobInfo>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct BreakLeaseOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
Azure::Core::Nullable<int32_t> BreakPeriod;
|
||||
Azure::Core::Nullable<std::string> IfModifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfUnmodifiedSince;
|
||||
Azure::Core::Nullable<std::string> IfMatch;
|
||||
Azure::Core::Nullable<std::string> IfNoneMatch;
|
||||
}; // struct BreakLeaseOptions
|
||||
|
||||
static Azure::Core::Response<BrokenLease> BreakLease(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const BreakLeaseOptions& options)
|
||||
{
|
||||
unused(options);
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url);
|
||||
request.AddHeader("Content-Length", "0");
|
||||
request.AddHeader("x-ms-version", c_ApiVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
request.AddQueryParameter("comp", "lease");
|
||||
request.AddHeader("x-ms-lease-action", "break");
|
||||
if (options.BreakPeriod.HasValue())
|
||||
{
|
||||
request.AddHeader(
|
||||
"x-ms-lease-break-period", std::to_string(options.BreakPeriod.GetValue()));
|
||||
}
|
||||
if (options.IfModifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Modified-Since", options.IfModifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfUnmodifiedSince.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Unmodified-Since", options.IfUnmodifiedSince.GetValue());
|
||||
}
|
||||
if (options.IfMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-Match", options.IfMatch.GetValue());
|
||||
}
|
||||
if (options.IfNoneMatch.HasValue())
|
||||
{
|
||||
request.AddHeader("If-None-Match", options.IfNoneMatch.GetValue());
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BrokenLease response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 202))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
response.LeaseTime = std::stoi(httpResponse.GetHeaders().at("x-ms-lease-time"));
|
||||
return Azure::Core::Response<BrokenLease>(std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
private:
|
||||
}; // class Blob
|
||||
|
||||
|
||||
@ -3,8 +3,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Storage {
|
||||
|
||||
template <class... T> void unused(T&&...) {}
|
||||
|
||||
constexpr int32_t c_InfiniteLeaseDuration = -1;
|
||||
|
||||
std::string CreateUniqueLeaseId();
|
||||
|
||||
}} // namespace Azure::Storage
|
||||
|
||||
@ -541,4 +541,77 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
options.Context, *m_pipeline, m_blobUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobLease> BlobClient::AcquireLease(
|
||||
const std::string& proposedLeaseId,
|
||||
int32_t duration,
|
||||
const AcquireBlobLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Blob::AcquireLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.ProposedLeaseId = proposedLeaseId;
|
||||
protocolLayerOptions.LeaseDuration = duration;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
protocolLayerOptions.IfMatch = options.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
|
||||
return BlobRestClient::Blob::AcquireLease(
|
||||
options.Context, *m_pipeline, m_blobUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobLease> BlobClient::RenewLease(
|
||||
const std::string& leaseId,
|
||||
const RenewBlobLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Blob::RenewLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseId = leaseId;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
protocolLayerOptions.IfMatch = options.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
|
||||
return BlobRestClient::Blob::RenewLease(
|
||||
options.Context, *m_pipeline, m_blobUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobInfo> BlobClient::ReleaseLease(
|
||||
const std::string& leaseId,
|
||||
const ReleaseBlobLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Blob::ReleaseLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseId = leaseId;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
protocolLayerOptions.IfMatch = options.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
|
||||
return BlobRestClient::Blob::ReleaseLease(
|
||||
options.Context, *m_pipeline, m_blobUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobLease> BlobClient::ChangeLease(
|
||||
const std::string& leaseId,
|
||||
const std::string& proposedLeaseId,
|
||||
const ChangeBlobLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Blob::ChangeLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseId = leaseId;
|
||||
protocolLayerOptions.ProposedLeaseId = proposedLeaseId;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
protocolLayerOptions.IfMatch = options.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
|
||||
return BlobRestClient::Blob::ChangeLease(
|
||||
options.Context, *m_pipeline, m_blobUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BrokenLease> BlobClient::BreakLease(
|
||||
const BreakBlobLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Blob::BreakLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.BreakPeriod = options.breakPeriod;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
protocolLayerOptions.IfMatch = options.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
|
||||
return BlobRestClient::Blob::BreakLease(
|
||||
options.Context, *m_pipeline, m_blobUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -226,4 +226,67 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
options.Context, *m_pipeline, m_containerUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobLease> BlobContainerClient::AcquireLease(
|
||||
const std::string& proposedLeaseId,
|
||||
int32_t duration,
|
||||
const AcquireBlobContainerLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Container::AcquireLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.ProposedLeaseId = proposedLeaseId;
|
||||
protocolLayerOptions.LeaseDuration = duration;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
return BlobRestClient::Container::AcquireLease(
|
||||
options.Context, *m_pipeline, m_containerUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobLease> BlobContainerClient::RenewLease(
|
||||
const std::string& leaseId,
|
||||
const RenewBlobContainerLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Container::RenewLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseId = leaseId;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
return BlobRestClient::Container::RenewLease(
|
||||
options.Context, *m_pipeline, m_containerUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobContainerInfo> BlobContainerClient::ReleaseLease(
|
||||
const std::string& leaseId,
|
||||
const ReleaseBlobContainerLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Container::ReleaseLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseId = leaseId;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
return BlobRestClient::Container::ReleaseLease(
|
||||
options.Context, *m_pipeline, m_containerUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobLease> BlobContainerClient::ChangeLease(
|
||||
const std::string& leaseId,
|
||||
const std::string& proposedLeaseId,
|
||||
const ChangeBlobContainerLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Container::ChangeLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseId = leaseId;
|
||||
protocolLayerOptions.ProposedLeaseId = proposedLeaseId;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
return BlobRestClient::Container::ChangeLease(
|
||||
options.Context, *m_pipeline, m_containerUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BrokenLease> BlobContainerClient::BreakLease(
|
||||
const BreakBlobContainerLeaseOptions& options) const
|
||||
{
|
||||
BlobRestClient::Container::BreakLeaseOptions protocolLayerOptions;
|
||||
protocolLayerOptions.BreakPeriod = options.breakPeriod;
|
||||
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
|
||||
return BlobRestClient::Container::BreakLease(
|
||||
options.Context, *m_pipeline, m_containerUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
35
sdk/storage/src/common/storage_common.cpp
Normal file
35
sdk/storage/src/common/storage_common.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "common/storage_common.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace Azure { namespace Storage {
|
||||
|
||||
std::string CreateUniqueLeaseId()
|
||||
{
|
||||
// TODO: return UUID provided by Azure Core once they provide one.
|
||||
|
||||
static thread_local std::mt19937_64 random_generator(std::random_device{}());
|
||||
|
||||
auto getRandomChar = []() {
|
||||
const char charset[] = "0123456789abcdef";
|
||||
std::uniform_int_distribution<size_t> distribution(0, sizeof(charset) - 2);
|
||||
return charset[distribution(random_generator)];
|
||||
};
|
||||
|
||||
std::string result;
|
||||
result.reserve(37);
|
||||
for (int i : {8, 4, 4, 4, 12})
|
||||
{
|
||||
for (int j = 0; j < i; ++j)
|
||||
result += getRandomChar();
|
||||
result += '-';
|
||||
}
|
||||
result.pop_back();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}} // namespace Azure::Storage
|
||||
@ -272,4 +272,57 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
container_client.Delete();
|
||||
}
|
||||
|
||||
TEST_F(BlobContainerClientTest, Lease)
|
||||
{
|
||||
std::string leaseId1 = CreateUniqueLeaseId();
|
||||
int32_t leaseDuration = 20;
|
||||
auto lease = *m_blobContainerClient->AcquireLease(leaseId1, leaseDuration);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId1);
|
||||
lease = *m_blobContainerClient->AcquireLease(leaseId1, leaseDuration);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId1);
|
||||
|
||||
auto properties = *m_blobContainerClient->GetProperties();
|
||||
EXPECT_EQ(properties.LeaseState, Blobs::BlobLeaseState::Leased);
|
||||
EXPECT_EQ(properties.LeaseStatus, Blobs::BlobLeaseStatus::Locked);
|
||||
EXPECT_FALSE(properties.LeaseDuration.GetValue().empty());
|
||||
|
||||
lease = *m_blobContainerClient->RenewLease(leaseId1);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId1);
|
||||
|
||||
std::string leaseId2 = CreateUniqueLeaseId();
|
||||
EXPECT_NE(leaseId1, leaseId2);
|
||||
lease = *m_blobContainerClient->ChangeLease(leaseId1, leaseId2);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId2);
|
||||
|
||||
auto containerInfo = *m_blobContainerClient->ReleaseLease(leaseId2);
|
||||
EXPECT_FALSE(containerInfo.ETag.empty());
|
||||
EXPECT_FALSE(containerInfo.LastModified.empty());
|
||||
|
||||
lease = *m_blobContainerClient->AcquireLease(CreateUniqueLeaseId(), c_InfiniteLeaseDuration);
|
||||
properties = *m_blobContainerClient->GetProperties();
|
||||
EXPECT_FALSE(properties.LeaseDuration.GetValue().empty());
|
||||
auto brokenLease = *m_blobContainerClient->BreakLease();
|
||||
EXPECT_FALSE(brokenLease.ETag.empty());
|
||||
EXPECT_FALSE(brokenLease.LastModified.empty());
|
||||
EXPECT_EQ(brokenLease.LeaseTime, 0);
|
||||
|
||||
lease = *m_blobContainerClient->AcquireLease(CreateUniqueLeaseId(), leaseDuration);
|
||||
brokenLease = *m_blobContainerClient->BreakLease();
|
||||
EXPECT_FALSE(brokenLease.ETag.empty());
|
||||
EXPECT_FALSE(brokenLease.LastModified.empty());
|
||||
EXPECT_NE(brokenLease.LeaseTime, 0);
|
||||
|
||||
Blobs::BreakBlobContainerLeaseOptions options;
|
||||
options.breakPeriod = 0;
|
||||
m_blobContainerClient->BreakLease(options);
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Test
|
||||
|
||||
@ -138,4 +138,57 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
pageBlobClient.StartCopyIncremental(sourceUri.ToString());
|
||||
}
|
||||
|
||||
TEST_F(PageBlobClientTest, Lease)
|
||||
{
|
||||
std::string leaseId1 = CreateUniqueLeaseId();
|
||||
int32_t leaseDuration = 20;
|
||||
auto lease = *m_pageBlobClient->AcquireLease(leaseId1, leaseDuration);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId1);
|
||||
lease = *m_pageBlobClient->AcquireLease(leaseId1, leaseDuration);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId1);
|
||||
|
||||
auto properties = *m_pageBlobClient->GetProperties();
|
||||
EXPECT_EQ(properties.LeaseState.GetValue(), Blobs::BlobLeaseState::Leased);
|
||||
EXPECT_EQ(properties.LeaseStatus.GetValue(), Blobs::BlobLeaseStatus::Locked);
|
||||
EXPECT_FALSE(properties.LeaseDuration.GetValue().empty());
|
||||
|
||||
lease = *m_pageBlobClient->RenewLease(leaseId1);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId1);
|
||||
|
||||
std::string leaseId2 = CreateUniqueLeaseId();
|
||||
EXPECT_NE(leaseId1, leaseId2);
|
||||
lease = *m_pageBlobClient->ChangeLease(leaseId1, leaseId2);
|
||||
EXPECT_FALSE(lease.ETag.empty());
|
||||
EXPECT_FALSE(lease.LastModified.empty());
|
||||
EXPECT_EQ(lease.LeaseId, leaseId2);
|
||||
|
||||
auto blobInfo = *m_pageBlobClient->ReleaseLease(leaseId2);
|
||||
EXPECT_FALSE(blobInfo.ETag.empty());
|
||||
EXPECT_FALSE(blobInfo.LastModified.empty());
|
||||
|
||||
lease = *m_pageBlobClient->AcquireLease(CreateUniqueLeaseId(), c_InfiniteLeaseDuration);
|
||||
properties = *m_pageBlobClient->GetProperties();
|
||||
EXPECT_FALSE(properties.LeaseDuration.GetValue().empty());
|
||||
auto brokenLease = *m_pageBlobClient->BreakLease();
|
||||
EXPECT_FALSE(brokenLease.ETag.empty());
|
||||
EXPECT_FALSE(brokenLease.LastModified.empty());
|
||||
EXPECT_EQ(brokenLease.LeaseTime, 0);
|
||||
|
||||
lease = *m_pageBlobClient->AcquireLease(CreateUniqueLeaseId(), leaseDuration);
|
||||
brokenLease = *m_pageBlobClient->BreakLease();
|
||||
EXPECT_FALSE(brokenLease.ETag.empty());
|
||||
EXPECT_FALSE(brokenLease.LastModified.empty());
|
||||
EXPECT_NE(brokenLease.LeaseTime, 0);
|
||||
|
||||
Blobs::BreakBlobLeaseOptions options;
|
||||
options.breakPeriod = 0;
|
||||
m_pageBlobClient->BreakLease(options);
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Test
|
||||
|
||||
Loading…
Reference in New Issue
Block a user