< Summary

Class:Azure.Storage.Blobs.Specialized.BlobLeaseClient
Assembly:Azure.Storage.Blobs
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\BlobLeaseClient.cs
Covered lines:277
Uncovered lines:16
Coverable lines:293
Total lines:1206
Line coverage:94.5% (277 of 293)
Covered branches:147
Total branches:162
Branch coverage:90.7% (147 of 162)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_BlobClient()-100%100%
get_BlobContainerClient()-100%100%
get_Uri()-100%83.33%
get_LeaseId()-100%100%
get_Pipeline()-100%100%
get_Version()-100%100%
get_ClientDiagnostics()-100%100%
.cctor()-100%100%
.ctor()-100%100%
.ctor(...)-100%75%
.ctor(...)-100%75%
CreateUniqueLeaseId()-100%100%
EnsureClient()-66.67%75%
Acquire(...)-100%100%
AcquireAsync()-100%100%
AcquireInternal()-93.02%89.29%
Renew(...)-100%100%
RenewAsync()-100%100%
RenewInternal()-92.31%92.31%
Release(...)-100%100%
ReleaseAsync()-100%100%
ReleaseInternal()-93.18%92.31%
Change(...)-100%100%
ChangeAsync()-100%100%
ChangeInternal()-92.86%92.31%
Break(...)-100%100%
BreakAsync()-100%100%
BreakInternal()-93.02%92.86%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\BlobLeaseClient.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.ComponentModel;
 6using System.Threading;
 7using System.Threading.Tasks;
 8using Azure.Core.Pipeline;
 9using Azure.Storage.Blobs.Models;
 10
 11#pragma warning disable SA1402  // File may only contain a single type
 12
 13namespace Azure.Storage.Blobs.Specialized
 14{
 15    /// <summary>
 16    /// The <see cref="BlobLeaseClient"/> allows you to manipulate Azure
 17    /// Storage leases on containers and blobs.
 18    /// </summary>
 19    public class BlobLeaseClient
 20    {
 21        /// <summary>
 22        /// The <see cref="BlobClient"/> to manage leases for.
 23        /// </summary>
 24        private readonly BlobBaseClient _blob;
 25
 26        /// <summary>
 27        /// Gets the <see cref="BlobClient"/> to manage leases for.
 28        /// </summary>
 1372829        protected virtual BlobBaseClient BlobClient => _blob;
 30
 31        /// <summary>
 32        /// The <see cref="BlobContainerClient"/> to manage leases for.
 33        /// </summary>
 34        private readonly BlobContainerClient _container;
 35
 36        /// <summary>
 37        /// Gets the <see cref="BlobContainerClient"/> to manage leases for.
 38        /// </summary>
 302439        protected virtual BlobContainerClient BlobContainerClient => _container;
 40
 41        /// <summary>
 42        /// Gets the URI of the object being leased.
 43        /// </summary>
 198844        public Uri Uri => BlobClient?.Uri ?? BlobContainerClient?.Uri;
 45
 46        /// <summary>
 47        /// Gets the Lease ID for this lease.
 48        /// </summary>
 318049        public virtual string LeaseId { get; private set; }
 50
 51        /// <summary>
 52        /// The <see cref="HttpPipeline"/> transport pipeline used to send
 53        /// every request.
 54        /// </summary>
 397655        private HttpPipeline Pipeline => BlobClient?.Pipeline ?? BlobContainerClient.Pipeline;
 56
 57        /// <summary>
 58        /// The version of the service to use when sending requests.
 59        /// </summary>
 198860        internal virtual BlobClientOptions.ServiceVersion Version => BlobClient?.Version ?? BlobContainerClient.Version;
 61
 62        /// <summary>
 63        /// The <see cref="ClientDiagnostics"/> instance used to create diagnostic scopes
 64        /// every request.
 65        /// </summary>
 198866        internal virtual ClientDiagnostics ClientDiagnostics => BlobClient?.ClientDiagnostics ?? BlobContainerClient.Cli
 67
 68        /// <summary>
 69        /// The <see cref="TimeSpan"/> representing an infinite lease duration.
 70        /// </summary>
 271        public static readonly TimeSpan InfiniteLeaseDuration = TimeSpan.FromSeconds(Constants.Blob.Lease.InfiniteLeaseD
 72
 73        /// <summary>
 74        /// Initializes a new instance of the <see cref="BlobLeaseClient"/> class
 75        /// for mocking.
 76        /// </summary>
 63277        protected BlobLeaseClient()
 78        {
 63279            _blob = null;
 63280            _container = null;
 63281        }
 82
 83        /// <summary>
 84        /// Initializes a new instance of the <see cref="BlobLeaseClient"/>  class.
 85        /// </summary>
 86        /// <param name="client">
 87        /// A <see cref="BlobClient"/> representing the blob being leased.
 88        /// </param>
 89        /// <param name="leaseId">
 90        /// An optional lease ID.  If no lease ID is provided, a random lease
 91        /// ID will be created.
 92        /// </param>
 96093        public BlobLeaseClient(BlobBaseClient client, string leaseId = null)
 94        {
 96095            _blob = client ?? throw Errors.ArgumentNull(nameof(client));
 96096            _container = null;
 96097            LeaseId = leaseId ?? CreateUniqueLeaseId();
 96098        }
 99
 100        /// <summary>
 101        /// Initializes a new instance of the <see cref="BlobLeaseClient"/>  class.
 102        /// </summary>
 103        /// <param name="client">
 104        /// A <see cref="BlobContainerClient"/> representing the blob container
 105        /// being leased.
 106        /// </param>
 107        /// <param name="leaseId">
 108        /// An optional lease ID.  If no lease ID is provided, a random lease
 109        /// ID will be created.
 110        /// </param>
 432111        public BlobLeaseClient(BlobContainerClient client, string leaseId = null)
 112        {
 432113            _blob = null;
 432114            _container = client ?? throw Errors.ArgumentNull(nameof(client));
 432115            LeaseId = leaseId ?? CreateUniqueLeaseId();
 432116        }
 117
 118        /// <summary>
 119        /// Gets a unique lease ID.
 120        /// </summary>
 121        /// <returns>A unique lease ID.</returns>
 68122        private static string CreateUniqueLeaseId() => Guid.NewGuid().ToString();
 123
 124        /// <summary>
 125        /// Ensure either the Blob or Container is present.
 126        /// </summary>
 127        private void EnsureClient()
 128        {
 1800129            if (BlobClient == null && BlobContainerClient == null)
 130            {
 131                // This can only happen if someone's not being careful while mocking
 0132                throw BlobErrors.BlobOrContainerMissing(nameof(BlobLeaseClient), nameof(BlobBaseClient), nameof(BlobCont
 133            }
 1800134        }
 135
 136        #region Acquire
 137        /// <summary>
 138        /// The <see cref="Acquire"/> operation acquires a lease on
 139        /// the blob or container.  The lease <paramref name="duration"/> must
 140        /// be between 15 to 60 seconds, or infinite (-1).
 141        ///
 142        /// If the container does not have an active lease, the Blob service
 143        /// creates a lease on the blob or container and returns it.  If the
 144        /// container has an active lease, you can only request a new lease
 145        /// using the active lease ID as <see cref="LeaseId"/>, but you can
 146        /// specify a new <paramref name="duration"/>.
 147        ///
 148        /// For more information, see <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container" />
 149        /// </summary>
 150        /// <param name="duration">
 151        /// Specifies the duration of the lease, in seconds, or specify
 152        /// <see cref="InfiniteLeaseDuration"/> for a lease that never expires.
 153        /// A non-infinite lease can be between 15 and 60 seconds.
 154        /// A lease duration cannot be changed using <see cref="RenewAsync"/>
 155        /// or <see cref="ChangeAsync"/>.
 156        /// </param>
 157        /// <param name="conditions">
 158        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 159        /// conditions on acquiring a lease.
 160        /// </param>
 161        /// <param name="cancellationToken">
 162        /// Optional <see cref="CancellationToken"/> to propagate
 163        /// notifications that the operation should be cancelled.
 164        /// </param>
 165        /// <returns>
 166        /// A <see cref="Response{Lease}"/> describing the lease.
 167        /// </returns>
 168        /// <remarks>
 169        /// A <see cref="RequestFailedException"/> will be thrown if
 170        /// a failure occurs.
 171        /// </remarks>
 172        public virtual Response<BlobLease> Acquire(
 173            TimeSpan duration,
 174            RequestConditions conditions = default,
 175            CancellationToken cancellationToken = default) =>
 596176            AcquireInternal(
 596177                duration,
 596178                conditions,
 596179                async: false,
 596180                cancellationToken)
 596181                .EnsureCompleted();
 182
 183        /// <summary>
 184        /// The <see cref="Acquire"/> operation acquires a lease on
 185        /// the blob or container.  The lease <paramref name="duration"/> must
 186        /// be between 15 to 60 seconds, or infinite (-1).
 187        ///
 188        /// If the container does not have an active lease, the Blob service
 189        /// creates a lease on the blob or container and returns it.  If the
 190        /// container has an active lease, you can only request a new lease
 191        /// using the active lease ID as <see cref="LeaseId"/>, but you can
 192        /// specify a new <paramref name="duration"/>.
 193        ///
 194        /// For more information, see
 195        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 196        /// Lease Container</see>.
 197        /// </summary>
 198        /// <param name="duration">
 199        /// Specifies the duration of the lease, in seconds, or specify
 200        /// <see cref="InfiniteLeaseDuration"/> for a lease that never expires.
 201        /// A non-infinite lease can be between 15 and 60 seconds.
 202        /// A lease duration cannot be changed using <see cref="RenewAsync"/>
 203        /// or <see cref="ChangeAsync"/>.
 204        /// </param>
 205        /// <param name="conditions">
 206        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 207        /// conditions on acquiring a lease.
 208        /// </param>
 209        /// <param name="cancellationToken">
 210        /// Optional <see cref="CancellationToken"/> to propagate
 211        /// notifications that the operation should be cancelled.
 212        /// </param>
 213        /// <returns>
 214        /// A <see cref="Response{Lease}"/> describing the lease.
 215        /// </returns>
 216        /// <remarks>
 217        /// A <see cref="RequestFailedException"/> will be thrown if
 218        /// a failure occurs.
 219        /// </remarks>
 220        public virtual async Task<Response<BlobLease>> AcquireAsync(
 221            TimeSpan duration,
 222            RequestConditions conditions = default,
 223            CancellationToken cancellationToken = default) =>
 596224            await AcquireInternal(
 596225                duration,
 596226                conditions,
 596227                async: true,
 596228                cancellationToken)
 596229                .ConfigureAwait(false);
 230
 231        /// <summary>
 232        /// The <see cref="AcquireInternal"/> operation acquires a lease on
 233        /// the blob or container.  The lease <paramref name="duration"/> must
 234        /// be between 15 to 60 seconds, or infinite (-1).
 235        ///
 236        /// If the container does not have an active lease, the Blob service
 237        /// creates a lease on the blob or container and returns it.  If the
 238        /// container has an active lease, you can only request a new lease
 239        /// using the active lease ID as <see cref="LeaseId"/>, but you can
 240        /// specify a new <paramref name="duration"/>.
 241        ///
 242        /// For more information, see
 243        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 244        /// Lease Container</see>.
 245        /// </summary>
 246        /// <param name="duration">
 247        /// Specifies the duration of the lease, in seconds, or specify
 248        /// <see cref="InfiniteLeaseDuration"/> for a lease that never expires.
 249        /// A non-infinite lease can be between 15 and 60 seconds.
 250        /// A lease duration cannot be changed using <see cref="RenewAsync"/>
 251        /// or <see cref="ChangeAsync"/>.
 252        /// </param>
 253        /// <param name="conditions">
 254        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 255        /// conditions on acquiring a lease.
 256        /// </param>
 257        /// <param name="async">
 258        /// Whether to invoke the operation asynchronously.
 259        /// </param>
 260        /// <param name="cancellationToken">
 261        /// Optional <see cref="CancellationToken"/> to propagate
 262        /// notifications that the operation should be cancelled.
 263        /// </param>
 264        /// <returns>
 265        /// A <see cref="Response{Lease}"/> describing the lease.
 266        /// </returns>
 267        /// <remarks>
 268        /// A <see cref="RequestFailedException"/> will be thrown if
 269        /// a failure occurs.
 270        /// </remarks>
 271        private async Task<Response<BlobLease>> AcquireInternal(
 272            TimeSpan duration,
 273            RequestConditions conditions,
 274            bool async,
 275            CancellationToken cancellationToken)
 276        {
 1192277            EnsureClient();
 278            // Int64 is an overflow safe cast relative to TimeSpan.MaxValue
 1192279            var serviceDuration = duration < TimeSpan.Zero ? Constants.Blob.Lease.InfiniteLeaseDuration : Convert.ToInt6
 1192280            using (Pipeline.BeginLoggingScope(nameof(BlobLeaseClient)))
 281            {
 282                Pipeline.LogMethodEnter(
 283                    nameof(BlobLeaseClient),
 284                    message:
 285                    $"{nameof(Uri)}: {Uri}\n" +
 286                    $"{nameof(LeaseId)}: {LeaseId}\n" +
 287                    $"{nameof(duration)}: {duration}");
 288                try
 289                {
 1192290                    string tagCondition = null;
 1192291                    if (conditions is BlobLeaseRequestConditions leaseConditions)
 292                    {
 28293                        tagCondition = leaseConditions?.TagConditions;
 294                    }
 295
 1192296                    if (BlobClient != null)
 297                    {
 912298                        return await BlobRestClient.Blob.AcquireLeaseAsync(
 912299                            ClientDiagnostics,
 912300                            Pipeline,
 912301                            Uri,
 912302                            version: Version.ToVersionString(),
 912303                            duration: serviceDuration,
 912304                            proposedLeaseId: LeaseId,
 912305                            ifModifiedSince: conditions?.IfModifiedSince,
 912306                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 912307                            ifMatch: conditions?.IfMatch,
 912308                            ifNoneMatch: conditions?.IfNoneMatch,
 912309                            ifTags: tagCondition,
 912310                            async: async,
 912311                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Acquire)}",
 912312                            cancellationToken: cancellationToken)
 912313                            .ConfigureAwait(false);
 314                    }
 315                    else
 316                    {
 280317                        if (conditions?.IfMatch != default || conditions?.IfNoneMatch != default)
 318                        {
 0319                            throw BlobErrors.BlobConditionsMustBeDefault(
 0320                                nameof(conditions.IfMatch),
 0321                                nameof(conditions.IfNoneMatch));
 322                        }
 280323                        return await BlobRestClient.Container.AcquireLeaseAsync(
 280324                            ClientDiagnostics,
 280325                            Pipeline,
 280326                            Uri,
 280327                            version: Version.ToVersionString(),
 280328                            duration: serviceDuration,
 280329                            proposedLeaseId: LeaseId,
 280330                            ifModifiedSince: conditions?.IfModifiedSince,
 280331                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 280332                            async: async,
 280333                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Acquire)}",
 280334                            cancellationToken: cancellationToken)
 280335                            .ConfigureAwait(false);
 336                    }
 337                }
 92338                catch (Exception ex)
 339                {
 340                    Pipeline.LogException(ex);
 92341                    throw;
 342                }
 343                finally
 344                {
 345                    Pipeline.LogMethodExit(nameof(BlobLeaseClient));
 346                }
 347            }
 1100348        }
 349        #endregion Acquire
 350
 351        #region Renew
 352        /// <summary>
 353        /// The <see cref="Renew"/> operation renews the blob or
 354        /// container's previously-acquired lease.
 355        ///
 356        /// The lease can be renewed if the leaseId
 357        /// matches that associated with the blob or container.  Note that the]
 358        /// lease may be renewed even if it has expired as long as the blob or
 359        /// container has not been leased again since the expiration of that
 360        /// lease.  When you renew a lease, the lease duration clock resets.
 361        ///
 362        /// For more information, see
 363        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 364        /// Lease Container</see>.
 365        /// </summary>
 366        /// <param name="conditions">
 367        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 368        /// conditions on renewing a lease.
 369        /// </param>
 370        /// <param name="cancellationToken">
 371        /// Optional <see cref="CancellationToken"/> to propagate
 372        /// notifications that the operation should be cancelled.
 373        /// </param>
 374        /// <returns>
 375        /// A <see cref="Response{Lease}"/> describing the lease.
 376        /// </returns>
 377        /// <remarks>
 378        /// A <see cref="RequestFailedException"/> will be thrown if
 379        /// a failure occurs.
 380        /// </remarks>
 381        public virtual Response<BlobLease> Renew(
 382            RequestConditions conditions = default,
 383            CancellationToken cancellationToken = default) =>
 94384            RenewInternal(
 94385                conditions,
 94386                false, // async
 94387                cancellationToken)
 94388                .EnsureCompleted();
 389
 390        /// <summary>
 391        /// The <see cref="RenewAsync"/> operation renews the blob or
 392        /// container's previously-acquired lease.
 393        ///
 394        /// The lease can be renewed if the leaseId
 395        /// matches that associated with the blob or container.  Note that the]
 396        /// lease may be renewed even if it has expired as long as the blob or
 397        /// container has not been leased again since the expiration of that
 398        /// lease.  When you renew a lease, the lease duration clock resets.
 399        ///
 400        /// For more information, see
 401        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 402        /// Lease Container</see>.
 403        /// </summary>
 404        /// <param name="conditions">
 405        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 406        /// conditions on renewing a lease.
 407        /// </param>
 408        /// <param name="cancellationToken">
 409        /// Optional <see cref="CancellationToken"/> to propagate
 410        /// notifications that the operation should be cancelled.
 411        /// </param>
 412        /// <returns>
 413        /// A <see cref="Response{Lease}"/> describing the lease.
 414        /// </returns>
 415        /// <remarks>
 416        /// A <see cref="RequestFailedException"/> will be thrown if
 417        /// a failure occurs.
 418        /// </remarks>
 419        public virtual async Task<Response<BlobLease>> RenewAsync(
 420            RequestConditions conditions = default,
 421            CancellationToken cancellationToken = default) =>
 94422            await RenewInternal(
 94423                conditions,
 94424                true, // async
 94425                cancellationToken)
 94426                .ConfigureAwait(false);
 427
 428        /// <summary>
 429        /// The <see cref="RenewInternal"/> operation renews the blob or
 430        /// container's previously-acquired lease.
 431        ///
 432        /// The lease can be renewed if the leaseId
 433        /// matches that associated with the blob or container.  Note that the]
 434        /// lease may be renewed even if it has expired as long as the blob or
 435        /// container has not been leased again since the expiration of that
 436        /// lease.  When you renew a lease, the lease duration clock resets.
 437        ///
 438        /// For more information, see
 439        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 440        /// Lease Container</see>.
 441        /// </summary>
 442        /// <param name="conditions">
 443        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 444        /// conditions on renewing a lease.
 445        /// </param>
 446        /// <param name="async">
 447        /// Whether to invoke the operation asynchronously.
 448        /// </param>
 449        /// <param name="cancellationToken">
 450        /// Optional <see cref="CancellationToken"/> to propagate
 451        /// notifications that the operation should be cancelled.
 452        /// </param>
 453        /// <returns>
 454        /// A <see cref="Response{Lease}"/> describing the lease.
 455        /// </returns>
 456        /// <remarks>
 457        /// A <see cref="RequestFailedException"/> will be thrown if
 458        /// a failure occurs.
 459        /// </remarks>
 460        private async Task<Response<BlobLease>> RenewInternal(
 461            RequestConditions conditions,
 462            bool async,
 463            CancellationToken cancellationToken)
 464        {
 188465            using (Pipeline.BeginLoggingScope(nameof(BlobLeaseClient)))
 466            {
 467                Pipeline.LogMethodEnter(
 468                    nameof(BlobLeaseClient),
 469                    message:
 470                    $"{nameof(Uri)}: {Uri}\n" +
 471                    $"{nameof(LeaseId)}: {LeaseId}\n" +
 472                    $"{nameof(conditions)}: {conditions}");
 473                try
 474                {
 188475                    string tagConditions = null;
 188476                    if (conditions != null && conditions.GetType() == typeof(BlobLeaseRequestConditions))
 477                    {
 8478                        tagConditions = ((BlobLeaseRequestConditions)conditions).TagConditions;
 479                    }
 480
 188481                    if (BlobClient != null)
 482                    {
 140483                        return await BlobRestClient.Blob.RenewLeaseAsync(
 140484                            ClientDiagnostics,
 140485                            Pipeline,
 140486                            Uri,
 140487                            leaseId: LeaseId,
 140488                            version: Version.ToVersionString(),
 140489                            ifModifiedSince: conditions?.IfModifiedSince,
 140490                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 140491                            ifMatch: conditions?.IfMatch,
 140492                            ifNoneMatch: conditions?.IfNoneMatch,
 140493                            ifTags: tagConditions,
 140494                            async: async,
 140495                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Renew)}",
 140496                            cancellationToken: cancellationToken)
 140497                            .ConfigureAwait(false);
 498                    }
 499                    else
 500                    {
 48501                        if (conditions?.IfMatch != default || conditions?.IfNoneMatch != default)
 502                        {
 0503                            throw BlobErrors.BlobConditionsMustBeDefault(
 0504                                nameof(conditions.IfMatch),
 0505                                nameof(conditions.IfNoneMatch));
 506                        }
 48507                        return await BlobRestClient.Container.RenewLeaseAsync(
 48508                            ClientDiagnostics,
 48509                            Pipeline,
 48510                            Uri,
 48511                            leaseId: LeaseId,
 48512                            version: Version.ToVersionString(),
 48513                            ifModifiedSince: conditions?.IfModifiedSince,
 48514                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 48515                            async: async,
 48516                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Renew)}",
 48517                            cancellationToken: cancellationToken)
 48518                            .ConfigureAwait(false);
 519                    }
 520                }
 80521                catch (Exception ex)
 522                {
 523                    Pipeline.LogException(ex);
 80524                    throw;
 525                }
 526                finally
 527                {
 528                    Pipeline.LogMethodExit(nameof(BlobLeaseClient));
 529                }
 530            }
 108531        }
 532        #endregion Renew
 533
 534        #region Release
 535        /// <summary>
 536        /// The <see cref="Release"/> operation releases the
 537        /// container or blob's previously-acquired lease.
 538        ///
 539        /// The lease may be released if the <see cref="LeaseId"/>
 540        /// matches that associated with the container or blob.  Releasing the
 541        /// lease allows another client to immediately acquire the lease for the
 542        /// container or blob as soon as the release is complete.
 543        ///
 544        /// For more information, see
 545        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 546        /// Lease Container</see>.
 547        /// </summary>
 548        /// <param name="conditions">
 549        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 550        /// conditions on releasing a lease.
 551        /// </param>
 552        /// <param name="cancellationToken">
 553        /// Optional <see cref="CancellationToken"/> to propagate
 554        /// notifications that the operation should be cancelled.
 555        /// </param>
 556        /// <returns>
 557        /// A <see cref="Response{ReleaseObjectLeaseInfo}"/> describing the
 558        /// updated blob or container.
 559        /// </returns>
 560        /// <remarks>
 561        /// A <see cref="RequestFailedException"/> will be thrown if
 562        /// a failure occurs.
 563        /// </remarks>
 564        public virtual Response<ReleasedObjectInfo> Release(
 565            RequestConditions conditions = default,
 566            CancellationToken cancellationToken = default) =>
 106567            ReleaseInternal(
 106568                conditions,
 106569                false, // async
 106570                cancellationToken)
 106571                .EnsureCompleted();
 572
 573        /// <summary>
 574        /// The <see cref="ReleaseAsync"/> operation releases the
 575        /// container or blob's previously-acquired lease.
 576        ///
 577        /// The lease may be released if the <see cref="LeaseId"/>
 578        /// matches that associated with the container or blob.  Releasing the
 579        /// lease allows another client to immediately acquire the lease for the
 580        /// container or blob as soon as the release is complete.
 581        ///
 582        /// For more information, see
 583        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 584        /// Lease Container</see>.
 585        /// </summary>
 586        /// <param name="conditions">
 587        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 588        /// conditions on releasing a lease.
 589        /// </param>
 590        /// <param name="cancellationToken">
 591        /// Optional <see cref="CancellationToken"/> to propagate
 592        /// notifications that the operation should be cancelled.
 593        /// </param>
 594        /// <returns>
 595        /// A <see cref="Response{ReleasedObjectInfo}"/> describing the
 596        /// updated blob or container.
 597        /// </returns>
 598        /// <remarks>
 599        /// A <see cref="RequestFailedException"/> will be thrown if
 600        /// a failure occurs.
 601        /// </remarks>
 602        public virtual async Task<Response<ReleasedObjectInfo>> ReleaseAsync(
 603            RequestConditions conditions = default,
 604            CancellationToken cancellationToken = default) =>
 106605            await ReleaseInternal(
 106606                conditions,
 106607                true, // async
 106608                cancellationToken)
 106609                .ConfigureAwait(false);
 610
 611        /// <summary>
 612        /// The <see cref="ReleaseInternal"/> operation releases the
 613        /// container or blob's previously-acquired lease.
 614        ///
 615        /// The lease may be released if the <see cref="LeaseId"/>
 616        /// matches that associated with the container or blob.  Releasing the
 617        /// lease allows another client to immediately acquire the lease for the
 618        /// container or blob as soon as the release is complete.
 619        ///
 620        /// For more information, see
 621        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 622        /// Lease Container</see>.
 623        /// </summary>
 624        /// <param name="conditions">
 625        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 626        /// conditions on releasing a lease.
 627        /// </param>
 628        /// <param name="async">
 629        /// Whether to invoke the operation asynchronously.
 630        /// </param>
 631        /// <param name="cancellationToken">
 632        /// Optional <see cref="CancellationToken"/> to propagate
 633        /// notifications that the operation should be cancelled.
 634        /// </param>
 635        /// <returns>
 636        /// A <see cref="Response{ReleasedObjectInfo}"/> describing the
 637        /// updated blob or container.
 638        /// </returns>
 639        /// <remarks>
 640        /// A <see cref="RequestFailedException"/> will be thrown if
 641        /// a failure occurs.
 642        /// </remarks>
 643        [EditorBrowsable(EditorBrowsableState.Never)]
 644        public virtual async Task<Response<ReleasedObjectInfo>> ReleaseInternal(
 645            RequestConditions conditions,
 646#pragma warning disable AZC0105 // DO NOT add 'async' parameter to public methods. This method is published, so it can't
 647            bool async,
 648#pragma warning restore AZC0105 // DO NOT add 'async' parameter to public methods.
 649            CancellationToken cancellationToken)
 650        {
 212651            EnsureClient();
 212652            using (Pipeline.BeginLoggingScope(nameof(BlobLeaseClient)))
 653            {
 654                Pipeline.LogMethodEnter(
 655                    nameof(BlobLeaseClient),
 656                    message:
 657                    $"{nameof(Uri)}: {Uri}\n" +
 658                    $"{nameof(LeaseId)}: {LeaseId}\n" +
 659                    $"{nameof(conditions)}: {conditions}");
 660                try
 661                {
 212662                    string tagConditions = default;
 663
 212664                    if (conditions != null && conditions.GetType() == typeof(BlobLeaseRequestConditions))
 665                    {
 8666                        tagConditions = ((BlobLeaseRequestConditions)conditions).TagConditions;
 667                    }
 668
 212669                    if (BlobClient != null)
 670                    {
 140671                        Response<BlobInfo> response =
 140672                            await BlobRestClient.Blob.ReleaseLeaseAsync(
 140673                                ClientDiagnostics,
 140674                                Pipeline,
 140675                                Uri,
 140676                                leaseId: LeaseId,
 140677                                version: Version.ToVersionString(),
 140678                                ifModifiedSince: conditions?.IfModifiedSince,
 140679                                ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 140680                                ifMatch: conditions?.IfMatch,
 140681                                ifNoneMatch: conditions?.IfNoneMatch,
 140682                                ifTags: tagConditions,
 140683                                async: async,
 140684                                operationName: $"{nameof(BlobLeaseClient)}.{nameof(Release)}",
 140685                                cancellationToken: cancellationToken)
 140686                                .ConfigureAwait(false);
 76687                        return Response.FromValue(new ReleasedObjectInfo(response.Value), response.GetRawResponse());
 688                    }
 689                    else
 690                    {
 72691                        if (conditions?.IfMatch != default || conditions?.IfNoneMatch != default)
 692                        {
 0693                            throw BlobErrors.BlobConditionsMustBeDefault(
 0694                                nameof(RequestConditions.IfMatch),
 0695                                nameof(RequestConditions.IfNoneMatch));
 696                        }
 72697                        Response<BlobContainerInfo> response =
 72698                            await BlobRestClient.Container.ReleaseLeaseAsync(
 72699                                ClientDiagnostics,
 72700                                Pipeline,
 72701                                Uri,
 72702                                leaseId: LeaseId,
 72703                                version: Version.ToVersionString(),
 72704                                ifModifiedSince: conditions?.IfModifiedSince,
 72705                                ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 72706                                async: async,
 72707                                operationName: $"{nameof(BlobLeaseClient)}.{nameof(Release)}",
 72708                                cancellationToken: cancellationToken)
 72709                                .ConfigureAwait(false);
 40710                        return Response.FromValue(new ReleasedObjectInfo(response.Value), response.GetRawResponse());
 711                    }
 712                }
 96713                catch (Exception ex)
 714                {
 715                    Pipeline.LogException(ex);
 96716                    throw;
 717                }
 718                finally
 719                {
 720                    Pipeline.LogMethodExit(nameof(BlobLeaseClient));
 721                }
 722            }
 116723        }
 724        #endregion Release
 725
 726        #region Change
 727        /// <summary>
 728        /// The <see cref="Change"/> operation changes the lease
 729        /// of an active lease.  A change must include the current
 730        /// <see cref="LeaseId"/> and a new <paramref name="proposedId"/>.
 731        ///
 732        /// For more information, see
 733        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 734        /// Lease Container</see>.
 735        /// </summary>
 736        /// <param name="proposedId">
 737        /// An optional proposed lease ID, in a GUID string format. A
 738        /// <see cref="RequestFailedException"/> will be thrown if the
 739        /// proposed lease ID is not in the correct format.
 740        /// </param>
 741        /// <param name="conditions">
 742        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 743        /// conditions on changing a lease.
 744        /// </param>
 745        /// <param name="cancellationToken">
 746        /// Optional <see cref="CancellationToken"/> to propagate
 747        /// notifications that the operation should be cancelled.
 748        /// </param>
 749        /// <returns>
 750        /// A <see cref="Response{Lease}"/> describing the lease.
 751        /// </returns>
 752        /// <remarks>
 753        /// A <see cref="RequestFailedException"/> will be thrown if
 754        /// a failure occurs.
 755        /// </remarks>
 756        public virtual Response<BlobLease> Change(
 757            string proposedId,
 758            RequestConditions conditions = default,
 759            CancellationToken cancellationToken = default) =>
 98760            ChangeInternal(
 98761                proposedId,
 98762                conditions,
 98763                false, // async
 98764                cancellationToken)
 98765                .EnsureCompleted();
 766
 767        /// <summary>
 768        /// The <see cref="ChangeAsync"/> operation changes the lease
 769        /// of an active lease.  A change must include the current
 770        /// <see cref="LeaseId"/> and a new <paramref name="proposedId"/>.
 771        ///
 772        /// For more information, see
 773        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 774        /// Lease Container</see>.
 775        /// </summary>
 776        /// <param name="proposedId">
 777        /// An optional proposed lease ID, in a GUID string format. A
 778        /// <see cref="RequestFailedException"/> will be thrown if the
 779        /// proposed lease ID is not in the correct format.
 780        /// </param>
 781        /// <param name="conditions">
 782        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 783        /// conditions on changing a lease.
 784        /// </param>
 785        /// <param name="cancellationToken">
 786        /// Optional <see cref="CancellationToken"/> to propagate
 787        /// notifications that the operation should be cancelled.
 788        /// </param>
 789        /// <returns>
 790        /// A <see cref="Response{Lease}"/> describing the lease.
 791        /// </returns>
 792        /// <remarks>
 793        /// A <see cref="RequestFailedException"/> will be thrown if
 794        /// a failure occurs.
 795        /// </remarks>
 796        public virtual async Task<Response<BlobLease>> ChangeAsync(
 797            string proposedId,
 798            RequestConditions conditions = default,
 799            CancellationToken cancellationToken = default) =>
 98800            await ChangeInternal(
 98801                proposedId,
 98802                conditions,
 98803                true, // async
 98804                cancellationToken)
 98805                .ConfigureAwait(false);
 806
 807        /// <summary>
 808        /// The <see cref="ChangeInternal"/> operation changes the lease
 809        /// of an active lease.  A change must include the current
 810        /// <see cref="LeaseId"/> and a new <paramref name="proposedId"/>.
 811        ///
 812        /// For more information, see
 813        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 814        /// Lease Container</see>.
 815        /// </summary>
 816        /// <param name="proposedId">
 817        /// An optional proposed lease ID, in a GUID string format. A
 818        /// <see cref="RequestFailedException"/> will be thrown if the
 819        /// proposed lease ID is not in the correct format.
 820        /// </param>
 821        /// <param name="conditions">
 822        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 823        /// conditions on changing a lease.
 824        /// </param>
 825        /// <param name="async">
 826        /// Whether to invoke the operation asynchronously.
 827        /// </param>
 828        /// <param name="cancellationToken">
 829        /// Optional <see cref="CancellationToken"/> to propagate
 830        /// notifications that the operation should be cancelled.
 831        /// </param>
 832        /// <returns>
 833        /// A <see cref="Response{Lease}"/> describing the lease.
 834        /// </returns>
 835        /// <remarks>
 836        /// A <see cref="RequestFailedException"/> will be thrown if
 837        /// a failure occurs.
 838        /// </remarks>
 839        private async Task<Response<BlobLease>> ChangeInternal(
 840            string proposedId,
 841            RequestConditions conditions,
 842            bool async,
 843            CancellationToken cancellationToken)
 844        {
 196845            EnsureClient();
 196846            using (Pipeline.BeginLoggingScope(nameof(BlobLeaseClient)))
 847            {
 848                Pipeline.LogMethodEnter(
 849                    nameof(BlobLeaseClient),
 850                    message:
 851                    $"{nameof(Uri)}: {Uri}\n" +
 852                    $"{nameof(LeaseId)}: {LeaseId}\n" +
 853                    $"{nameof(proposedId)}: {proposedId}\n" +
 854                    $"{nameof(conditions)}: {conditions}");
 855                try
 856                {
 196857                    string tagCondition = null;
 196858                    if (conditions != null && conditions.GetType() == typeof(BlobLeaseRequestConditions))
 859                    {
 8860                        tagCondition = ((BlobLeaseRequestConditions)conditions).TagConditions;
 861                    }
 862
 196863                    if (BlobClient != null)
 864                    {
 140865                        return await BlobRestClient.Blob.ChangeLeaseAsync(
 140866                            ClientDiagnostics,
 140867                            Pipeline,
 140868                            Uri,
 140869                            leaseId: LeaseId,
 140870                            proposedLeaseId: proposedId,
 140871                            version: Version.ToVersionString(),
 140872                            ifModifiedSince: conditions?.IfModifiedSince,
 140873                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 140874                            ifMatch: conditions?.IfMatch,
 140875                            ifNoneMatch: conditions?.IfNoneMatch,
 140876                            ifTags: tagCondition,
 140877                            async: async,
 140878                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Change)}",
 140879                            cancellationToken: cancellationToken)
 140880                            .ConfigureAwait(false);
 881                    }
 882                    else
 883                    {
 56884                        if (conditions?.IfMatch != default || conditions?.IfNoneMatch != default)
 885                        {
 0886                            throw BlobErrors.BlobConditionsMustBeDefault(
 0887                                nameof(conditions.IfMatch),
 0888                                nameof(conditions.IfNoneMatch));
 889                        }
 56890                        return await BlobRestClient.Container.ChangeLeaseAsync(
 56891                            ClientDiagnostics,
 56892                            Pipeline,
 56893                            Uri,
 56894                            leaseId: LeaseId,
 56895                            proposedLeaseId: proposedId,
 56896                            version: Version.ToVersionString(),
 56897                            ifModifiedSince: conditions?.IfModifiedSince,
 56898                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 56899                            async: async,
 56900                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Change)}",
 56901                            cancellationToken: cancellationToken)
 56902                            .ConfigureAwait(false);
 903                    }
 904                }
 88905                catch (Exception ex)
 906                {
 907                    Pipeline.LogException(ex);
 88908                    throw;
 909                }
 910                finally
 911                {
 912                    Pipeline.LogMethodExit(nameof(BlobLeaseClient));
 913                }
 914            }
 108915        }
 916        #endregion Change
 917
 918        #region Break
 919        /// <summary>
 920        /// The <see cref="Break"/> operation breaks the blob or
 921        /// container's previously-acquired lease (if it exists).
 922        ///
 923        /// Once a lease is broken, it cannot be renewed.  Any authorized
 924        /// request can break the lease; the request is not required to
 925        /// specify a matching lease ID.  When a lease is broken, the lease
 926        /// break <paramref name="breakPeriod"/> is allowed to elapse,
 927        /// during which time no lease operation except
 928        /// <see cref="Break(TimeSpan?, RequestConditions, CancellationToken)"/>
 929        /// and <see cref="Release"/> can be
 930        /// performed on the blob or container.  When a lease is successfully
 931        /// broken, the response indicates the interval in seconds until a new
 932        /// lease can be acquired.
 933        ///
 934        /// A lease that has been broken can also be released.  A client can
 935        /// immediately acquire a blob or container lease that has been
 936        /// released.
 937        ///
 938        /// For more information, see
 939        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 940        /// Lease Container</see>.
 941        /// </summary>
 942        /// <param name="breakPeriod">
 943        /// Specifies the proposed duration the lease should continue before
 944        /// it is broken, in seconds, between 0 and 60.  This break period is
 945        /// only used if it is shorter than the time remaining on the lease.
 946        /// If longer, the time remaining on the lease is used.  A new lease
 947        /// will not be available before the break period has expired, but the
 948        /// lease may be held for longer than the break period.  If this value
 949        /// is not provided, a fixed-duration lease breaks after the remaining
 950        /// lease period elapses, and an infinite lease breaks immediately.
 951        /// </param>
 952        /// <param name="conditions">
 953        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 954        /// conditions on breaking a lease.
 955        /// </param>
 956        /// <param name="cancellationToken">
 957        /// Optional <see cref="CancellationToken"/> to propagate
 958        /// notifications that the operation should be cancelled.
 959        /// </param>
 960        /// <returns>
 961        /// A <see cref="Response{Lease}"/> describing the broken lease.
 962        /// </returns>
 963        /// <remarks>
 964        /// A <see cref="RequestFailedException"/> will be thrown if
 965        /// a failure occurs.
 966        /// </remarks>
 967        public virtual Response<BlobLease> Break(
 968            TimeSpan? breakPeriod = default,
 969            RequestConditions conditions = default,
 970            CancellationToken cancellationToken = default) =>
 100971            BreakInternal(
 100972                breakPeriod,
 100973                conditions,
 100974                false, // async
 100975                cancellationToken)
 100976                .EnsureCompleted();
 977
 978        /// <summary>
 979        /// The <see cref="BreakAsync"/> operation breaks the blob or
 980        /// container's previously-acquired lease (if it exists).
 981        ///
 982        /// Once a lease is broken, it cannot be renewed.  Any authorized
 983        /// request can break the lease; the request is not required to
 984        /// specify a matching lease ID.  When a lease is broken, the lease
 985        /// break <paramref name="breakPeriod"/> is allowed to elapse,
 986        /// during which time no lease operation except
 987        /// <see cref="BreakAsync(TimeSpan?, RequestConditions, CancellationToken)"/>
 988        /// and <see cref="ReleaseAsync"/> can be
 989        /// performed on the blob or container.  When a lease is successfully
 990        /// broken, the response indicates the interval in seconds until a new
 991        /// lease can be acquired.
 992        ///
 993        /// A lease that has been broken can also be released.  A client can
 994        /// immediately acquire a blob or container lease that has been
 995        /// released.
 996        ///
 997        /// For more information, see
 998        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 999        /// Lease Container</see>.
 1000        /// </summary>
 1001        /// <param name="breakPeriod">
 1002        /// Specifies the proposed duration the lease should continue before
 1003        /// it is broken, in seconds, between 0 and 60.  This break period is
 1004        /// only used if it is shorter than the time remaining on the lease.
 1005        /// If longer, the time remaining on the lease is used.  A new lease
 1006        /// will not be available before the break period has expired, but the
 1007        /// lease may be held for longer than the break period.  If this value
 1008        /// is not provided, a fixed-duration lease breaks after the remaining
 1009        /// lease period elapses, and an infinite lease breaks immediately.
 1010        /// </param>
 1011        /// <param name="conditions">
 1012        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 1013        /// conditions on breaking a lease.
 1014        /// </param>
 1015        /// <param name="cancellationToken">
 1016        /// Optional <see cref="CancellationToken"/> to propagate
 1017        /// notifications that the operation should be cancelled.
 1018        /// </param>
 1019        /// <returns>
 1020        /// A <see cref="Response{Lease}"/> describing the broken lease.
 1021        /// </returns>
 1022        /// <remarks>
 1023        /// A <see cref="RequestFailedException"/> will be thrown if
 1024        /// a failure occurs.
 1025        /// </remarks>
 1026        public virtual async Task<Response<BlobLease>> BreakAsync(
 1027            TimeSpan? breakPeriod = default,
 1028            RequestConditions conditions = default,
 1029            CancellationToken cancellationToken = default) =>
 1001030            await BreakInternal(
 1001031                breakPeriod,
 1001032                conditions,
 1001033                true, // async
 1001034                cancellationToken)
 1001035                .ConfigureAwait(false);
 1036
 1037        /// <summary>
 1038        /// The <see cref="BreakInternal"/> operation breaks the blob or
 1039        /// container's previously-acquired lease (if it exists).
 1040        ///
 1041        /// Once a lease is broken, it cannot be renewed.  Any authorized
 1042        /// request can break the lease; the request is not required to
 1043        /// specify a matching lease ID.  When a lease is broken, the lease
 1044        /// break <paramref name="breakPeriod"/> is allowed to elapse,
 1045        /// during which time no lease operation except
 1046        /// <see cref="BreakAsync"/>
 1047        /// and <see cref="ReleaseAsync"/> can be
 1048        /// performed on the blob or container.  When a lease is successfully
 1049        /// broken, the response indicates the interval in seconds until a new
 1050        /// lease can be acquired.
 1051        ///
 1052        /// A lease that has been broken can also be released.  A client can
 1053        /// immediately acquire a blob or container lease that has been
 1054        /// released.
 1055        ///
 1056        /// For more information, see
 1057        /// <see href="https://docs.microsoft.com/rest/api/storageservices/lease-container">
 1058        /// Lease Container</see>.
 1059        /// </summary>
 1060        /// <param name="breakPeriod">
 1061        /// Specifies the proposed duration the lease should continue before
 1062        /// it is broken, in seconds, between 0 and 60.  This break period is
 1063        /// only used if it is shorter than the time remaining on the lease.
 1064        /// If longer, the time remaining on the lease is used.  A new lease
 1065        /// will not be available before the break period has expired, but the
 1066        /// lease may be held for longer than the break period.  If this value
 1067        /// is not provided, a fixed-duration lease breaks after the remaining
 1068        /// lease period elapses, and an infinite lease breaks immediately.
 1069        /// </param>
 1070        /// <param name="conditions">
 1071        /// Optional <see cref="BlobLeaseRequestConditions"/> to add
 1072        /// conditions on breaking a lease.
 1073        /// </param>
 1074        /// <param name="async">
 1075        /// Whether to invoke the operation asynchronously.
 1076        /// </param>
 1077        /// <param name="cancellationToken">
 1078        /// Optional <see cref="CancellationToken"/> to propagate
 1079        /// notifications that the operation should be cancelled.
 1080        /// </param>
 1081        /// <returns>
 1082        /// A <see cref="Response{Lease}"/> describing the broken lease.
 1083        /// </returns>
 1084        /// <remarks>
 1085        /// A <see cref="RequestFailedException"/> will be thrown if
 1086        /// a failure occurs.
 1087        /// </remarks>
 1088        private async Task<Response<BlobLease>> BreakInternal(
 1089            TimeSpan? breakPeriod,
 1090            RequestConditions conditions,
 1091            bool async,
 1092            CancellationToken cancellationToken)
 1093        {
 2001094            EnsureClient();
 2001095            long? serviceBreakPeriod = breakPeriod != null ? Convert.ToInt64(breakPeriod.Value.TotalSeconds) : (long?) n
 2001096            using (Pipeline.BeginLoggingScope(nameof(BlobLeaseClient)))
 1097            {
 1098                Pipeline.LogMethodEnter(
 1099                    nameof(BlobLeaseClient),
 1100                    message:
 1101                    $"{nameof(Uri)}: {Uri}\n" +
 1102                    $"{nameof(breakPeriod)}: {breakPeriod}\n" +
 1103                    $"{nameof(conditions)}: {conditions}");
 1104                try
 1105                {
 2001106                    string tagConditions = null;
 2001107                    if (conditions != null && conditions.GetType() == typeof(BlobLeaseRequestConditions))
 1108                    {
 81109                        tagConditions = ((BlobLeaseRequestConditions)conditions).TagConditions;
 1110                    }
 1111
 2001112                    if (BlobClient != null)
 1113                    {
 1441114                        return (await BlobRestClient.Blob.BreakLeaseAsync(
 1441115                            ClientDiagnostics,
 1441116                            Pipeline,
 1441117                            Uri,
 1441118                            version: Version.ToVersionString(),
 1441119                            breakPeriod: serviceBreakPeriod,
 1441120                            ifModifiedSince: conditions?.IfModifiedSince,
 1441121                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1441122                            ifMatch: conditions?.IfMatch,
 1441123                            ifNoneMatch: conditions?.IfNoneMatch,
 1441124                            ifTags: tagConditions,
 1441125                            async: async,
 1441126                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Break)}",
 1441127                            cancellationToken: cancellationToken)
 1441128                            .ConfigureAwait(false))
 1441129                            .ToLease();
 1130                    }
 1131                    else
 1132                    {
 561133                        if (conditions?.IfMatch != default || conditions?.IfNoneMatch != default)
 1134                        {
 01135                            throw BlobErrors.BlobConditionsMustBeDefault(
 01136                                nameof(conditions.IfMatch),
 01137                                nameof(conditions.IfNoneMatch));
 1138                        }
 561139                        return (await BlobRestClient.Container.BreakLeaseAsync(
 561140                            ClientDiagnostics,
 561141                            Pipeline,
 561142                            Uri,
 561143                            version: Version.ToVersionString(),
 561144                            breakPeriod: serviceBreakPeriod,
 561145                            ifModifiedSince: conditions?.IfModifiedSince,
 561146                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 561147                            async: async,
 561148                            operationName: $"{nameof(BlobLeaseClient)}.{nameof(Break)}",
 561149                            cancellationToken: cancellationToken)
 561150                            .ConfigureAwait(false))
 561151                            .ToLease();
 1152                    }
 1153                }
 881154                catch (Exception ex)
 1155                {
 1156                    Pipeline.LogException(ex);
 881157                    throw;
 1158                }
 1159                finally
 1160                {
 1161                    Pipeline.LogMethodExit(nameof(BlobLeaseClient));
 1162                }
 1163            }
 1121164        }
 1165        #endregion Break
 1166    }
 1167
 1168    /// <summary>
 1169    /// Add easy to discover methods to <see cref="BlobContainerClient"/> and
 1170    /// <see cref="BlobClient"/> for easily creating <see cref="BlobLeaseClient"/>
 1171    /// instances.
 1172    /// </summary>
 1173    public static partial class SpecializedBlobExtensions
 1174    {
 1175        /// <summary>
 1176        /// Initializes a new instance of the <see cref="BlobLeaseClient"/> class.
 1177        /// </summary>
 1178        /// <param name="client">
 1179        /// A <see cref="BlobClient"/> representing the blob being leased.
 1180        /// </param>
 1181        /// <param name="leaseId">
 1182        /// An optional lease ID.  If no lease ID is provided, a random lease
 1183        /// ID will be created.
 1184        /// </param>
 1185        public static BlobLeaseClient GetBlobLeaseClient(
 1186            this BlobBaseClient client,
 1187            string leaseId = null) =>
 1188            new BlobLeaseClient(client, leaseId);
 1189
 1190        /// <summary>
 1191        /// Initializes a new instance of the <see cref="BlobLeaseClient"/> class.
 1192        /// </summary>
 1193        /// <param name="client">
 1194        /// A <see cref="BlobContainerClient"/> representing the container
 1195        /// being leased.
 1196        /// </param>
 1197        /// <param name="leaseId">
 1198        /// An optional lease ID.  If no lease ID is provided, a random lease
 1199        /// ID will be created.
 1200        /// </param>
 1201        public static BlobLeaseClient GetBlobLeaseClient(
 1202            this BlobContainerClient client,
 1203            string leaseId = null) =>
 1204            new BlobLeaseClient(client, leaseId);
 1205    }
 1206}