< Summary

Class:Azure.Storage.Blobs.Specialized.PageBlobClient
Assembly:Azure.Storage.Blobs
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\PageBlobClient.cs
Covered lines:524
Uncovered lines:28
Coverable lines:552
Total lines:2937
Line coverage:94.9% (524 of 552)
Covered branches:200
Total branches:232
Branch coverage:86.2% (200 of 232)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_PageBlobPageBytes()-0%100%
get_PageBlobMaxUploadPagesBytes()-0%100%
.ctor()-100%100%
.ctor(...)-0%100%
.ctor(...)-100%100%
.ctor(...)-100%100%
.ctor(...)-0%100%
.ctor(...)-33.33%100%
.ctor(...)-100%100%
AssertNoClientSideEncryption(...)-66.67%75%
WithSnapshot(...)-100%100%
WithSnapshotCore(...)-100%100%
WithVersion(...)-100%100%
Create(...)-100%50%
CreateAsync()-100%50%
Create(...)-100%100%
CreateAsync()-100%100%
CreateIfNotExists(...)-0%0%
CreateIfNotExistsAsync()-0%0%
CreateIfNotExists(...)-100%100%
CreateIfNotExistsAsync()-100%100%
CreateIfNotExistsInternal()-100%100%
CreateInternal()-100%100%
UploadPages(...)-100%100%
UploadPagesAsync()-100%100%
UploadPagesInternal()-100%100%
ClearPages(...)-100%100%
ClearPagesAsync()-100%100%
ClearPagesInternal()-100%87.5%
GetPageRanges(...)-100%100%
GetPageRangesAsync()-100%100%
GetPageRangesInternal()-100%93.75%
GetPageRangesDiff(...)-100%100%
GetPageRangesDiffAsync()-100%100%
GetPageRangesDiffInternal()-100%93.75%
GetManagedDiskPageRangesDiff(...)-100%100%
GetManagedDiskPageRangesDiffAsync()-100%100%
Resize(...)-100%100%
ResizeAsync()-100%100%
ResizeInternal()-100%100%
UpdateSequenceNumber(...)-100%100%
UpdateSequenceNumberAsync()-100%100%
UpdateSequenceNumberInternal()-100%100%
StartCopyIncremental(...)-100%100%
StartCopyIncrementalAsync()-100%100%
StartCopyIncrementalInternal()-100%100%
UploadPagesFromUri(...)-100%100%
UploadPagesFromUriAsync()-100%100%
UploadPagesFromUriInternal()-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\PageBlobClient.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.IO;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using System.Xml.Serialization;
 10using Azure.Core;
 11using Azure.Core.Pipeline;
 12using Azure.Storage.Blobs.Models;
 13using Metadata = System.Collections.Generic.IDictionary<string, string>;
 14using Tags = System.Collections.Generic.IDictionary<string, string>;
 15
 16#pragma warning disable SA1402  // File may only contain a single type
 17
 18namespace Azure.Storage.Blobs.Specialized
 19{
 20    /// <summary>
 21    /// The <see cref="PageBlobClient"/> allows you to manipulate Azure
 22    /// Storage page blobs.
 23    ///
 24    /// Page blobs are a collection of 512-byte pages optimized for random
 25    /// read and write operations. To create a page blob, you initialize the
 26    /// page blob and specify the maximum size the page blob will grow. To add
 27    /// or update the contents of a page blob, you write a page or pages by
 28    /// specifying an offset and a range that align to 512-byte page
 29    /// boundaries.  A write to a page blob can overwrite just one page, some
 30    /// pages, or up to 4 MB of the page blob.  Writes to page blobs happen
 31    /// in-place and are immediately committed to the blob. The maximum size
 32    /// for a page blob is 8 TB.
 33    /// </summary>
 34    public class PageBlobClient : BlobBaseClient
 35    {
 36        /// <summary>
 37        /// Gets the number of bytes in a page (512).
 38        /// </summary>
 039    public virtual int PageBlobPageBytes => 512;
 40
 41        /// <summary>
 42        /// Gets the maximum number of bytes that can be sent in a call
 43        /// to the <see cref="UploadPagesAsync"/> operation.
 44        /// </summary>
 045        public virtual int PageBlobMaxUploadPagesBytes => 4 * Constants.MB; // 4MB
 46
 47        #region ctors
 48        /// <summary>
 49        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 50        /// class for mocking.
 51        /// </summary>
 107252        protected PageBlobClient()
 53        {
 107254        }
 55
 56        /// <summary>
 57        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 58        /// class.
 59        /// </summary>
 60        /// <param name="connectionString">
 61        /// A connection string includes the authentication information
 62        /// required for your application to access data in an Azure Storage
 63        /// account at runtime.
 64        ///
 65        /// For more information
 66        /// <see href="https://docs.microsoft.com/azure/storage/common/storage-configure-connection-string">
 67        /// Configure Azure Storage connection strings</see>
 68        /// </param>
 69        /// <param name="blobContainerName">
 70        /// The name of the container containing this page blob.
 71        /// </param>
 72        /// <param name="blobName">
 73        /// The name of this page blob.
 74        /// </param>
 75        public PageBlobClient(string connectionString, string blobContainerName, string blobName)
 076            : base(connectionString, blobContainerName, blobName)
 77        {
 078        }
 79
 80        /// <summary>
 81        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 82        /// class.
 83        /// </summary>
 84        /// <param name="connectionString">
 85        /// A connection string includes the authentication information
 86        /// required for your application to access data in an Azure Storage
 87        /// account at runtime.
 88        ///
 89        /// For more information,
 90        /// <see href="https://docs.microsoft.com/azure/storage/common/storage-configure-connection-string">
 91        /// Configure Azure Storage connection strings</see>
 92        /// </param>
 93        /// <param name="blobContainerName">
 94        /// The name of the container containing this page blob.
 95        /// </param>
 96        /// <param name="blobName">
 97        /// The name of this page blob.
 98        /// </param>
 99        /// <param name="options">
 100        /// Optional client options that define the transport pipeline
 101        /// policies for authentication, retries, etc., that are applied to
 102        /// every request.
 103        /// </param>
 104        public PageBlobClient(string connectionString, string blobContainerName, string blobName, BlobClientOptions opti
 20105            : base(connectionString, blobContainerName, blobName, options)
 106        {
 20107            AssertNoClientSideEncryption(options);
 20108        }
 109
 110        /// <summary>
 111        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 112        /// class.
 113        /// </summary>
 114        /// <param name="blobUri">
 115        /// A <see cref="Uri"/> referencing the page blob that includes the
 116        /// name of the account, the name of the blob container, and the name of
 117        /// the blob.
 118        /// </param>
 119        /// <param name="options">
 120        /// Optional client options that define the transport pipeline
 121        /// policies for authentication, retries, etc., that are applied to
 122        /// every request.
 123        /// </param>
 124        public PageBlobClient(Uri blobUri, BlobClientOptions options = default)
 16125            : base(blobUri, options)
 126        {
 12127            AssertNoClientSideEncryption(options);
 12128        }
 129
 130        /// <summary>
 131        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 132        /// class.
 133        /// </summary>
 134        /// <param name="blobUri">
 135        /// A <see cref="Uri"/> referencing the page blob that includes the
 136        /// name of the account, the name of the blob container, and the name of
 137        /// the blob.
 138        /// </param>
 139        /// <param name="credential">
 140        /// The shared key credential used to sign requests.
 141        /// </param>
 142        /// <param name="options">
 143        /// Optional client options that define the transport pipeline
 144        /// policies for authentication, retries, etc., that are applied to
 145        /// every request.
 146        /// </param>
 147        public PageBlobClient(Uri blobUri, StorageSharedKeyCredential credential, BlobClientOptions options = default)
 0148            : base(blobUri, credential, options)
 149        {
 0150            AssertNoClientSideEncryption(options);
 0151        }
 152
 153        /// <summary>
 154        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 155        /// class.
 156        /// </summary>
 157        /// <param name="blobUri">
 158        /// A <see cref="Uri"/> referencing the page blob that includes the
 159        /// name of the account, the name of the blob container, and the name of
 160        /// the blob.
 161        /// </param>
 162        /// <param name="credential">
 163        /// The token credential used to sign requests.
 164        /// </param>
 165        /// <param name="options">
 166        /// Optional client options that define the transport pipeline
 167        /// policies for authentication, retries, etc., that are applied to
 168        /// every request.
 169        /// </param>
 170        public PageBlobClient(Uri blobUri, TokenCredential credential, BlobClientOptions options = default)
 4171            : base(blobUri, credential, options)
 172        {
 0173            AssertNoClientSideEncryption(options);
 0174        }
 175
 176        /// <summary>
 177        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 178        /// class.
 179        /// </summary>
 180        /// <param name="blobUri">
 181        /// A <see cref="Uri"/> referencing the page blob that includes the
 182        /// name of the account, the name of the blob container, and the name of
 183        /// the blob.
 184        /// </param>
 185        /// <param name="pipeline">
 186        /// The transport pipeline used to send every request.
 187        /// </param>
 188        /// <param name="version">
 189        /// The version of the service to use when sending requests.
 190        /// </param>
 191        /// <param name="clientDiagnostics">Client diagnostics.</param>
 192        /// <param name="customerProvidedKey">Customer provided key.</param>
 193        /// <param name="encryptionScope">Encryption scope.</param>
 194        internal PageBlobClient(
 195            Uri blobUri,
 196            HttpPipeline pipeline,
 197            BlobClientOptions.ServiceVersion version,
 198            ClientDiagnostics clientDiagnostics,
 199            CustomerProvidedKey? customerProvidedKey,
 200            string encryptionScope)
 1308201            : base(
 1308202                  blobUri,
 1308203                  pipeline,
 1308204                  version,
 1308205                  clientDiagnostics,
 1308206                  customerProvidedKey,
 1308207                  clientSideEncryption: default,
 1308208                  encryptionScope)
 209        {
 1308210        }
 211
 212        private static void AssertNoClientSideEncryption(BlobClientOptions options)
 213        {
 32214            if (options?._clientSideEncryptionOptions != default)
 215            {
 0216                throw Errors.ClientSideEncryption.TypeNotSupported(typeof(PageBlobClient));
 217            }
 32218        }
 219        #endregion ctors
 220
 221        /// <summary>
 222        /// Initializes a new instance of the <see cref="PageBlobClient"/>
 223        /// class with an identical <see cref="Uri"/> source but the specified
 224        /// snapshot timestamp.
 225        ///
 226        /// For more information, see
 227        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 228        /// Create a snapshot of a blob</see>.
 229        /// </summary>
 230        /// <param name="snapshot">The snapshot identifier.</param>
 231        /// <returns>A new <see cref="PageBlobClient"/> instance.</returns>
 232        /// <remarks>
 233        /// Pass null or empty string to remove the snapshot returning a URL
 234        /// to the base blob.
 235        /// </remarks>
 116236        public new PageBlobClient WithSnapshot(string snapshot) => (PageBlobClient)WithSnapshotCore(snapshot);
 237
 238        /// <summary>
 239        /// Creates a new instance of the <see cref="PageBlobClient"/> class
 240        /// with an identical <see cref="Uri"/> source but the specified
 241        /// snapshot timestamp.
 242        /// </summary>
 243        /// <param name="snapshot">The snapshot identifier.</param>
 244        /// <returns>A new <see cref="PageBlobClient"/> instance.</returns>
 245        protected sealed override BlobBaseClient WithSnapshotCore(string snapshot)
 246        {
 116247            var builder = new BlobUriBuilder(Uri)
 116248            {
 116249                Snapshot = snapshot
 116250            };
 251
 116252            return new PageBlobClient(
 116253                builder.ToUri(),
 116254                Pipeline,
 116255                Version,
 116256                ClientDiagnostics,
 116257                CustomerProvidedKey,
 116258                EncryptionScope);
 259        }
 260
 261        /// <summary>
 262        /// Creates a new PageBlobClient object identical to the source but with the specified version ID.
 263        /// Pass "" to remove the version ID returning a URL to the base blob.
 264        /// </summary>
 265        /// <param name="versionId">version ID</param>
 266        /// <returns></returns>
 267        public new PageBlobClient WithVersion(string versionId)
 268        {
 4269            var builder = new BlobUriBuilder(Uri)
 4270            {
 4271                VersionId = versionId
 4272            };
 273
 4274            return new PageBlobClient(
 4275                builder.ToUri(), Pipeline,
 4276                Version,
 4277                ClientDiagnostics,
 4278                CustomerProvidedKey,
 4279                EncryptionScope);
 280        }
 281
 282        #region Create
 283        /// <summary>
 284        /// The <see cref="Create(long, PageBlobCreateOptions, CancellationToken)"/>
 285        /// operation creates a new page blob of the specified <paramref name="size"/>.
 286        /// The content of any existing blob is overwritten with the newly initialized page blob
 287        /// To add content to the page blob, call the
 288        /// <see cref="UploadPages"/> operation.
 289        ///
 290        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 291        /// </summary>
 292        /// <param name="size">
 293        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 294        /// size must be aligned to a 512-byte boundary.
 295        /// </param>
 296        /// <param name="options">
 297        /// Optional parameters.
 298        /// </param>
 299        /// <param name="cancellationToken">
 300        /// Optional <see cref="CancellationToken"/> to propagate
 301        /// notifications that the operation should be cancelled.
 302        /// </param>
 303        /// <returns>
 304        /// A <see cref="Response{BlobContentInfo}"/> describing the
 305        /// newly created page blob.
 306        /// </returns>
 307        /// <remarks>
 308        /// A <see cref="RequestFailedException"/> will be thrown if
 309        /// a failure occurs.
 310        /// </remarks>
 311        public virtual Response<BlobContentInfo> Create(
 312            long size,
 313            PageBlobCreateOptions options,
 314            CancellationToken cancellationToken = default) =>
 2315            CreateInternal(
 2316                size,
 2317                options?.SequenceNumber,
 2318                options?.HttpHeaders,
 2319                options?.Metadata,
 2320                options?.Tags,
 2321                options?.Conditions,
 2322                async: false,
 2323                cancellationToken)
 2324            .EnsureCompleted();
 325
 326        /// <summary>
 327        /// The <see cref="CreateAsync(long, PageBlobCreateOptions, CancellationToken)"/>
 328        /// operation creates a new page blob of the specified <paramref name="size"/>.
 329        /// The content of any existing blob is overwritten with the newly initialized page blob
 330        /// To add content to the page blob, call the
 331        /// <see cref="UploadPages"/> operation.
 332        ///
 333        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 334        /// </summary>
 335        /// <param name="size">
 336        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 337        /// size must be aligned to a 512-byte boundary.
 338        /// </param>
 339        /// <param name="options">
 340        /// Optional parameters.
 341        /// </param>
 342        /// <param name="cancellationToken">
 343        /// Optional <see cref="CancellationToken"/> to propagate
 344        /// notifications that the operation should be cancelled.
 345        /// </param>
 346        /// <returns>
 347        /// A <see cref="Response{BlobContentInfo}"/> describing the
 348        /// newly created page blob.
 349        /// </returns>
 350        /// <remarks>
 351        /// A <see cref="RequestFailedException"/> will be thrown if
 352        /// a failure occurs.
 353        /// </remarks>
 354        public virtual async Task<Response<BlobContentInfo>> CreateAsync(
 355            long size,
 356            PageBlobCreateOptions options,
 357            CancellationToken cancellationToken = default) =>
 2358            await CreateInternal(
 2359                size,
 2360                options?.SequenceNumber,
 2361                options?.HttpHeaders,
 2362                options?.Metadata,
 2363                options?.Tags,
 2364                options?.Conditions,
 2365                async: true,
 2366                cancellationToken)
 2367            .ConfigureAwait(false);
 368
 369        /// <summary>
 370        /// The <see cref="Create(long, long?, BlobHttpHeaders, Metadata, PageBlobRequestConditions, CancellationToken)"
 371        /// operation creates a new page blob of the specified <paramref name="size"/>.  The content of any
 372        /// existing blob is overwritten with the newly initialized page blob
 373        /// To add content to the page blob, call the
 374        /// <see cref="UploadPages"/> operation.
 375        ///
 376        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 377        /// </summary>
 378        /// <param name="size">
 379        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 380        /// size must be aligned to a 512-byte boundary.
 381        /// </param>
 382        /// <param name="sequenceNumber">
 383        /// Optional user-controlled value that you can use to track requests.
 384        /// The value of the <paramref name="sequenceNumber"/> must be between
 385        /// 0 and 2^63 - 1.  The default value is 0.
 386        /// </param>
 387        /// <param name="httpHeaders">
 388        /// Optional standard HTTP header properties that can be set for the
 389        /// new page blob.
 390        /// </param>
 391        /// <param name="metadata">
 392        /// Optional custom metadata to set for this page blob.
 393        /// </param>
 394        /// <param name="conditions">
 395        /// Optional <see cref="PageBlobRequestConditions"/> to add
 396        /// conditions on the creation of this new page blob.
 397        /// </param>
 398        /// <param name="cancellationToken">
 399        /// Optional <see cref="CancellationToken"/> to propagate
 400        /// notifications that the operation should be cancelled.
 401        /// </param>
 402        /// <returns>
 403        /// A <see cref="Response{BlobContentInfo}"/> describing the
 404        /// newly created page blob.
 405        /// </returns>
 406        /// <remarks>
 407        /// A <see cref="RequestFailedException"/> will be thrown if
 408        /// a failure occurs.
 409        /// </remarks>
 410        [EditorBrowsable(EditorBrowsableState.Never)]
 411        public virtual Response<BlobContentInfo> Create(
 412            long size,
 413            long? sequenceNumber = default,
 414            BlobHttpHeaders httpHeaders = default,
 415            Metadata metadata = default,
 416            PageBlobRequestConditions conditions = default,
 417            CancellationToken cancellationToken = default) =>
 490418            CreateInternal(
 490419                size,
 490420                sequenceNumber,
 490421                httpHeaders,
 490422                metadata,
 490423                default,
 490424                conditions,
 490425                false, // async
 490426                cancellationToken)
 490427                .EnsureCompleted();
 428
 429        /// <summary>
 430        /// The <see cref="CreateAsync(long, long?, BlobHttpHeaders, Metadata, PageBlobRequestConditions, CancellationTo
 431        /// operation creates a new page blob of the specified <paramref name="size"/>.  The content of any
 432        /// existing blob is overwritten with the newly initialized page blob
 433        /// To add content to the page blob, call the
 434        /// <see cref="UploadPagesAsync"/> operation.
 435        ///
 436        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 437        /// </summary>
 438        /// <param name="size">
 439        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 440        /// size must be aligned to a 512-byte boundary.
 441        /// </param>
 442        /// <param name="sequenceNumber">
 443        /// Optional user-controlled value that you can use to track requests.
 444        /// The value of the <paramref name="sequenceNumber"/> must be between
 445        /// 0 and 2^63 - 1.  The default value is 0.
 446        /// </param>
 447        /// <param name="httpHeaders">
 448        /// Optional standard HTTP header properties that can be set for the
 449        /// new page blob.
 450        /// </param>
 451        /// <param name="metadata">
 452        /// Optional custom metadata to set for this page blob.
 453        /// </param>
 454        /// <param name="conditions">
 455        /// Optional <see cref="PageBlobRequestConditions"/> to add
 456        /// conditions on the creation of this new page blob.
 457        /// </param>
 458        /// <param name="cancellationToken">
 459        /// Optional <see cref="CancellationToken"/> to propagate
 460        /// notifications that the operation should be cancelled.
 461        /// </param>
 462        /// <returns>
 463        /// A <see cref="Response{BlobContentInfo}"/> describing the
 464        /// newly created page blob.
 465        /// </returns>
 466        /// <remarks>
 467        /// A <see cref="RequestFailedException"/> will be thrown if
 468        /// a failure occurs.
 469        /// </remarks>
 470        [EditorBrowsable(EditorBrowsableState.Never)]
 471        public virtual async Task<Response<BlobContentInfo>> CreateAsync(
 472            long size,
 473            long? sequenceNumber = default,
 474            BlobHttpHeaders httpHeaders = default,
 475            Metadata metadata = default,
 476            PageBlobRequestConditions conditions = default,
 477            CancellationToken cancellationToken = default) =>
 498478            await CreateInternal(
 498479                size,
 498480                sequenceNumber,
 498481                httpHeaders,
 498482                metadata,
 498483                default,
 498484                conditions,
 498485                true, // async
 498486                cancellationToken)
 498487                .ConfigureAwait(false);
 488
 489        /// <summary>
 490        /// The <see cref="CreateIfNotExists(long, PageBlobCreateOptions, CancellationToken)"/>
 491        /// operation creates a new page blob of the specified <paramref name="size"/>.  If the blob already
 492        /// exists, the content of the existing blob will remain unchanged. If the blob does not already exists,
 493        /// a new page blob with the specified <paramref name="size"/> will be created.
 494        /// <see cref="UploadPages"/> operation.
 495        ///
 496        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 497        /// </summary>
 498        /// <param name="size">
 499        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 500        /// size must be aligned to a 512-byte boundary.
 501        /// </param>
 502        /// <param name="options">
 503        /// Optional parameters.
 504        /// </param>
 505        /// /// <param name="cancellationToken">
 506        /// Optional <see cref="CancellationToken"/> to propagate
 507        /// notifications that the operation should be cancelled.
 508        /// </param>
 509        /// <returns>
 510        /// If the page blob does not already exist, A <see cref="Response{BlobContentInfo}"/>
 511        /// describing the newly created page blob. Otherwise, <c>null</c>.
 512        /// </returns>
 513        /// <remarks>
 514        /// A <see cref="RequestFailedException"/> will be thrown if
 515        /// a failure occurs.
 516        /// </remarks>
 517        public virtual Response<BlobContentInfo> CreateIfNotExists(
 518            long size,
 519            PageBlobCreateOptions options,
 520            CancellationToken cancellationToken = default) =>
 0521            CreateIfNotExistsInternal(
 0522                size,
 0523                options?.SequenceNumber,
 0524                options?.HttpHeaders,
 0525                options?.Metadata,
 0526                options?.Tags,
 0527                false, // async
 0528                cancellationToken)
 0529                .EnsureCompleted();
 530
 531        /// <summary>
 532        /// The <see cref="CreateIfNotExistsAsync(long, PageBlobCreateOptions, CancellationToken)"/>
 533        /// operation creates a new page blob of the specified <paramref name="size"/>.  If the blob already
 534        /// exists, the content of the existing blob will remain unchanged. If the blob does not already exists,
 535        /// a new page blob with the specified <paramref name="size"/> will be created.
 536        /// <see cref="UploadPages"/> operation.
 537        ///
 538        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 539        /// </summary>
 540        /// <param name="size">
 541        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 542        /// size must be aligned to a 512-byte boundary.
 543        /// </param>
 544        /// <param name="options">
 545        /// Optional parameters.
 546        /// </param>
 547        /// /// <param name="cancellationToken">
 548        /// Optional <see cref="CancellationToken"/> to propagate
 549        /// notifications that the operation should be cancelled.
 550        /// </param>
 551        /// <returns>
 552        /// If the page blob does not already exist, A <see cref="Response{BlobContentInfo}"/>
 553        /// describing the newly created page blob. Otherwise, <c>null</c>.
 554        /// </returns>
 555        /// <remarks>
 556        /// A <see cref="RequestFailedException"/> will be thrown if
 557        /// a failure occurs.
 558        /// </remarks>
 559        public virtual async Task<Response<BlobContentInfo>> CreateIfNotExistsAsync(
 560            long size,
 561            PageBlobCreateOptions options,
 562            CancellationToken cancellationToken = default) =>
 0563            await CreateIfNotExistsInternal(
 0564                size,
 0565                options?.SequenceNumber,
 0566                options?.HttpHeaders,
 0567                options?.Metadata,
 0568                options?.Tags,
 0569                true, // async
 0570                cancellationToken)
 0571                .ConfigureAwait(false);
 572
 573        /// <summary>
 574        /// The <see cref="CreateIfNotExists(long, long?, BlobHttpHeaders, Metadata, CancellationToken)"/>
 575        /// operation creates a new page blob of the specified <paramref name="size"/>.  If the blob already
 576        /// exists, the content of the existing blob will remain unchanged. If the blob does not already exists,
 577        /// a new page blob with the specified <paramref name="size"/> will be created.
 578        /// <see cref="UploadPages"/> operation.
 579        ///
 580        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 581        /// </summary>
 582        /// <param name="size">
 583        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 584        /// size must be aligned to a 512-byte boundary.
 585        /// </param>
 586        /// <param name="sequenceNumber">
 587        /// Optional user-controlled value that you can use to track requests.
 588        /// The value of the <paramref name="sequenceNumber"/> must be between
 589        /// 0 and 2^63 - 1.  The default value is 0.
 590        /// </param>
 591        /// <param name="httpHeaders">
 592        /// Optional standard HTTP header properties that can be set for the
 593        /// new page blob.
 594        /// </param>
 595        /// <param name="metadata">
 596        /// Optional custom metadata to set for this page blob.
 597        /// </param>
 598        /// /// <param name="cancellationToken">
 599        /// Optional <see cref="CancellationToken"/> to propagate
 600        /// notifications that the operation should be cancelled.
 601        /// </param>
 602        /// <returns>
 603        /// If the page blob does not already exist, A <see cref="Response{BlobContentInfo}"/>
 604        /// describing the newly created page blob. Otherwise, <c>null</c>.
 605        /// </returns>
 606        /// <remarks>
 607        /// A <see cref="RequestFailedException"/> will be thrown if
 608        /// a failure occurs.
 609        /// </remarks>
 610        [EditorBrowsable(EditorBrowsableState.Never)]
 611        public virtual Response<BlobContentInfo> CreateIfNotExists(
 612            long size,
 613            long? sequenceNumber = default,
 614            BlobHttpHeaders httpHeaders = default,
 615            Metadata metadata = default,
 616            CancellationToken cancellationToken = default) =>
 6617            CreateIfNotExistsInternal(
 6618                size,
 6619                sequenceNumber,
 6620                httpHeaders,
 6621                metadata,
 6622                default,
 6623                false, // async
 6624                cancellationToken)
 6625                .EnsureCompleted();
 626
 627        /// <summary>
 628        /// The <see cref="CreateIfNotExistsAsync(long, long?, BlobHttpHeaders, Metadata, CancellationToken)"/>
 629        /// operation creates a new page blob of the specified <paramref name="size"/>.  If the blob already exists,
 630        /// the content of the existing blob will remain unchanged. If the blob does not already exists,
 631        /// a new page blob with the specified <paramref name="size"/> will be created.
 632        /// <see cref="UploadPagesAsync"/> operation.
 633        ///
 634        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 635        /// </summary>
 636        /// <param name="size">
 637        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 638        /// size must be aligned to a 512-byte boundary.
 639        /// </param>
 640        /// <param name="sequenceNumber">
 641        /// Optional user-controlled value that you can use to track requests.
 642        /// The value of the <paramref name="sequenceNumber"/> must be between
 643        /// 0 and 2^63 - 1.  The default value is 0.
 644        /// </param>
 645        /// <param name="httpHeaders">
 646        /// Optional standard HTTP header properties that can be set for the
 647        /// new page blob.
 648        /// </param>
 649        /// <param name="metadata">
 650        /// Optional custom metadata to set for this page blob.
 651        /// </param>
 652        /// <param name="cancellationToken">
 653        /// Optional <see cref="CancellationToken"/> to propagate
 654        /// notifications that the operation should be cancelled.
 655        /// </param>
 656        /// <returns>
 657        /// If the page blob does not already exist, A <see cref="Response{BlobContentInfo}"/>
 658        /// describing the newly created page blob. Otherwise, <c>null</c>.
 659        /// </returns>
 660        /// <remarks>
 661        /// A <see cref="RequestFailedException"/> will be thrown if
 662        /// a failure occurs.
 663        /// </remarks>
 664        [EditorBrowsable(EditorBrowsableState.Never)]
 665        public virtual async Task<Response<BlobContentInfo>> CreateIfNotExistsAsync(
 666            long size,
 667            long? sequenceNumber = default,
 668            BlobHttpHeaders httpHeaders = default,
 669            Metadata metadata = default,
 670            CancellationToken cancellationToken = default) =>
 6671            await CreateIfNotExistsInternal(
 6672                size,
 6673                sequenceNumber,
 6674                httpHeaders,
 6675                metadata,
 6676                default,
 6677                true, // async
 6678                cancellationToken)
 6679                .ConfigureAwait(false);
 680
 681        /// <summary>
 682        /// The <see cref="CreateIfNotExistsInternal"/> operation creates a new page blob
 683        /// of the specified <paramref name="size"/>.  If the blob already exists, the content of
 684        /// the existing blob will remain unchanged. If the blob does not already exists,
 685        /// a new page blob with the specified <paramref name="size"/> will be created.
 686        /// To add content to the page blob, call the
 687        /// <see cref="UploadPagesAsync"/> operation.
 688        ///
 689        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 690        /// </summary>
 691        /// <param name="size">
 692        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 693        /// size must be aligned to a 512-byte boundary.
 694        /// </param>
 695        /// <param name="sequenceNumber">
 696        /// Optional user-controlled value that you can use to track requests.
 697        /// The value of the <paramref name="sequenceNumber"/> must be between
 698        /// 0 and 2^63 - 1.  The default value is 0.
 699        /// </param>
 700        /// <param name="httpHeaders">
 701        /// Optional standard HTTP header properties that can be set for the
 702        /// new page blob.
 703        /// </param>
 704        /// <param name="metadata">
 705        /// Optional custom metadata to set for this page blob.
 706        /// </param>
 707        /// <param name="tags">
 708        /// Optional tags to set for this page blob.
 709        /// </param>
 710        /// <param name="async">
 711        /// Whether to invoke the operation asynchronously.
 712        /// </param>
 713        /// <param name="cancellationToken">
 714        /// Optional <see cref="CancellationToken"/> to propagate
 715        /// notifications that the operation should be cancelled.
 716        /// </param>
 717        /// <returns>
 718        /// If the page blob does not already exist, A <see cref="Response{BlobContentInfo}"/>
 719        /// describing the newly created page blob. Otherwise, <c>null</c>.
 720        /// </returns>
 721        /// <remarks>
 722        /// A <see cref="RequestFailedException"/> will be thrown if
 723        /// a failure occurs.
 724        /// </remarks>
 725        private async Task<Response<BlobContentInfo>> CreateIfNotExistsInternal(
 726            long size,
 727            long? sequenceNumber,
 728            BlobHttpHeaders httpHeaders,
 729            Metadata metadata,
 730            Tags tags,
 731            bool async,
 732            CancellationToken cancellationToken)
 733        {
 12734            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 735            {
 736                Pipeline.LogMethodEnter(
 737                    nameof(PageBlobClient),
 738                    message:
 739                    $"{nameof(Uri)}: {Uri}\n" +
 740                    $"{nameof(size)}: {size}\n" +
 741                    $"{nameof(sequenceNumber)}: {sequenceNumber}\n" +
 742                    $"{nameof(httpHeaders)}: {httpHeaders}");
 12743                var conditions = new PageBlobRequestConditions { IfNoneMatch = new ETag(Constants.Wildcard) };
 744                try
 745                {
 12746                    return await CreateInternal(
 12747                        size,
 12748                        sequenceNumber,
 12749                        httpHeaders,
 12750                        metadata,
 12751                        tags,
 12752                        conditions,
 12753                        async,
 12754                        cancellationToken,
 12755                        $"{nameof(PageBlobClient)}.{nameof(CreateIfNotExists)}")
 12756                        .ConfigureAwait(false);
 757                }
 758                catch (RequestFailedException storageRequestFailedException)
 8759                when (storageRequestFailedException.ErrorCode == BlobErrorCode.BlobAlreadyExists)
 760                {
 4761                    return default;
 762                }
 4763                catch (Exception ex)
 764                {
 765                    Pipeline.LogException(ex);
 4766                    throw;
 767                }
 768                finally
 769                {
 770                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 771                }
 772            }
 8773        }
 774
 775        /// <summary>
 776        /// The <see cref="CreateInternal"/> operation creates a new page blob
 777        /// of the specified <paramref name="size"/>.  The content of any
 778        /// existing blob is overwritten with the newly initialized page blob
 779        /// To add content to the page blob, call the
 780        /// <see cref="UploadPagesAsync"/> operation.
 781        ///
 782        /// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-blob.
 783        /// </summary>
 784        /// <param name="size">
 785        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 786        /// size must be aligned to a 512-byte boundary.
 787        /// </param>
 788        /// <param name="sequenceNumber">
 789        /// Optional user-controlled value that you can use to track requests.
 790        /// The value of the <paramref name="sequenceNumber"/> must be between
 791        /// 0 and 2^63 - 1.  The default value is 0.
 792        /// </param>
 793        /// <param name="httpHeaders">
 794        /// Optional standard HTTP header properties that can be set for the
 795        /// new page blob.
 796        /// </param>
 797        /// <param name="metadata">
 798        /// Optional custom metadata to set for this page blob.
 799        /// </param>
 800        /// <param name="tags">
 801        /// Optional tags to set for this page blob.
 802        /// </param>
 803        /// <param name="conditions">
 804        /// Optional <see cref="PageBlobRequestConditions"/> to add
 805        /// conditions on the creation of this new page blob.
 806        /// </param>
 807        /// <param name="async">
 808        /// Whether to invoke the operation asynchronously.
 809        /// </param>
 810        /// <param name="cancellationToken">
 811        /// Optional <see cref="CancellationToken"/> to propagate
 812        /// notifications that the operation should be cancelled.
 813        /// </param>
 814        /// <param name="operationName">
 815        /// Optional. To indicate if the name of the operation.
 816        /// </param>
 817        /// <returns>
 818        /// A <see cref="Response{BlobContentInfo}"/> describing the
 819        /// newly created page blob.
 820        /// </returns>
 821        /// <remarks>
 822        /// A <see cref="RequestFailedException"/> will be thrown if
 823        /// a failure occurs.
 824        /// </remarks>
 825        private async Task<Response<BlobContentInfo>> CreateInternal(
 826            long size,
 827            long? sequenceNumber,
 828            BlobHttpHeaders httpHeaders,
 829            Metadata metadata,
 830            Tags tags,
 831            PageBlobRequestConditions conditions,
 832            bool async,
 833            CancellationToken cancellationToken,
 834            string operationName = null)
 835        {
 1004836            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 837            {
 838                Pipeline.LogMethodEnter(
 839                    nameof(PageBlobClient),
 840                    message:
 841                    $"{nameof(Uri)}: {Uri}\n" +
 842                    $"{nameof(size)}: {size}\n" +
 843                    $"{nameof(sequenceNumber)}: {sequenceNumber}\n" +
 844                    $"{nameof(httpHeaders)}: {httpHeaders}");
 845                try
 846                {
 1004847                    return await BlobRestClient.PageBlob.CreateAsync(
 1004848                        ClientDiagnostics,
 1004849                        Pipeline,
 1004850                        Uri,
 1004851                        version: Version.ToVersionString(),
 1004852                        contentLength: default,
 1004853                        blobContentType: httpHeaders?.ContentType,
 1004854                        blobContentEncoding: httpHeaders?.ContentEncoding,
 1004855                        blobContentLanguage: httpHeaders?.ContentLanguage,
 1004856                        blobContentHash: httpHeaders?.ContentHash,
 1004857                        blobCacheControl: httpHeaders?.CacheControl,
 1004858                        metadata: metadata,
 1004859                        leaseId: conditions?.LeaseId,
 1004860                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 1004861                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 1004862                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 1004863                        encryptionScope: EncryptionScope,
 1004864                        blobContentDisposition: httpHeaders?.ContentDisposition,
 1004865                        ifModifiedSince: conditions?.IfModifiedSince,
 1004866                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1004867                        ifMatch: conditions?.IfMatch,
 1004868                        ifNoneMatch: conditions?.IfNoneMatch,
 1004869                        ifTags: conditions?.TagConditions,
 1004870                        blobContentLength: size,
 1004871                        blobSequenceNumber: sequenceNumber,
 1004872                        blobTagsString: tags?.ToTagsString(),
 1004873                        async: async,
 1004874                        operationName: operationName ?? $"{nameof(PageBlobClient)}.{nameof(Create)}",
 1004875                        cancellationToken: cancellationToken)
 1004876                        .ConfigureAwait(false);
 877                }
 36878                catch (Exception ex)
 879                {
 880                    Pipeline.LogException(ex);
 36881                    throw;
 882                }
 883                finally
 884                {
 885                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 886                }
 887            }
 968888        }
 889        #endregion Create
 890
 891        #region UploadPages
 892        /// <summary>
 893        /// The <see cref="UploadPages"/> operation writes
 894        /// <paramref name="content"/> to a range of pages in a page blob,
 895        /// starting at <paramref name="offset"/>.
 896        ///
 897        /// For more information, see
 898        /// <see href="https://docs.microsoft.com/rest/api/storageservices/put-page">
 899        /// Put Page</see>.
 900        /// </summary>
 901        /// <param name="content">
 902        /// A <see cref="Stream"/> containing the content of the pages to
 903        /// upload.  The content can be up to 4 MB in size.
 904        /// </param>
 905        /// <param name="offset">
 906        /// Specifies the starting offset for the <paramref name="content"/>
 907        /// to be written as a page.  Given that pages must be aligned with
 908        /// 512-byte boundaries, the start offset must be a modulus of 512.
 909        /// </param>
 910        /// <param name="transactionalContentHash">
 911        /// Optional MD5 hash of the block content.  This hash is used to
 912        /// verify the integrity of the block during transport. When this hash
 913        /// is specified, the storage service compares the hash of the content
 914        /// that has arrived with this value.  Note that this MD5 hash is not
 915        /// stored with the blob.  If the two hashes do not match, the
 916        /// operation will fail with a <see cref="RequestFailedException"/>.
 917        /// </param>
 918        /// <param name="conditions">
 919        /// Optional <see cref="PageBlobRequestConditions"/> to add
 920        /// conditions on uploading pages to this page blob.
 921        /// </param>
 922        /// <param name="progressHandler">
 923        /// Optional <see cref="IProgress{Long}"/> to provide
 924        /// progress updates about data transfers.
 925        /// </param>
 926        /// <param name="cancellationToken">
 927        /// Optional <see cref="CancellationToken"/> to propagate
 928        /// notifications that the operation should be cancelled.
 929        /// </param>
 930        /// <returns>
 931        /// A <see cref="Response{PageInfo}"/> describing the
 932        /// state of the updated pages.
 933        /// </returns>
 934        /// <remarks>
 935        /// A <see cref="RequestFailedException"/> will be thrown if
 936        /// a failure occurs.
 937        /// </remarks>
 938        public virtual Response<PageInfo> UploadPages(
 939            Stream content,
 940            long offset,
 941            byte[] transactionalContentHash = default,
 942            PageBlobRequestConditions conditions = default,
 943            IProgress<long> progressHandler = default,
 944            CancellationToken cancellationToken = default) =>
 278945            UploadPagesInternal(
 278946                content,
 278947                offset,
 278948                transactionalContentHash,
 278949                conditions,
 278950                progressHandler,
 278951                false, // async
 278952                cancellationToken)
 278953                .EnsureCompleted();
 954
 955        /// <summary>
 956        /// The <see cref="UploadPagesAsync"/> operation writes
 957        /// <paramref name="content"/> to a range of pages in a page blob,
 958        /// starting at <paramref name="offset"/>.
 959        ///
 960        /// For more information, see
 961        /// <see href="https://docs.microsoft.com/rest/api/storageservices/put-page">
 962        /// Put Page</see>.
 963        /// </summary>
 964        /// <param name="content">
 965        /// A <see cref="Stream"/> containing the content of the pages to
 966        /// upload.  The content can be up to 4 MB in size.
 967        /// </param>
 968        /// <param name="offset">
 969        /// Specifies the starting offset for the <paramref name="content"/>
 970        /// to be written as a page.  Given that pages must be aligned with
 971        /// 512-byte boundaries, the start offset must be a modulus of 512.
 972        /// </param>
 973        /// <param name="transactionalContentHash">
 974        /// Optional MD5 hash of the block content.  This hash is used to
 975        /// verify the integrity of the block during transport. When this hash
 976        /// is specified, the storage service compares the hash of the content
 977        /// that has arrived with this value.  Note that this MD5 hash is not
 978        /// stored with the blob.  If the two hashes do not match, the
 979        /// operation will fail with a <see cref="RequestFailedException"/>.
 980        /// </param>
 981        /// <param name="conditions">
 982        /// Optional <see cref="PageBlobRequestConditions"/> to add
 983        /// conditions on uploading pages to this page blob.
 984        /// </param>
 985        /// <param name="progressHandler">
 986        /// Optional <see cref="IProgress{Long}"/> to provide
 987        /// progress updates about data transfers.
 988        /// </param>
 989        /// <param name="cancellationToken">
 990        /// Optional <see cref="CancellationToken"/> to propagate
 991        /// notifications that the operation should be cancelled.
 992        /// </param>
 993        /// <returns>
 994        /// A <see cref="Response{PageInfo}"/> describing the
 995        /// state of the updated pages.
 996        /// </returns>
 997        /// <remarks>
 998        /// A <see cref="RequestFailedException"/> will be thrown if
 999        /// a failure occurs.
 1000        /// </remarks>
 1001        public virtual async Task<Response<PageInfo>> UploadPagesAsync(
 1002            Stream content,
 1003            long offset,
 1004            byte[] transactionalContentHash = default,
 1005            PageBlobRequestConditions conditions = default,
 1006            IProgress<long> progressHandler = default,
 1007            CancellationToken cancellationToken = default) =>
 2781008            await UploadPagesInternal(
 2781009                content,
 2781010                offset,
 2781011                transactionalContentHash,
 2781012                conditions,
 2781013                progressHandler,
 2781014                true, // async
 2781015                cancellationToken)
 2781016                .ConfigureAwait(false);
 1017
 1018        /// <summary>
 1019        /// The <see cref="UploadPagesInternal"/> operation writes
 1020        /// <paramref name="content"/> to a range of pages in a page blob,
 1021        /// starting at <paramref name="offset"/>.
 1022        ///
 1023        /// For more information, see
 1024        /// <see href="https://docs.microsoft.com/rest/api/storageservices/put-page">
 1025        /// Put Page</see>.
 1026        /// </summary>
 1027        /// <param name="content">
 1028        /// A <see cref="Stream"/> containing the content of the pages to
 1029        /// upload.  The content can be up to 4 MB in size.
 1030        /// </param>
 1031        /// <param name="offset">
 1032        /// Specifies the starting offset for the <paramref name="content"/>
 1033        /// to be written as a page.  Given that pages must be aligned with
 1034        /// 512-byte boundaries, the start offset must be a modulus of 512.
 1035        /// </param>
 1036        /// <param name="transactionalContentHash">
 1037        /// Optional MD5 hash of the block content.  This hash is used to
 1038        /// verify the integrity of the block during transport. When this hash
 1039        /// is specified, the storage service compares the hash of the content
 1040        /// that has arrived with this value.  Note that this MD5 hash is not
 1041        /// stored with the blob.  If the two hashes do not match, the
 1042        /// operation will fail with a <see cref="RequestFailedException"/>.
 1043        /// </param>
 1044        /// <param name="conditions">
 1045        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1046        /// conditions on uploading pages to this page blob.
 1047        /// </param>
 1048        /// <param name="progressHandler">
 1049        /// Optional <see cref="IProgress{Long}"/> to provide
 1050        /// progress updates about data transfers.
 1051        /// </param>
 1052        /// <param name="async">
 1053        /// Whether to invoke the operation asynchronously.
 1054        /// </param>
 1055        /// <param name="cancellationToken">
 1056        /// Optional <see cref="CancellationToken"/> to propagate
 1057        /// notifications that the operation should be cancelled.
 1058        /// </param>
 1059        /// <returns>
 1060        /// A <see cref="Response{PageInfo}"/> describing the
 1061        /// state of the updated pages.
 1062        /// </returns>
 1063        /// <remarks>
 1064        /// A <see cref="RequestFailedException"/> will be thrown if
 1065        /// a failure occurs.
 1066        /// </remarks>
 1067        private async Task<Response<PageInfo>> UploadPagesInternal(
 1068            Stream content,
 1069            long offset,
 1070            byte[] transactionalContentHash,
 1071            PageBlobRequestConditions conditions,
 1072            IProgress<long> progressHandler,
 1073            bool async,
 1074            CancellationToken cancellationToken)
 1075        {
 5561076            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 1077            {
 1078                Pipeline.LogMethodEnter(
 1079                    nameof(PageBlobClient),
 1080                    message:
 1081                    $"{nameof(Uri)}: {Uri}\n" +
 1082                    $"{nameof(offset)}: {offset}\n" +
 1083                    $"{nameof(conditions)}: {conditions}");
 1084                try
 1085                {
 5561086                    content = content?.WithNoDispose().WithProgress(progressHandler);
 5561087                    var range = new HttpRange(offset, content?.Length ?? null);
 1088
 5561089                    return await BlobRestClient.PageBlob.UploadPagesAsync(
 5561090                        ClientDiagnostics,
 5561091                        Pipeline,
 5561092                        Uri,
 5561093                        body: content,
 5561094                        contentLength: content?.Length ?? 0,
 5561095                        version: Version.ToVersionString(),
 5561096                        transactionalContentHash: transactionalContentHash,
 5561097                        timeout: default,
 5561098                        range: range.ToString(),
 5561099                        leaseId: conditions?.LeaseId,
 5561100                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 5561101                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 5561102                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 5561103                        encryptionScope: EncryptionScope,
 5561104                        ifSequenceNumberLessThanOrEqualTo: conditions?.IfSequenceNumberLessThanOrEqual,
 5561105                        ifSequenceNumberLessThan: conditions?.IfSequenceNumberLessThan,
 5561106                        ifSequenceNumberEqualTo: conditions?.IfSequenceNumberEqual,
 5561107                        ifModifiedSince: conditions?.IfModifiedSince,
 5561108                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 5561109                        ifMatch: conditions?.IfMatch,
 5561110                        ifNoneMatch: conditions?.IfNoneMatch,
 5561111                        ifTags: conditions?.TagConditions,
 5561112                        async: async,
 5561113                        operationName: $"{nameof(PageBlobClient)}.{nameof(UploadPages)}",
 5561114                        cancellationToken: cancellationToken).ConfigureAwait(false);
 1115                }
 441116                catch (Exception ex)
 1117                {
 1118                    Pipeline.LogException(ex);
 441119                    throw;
 1120                }
 1121                finally
 1122                {
 1123                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 1124                }
 1125            }
 5121126        }
 1127        #endregion UploadPages
 1128
 1129        #region ClearPages
 1130        /// <summary>
 1131        /// The <see cref="ClearPages"/> operation clears one or more
 1132        /// pages from the page blob, as specificed by the <paramref name="range"/>.
 1133        ///
 1134        /// For more information, see
 1135        /// <see href="https://docs.microsoft.com/rest/api/storageservices/put-page">
 1136        /// Put Page</see>.
 1137        /// </summary>
 1138        /// <param name="range">
 1139        /// Specifies the range of bytes to be cleared. Both the start and
 1140        /// end of the range must be specified.  For a page clear operation,
 1141        /// the page range can be up to the value of the blob's full size.
 1142        /// Given that pages must be aligned with 512-byte boundaries, the
 1143        /// start of the range must be a modulus of 512 and the end of the
 1144        /// range must be a modulus of 512 â€“ 1.  Examples of valid byte ranges
 1145        /// are 0-511, 512-1023, etc.
 1146        /// </param>
 1147        /// <param name="conditions">
 1148        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1149        /// conditions on clearing pages from this page blob.
 1150        /// </param>
 1151        /// <param name="cancellationToken">
 1152        /// Optional <see cref="CancellationToken"/> to propagate
 1153        /// notifications that the operation should be cancelled.
 1154        /// </param>
 1155        /// <returns>
 1156        /// A <see cref="Response{PageInfo}"/> describing the
 1157        /// state of the updated pages.
 1158        /// </returns>
 1159        /// <remarks>
 1160        /// A <see cref="RequestFailedException"/> will be thrown if
 1161        /// a failure occurs.
 1162        /// </remarks>
 1163        public virtual Response<PageInfo> ClearPages(
 1164            HttpRange range,
 1165            PageBlobRequestConditions conditions = default,
 1166            CancellationToken cancellationToken = default) =>
 461167            ClearPagesInternal(
 461168                range,
 461169                conditions,
 461170                false, // async
 461171                cancellationToken)
 461172                .EnsureCompleted();
 1173
 1174        /// <summary>
 1175        /// The <see cref="ClearPagesAsync"/> operation clears one or more
 1176        /// pages from the page blob, as specificed by the <paramref name="range"/>.
 1177        ///
 1178        /// For more information, see
 1179        /// <see href="https://docs.microsoft.com/rest/api/storageservices/put-page">
 1180        /// Put Page</see>.
 1181        /// </summary>
 1182        /// <param name="range">
 1183        /// Specifies the range of bytes to be cleared. Both the start and
 1184        /// end of the range must be specified.  For a page clear operation,
 1185        /// the page range can be up to the value of the blob's full size.
 1186        /// Given that pages must be aligned with 512-byte boundaries, the
 1187        /// start of the range must be a modulus of 512 and the end of the
 1188        /// range must be a modulus of 512 â€“ 1.  Examples of valid byte ranges
 1189        /// are 0-511, 512-1023, etc.
 1190        /// </param>
 1191        /// <param name="conditions">
 1192        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1193        /// conditions on clearing pages from this page blob.
 1194        /// </param>
 1195        /// <param name="cancellationToken">
 1196        /// Optional <see cref="CancellationToken"/> to propagate
 1197        /// notifications that the operation should be cancelled.
 1198        /// </param>
 1199        /// <returns>
 1200        /// A <see cref="Response{PageInfo}"/> describing the
 1201        /// state of the updated pages.
 1202        /// </returns>
 1203        /// <remarks>
 1204        /// A <see cref="RequestFailedException"/> will be thrown if
 1205        /// a failure occurs.
 1206        /// </remarks>
 1207        public virtual async Task<Response<PageInfo>> ClearPagesAsync(
 1208            HttpRange range,
 1209            PageBlobRequestConditions conditions = default,
 1210            CancellationToken cancellationToken = default) =>
 461211            await ClearPagesInternal(
 461212                range,
 461213                conditions,
 461214                true, // async
 461215                cancellationToken)
 461216                .ConfigureAwait(false);
 1217
 1218        /// <summary>
 1219        /// The <see cref="ClearPagesInternal"/> operation clears one or more
 1220        /// pages from the page blob, as specificed by the <paramref name="range"/>.
 1221        ///
 1222        /// For more information, see
 1223        /// <see href="https://docs.microsoft.com/rest/api/storageservices/put-page">
 1224        /// Put Page</see>.
 1225        /// </summary>
 1226        /// <param name="range">
 1227        /// Specifies the range of bytes to be cleared. Both the start and
 1228        /// end of the range must be specified.  For a page clear operation,
 1229        /// the page range can be up to the value of the blob's full size.
 1230        /// Given that pages must be aligned with 512-byte boundaries, the
 1231        /// start of the range must be a modulus of 512 and the end of the
 1232        /// range must be a modulus of 512 â€“ 1.  Examples of valid byte ranges
 1233        /// are 0-511, 512-1023, etc.
 1234        /// </param>
 1235        /// <param name="conditions">
 1236        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1237        /// conditions on clearing pages from this page blob.
 1238        /// </param>
 1239        /// <param name="async">
 1240        /// Whether to invoke the operation asynchronously.
 1241        /// </param>
 1242        /// <param name="cancellationToken">
 1243        /// Optional <see cref="CancellationToken"/> to propagate
 1244        /// notifications that the operation should be cancelled.
 1245        /// </param>
 1246        /// <returns>
 1247        /// A <see cref="Response{PageInfo}"/> describing the
 1248        /// state of the updated pages.
 1249        /// </returns>
 1250        /// <remarks>
 1251        /// A <see cref="RequestFailedException"/> will be thrown if
 1252        /// a failure occurs.
 1253        /// </remarks>
 1254        private async Task<Response<PageInfo>> ClearPagesInternal(
 1255            HttpRange range,
 1256            PageBlobRequestConditions conditions,
 1257            bool async,
 1258            CancellationToken cancellationToken)
 1259        {
 921260            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 1261            {
 1262                Pipeline.LogMethodEnter(
 1263                    nameof(PageBlobClient),
 1264                    message:
 1265                    $"{nameof(Uri)}: {Uri}\n" +
 1266                    $"{nameof(conditions)}: {conditions}");
 1267                try
 1268                {
 921269                    return await BlobRestClient.PageBlob.ClearPagesAsync(
 921270                        ClientDiagnostics,
 921271                        Pipeline,
 921272                        Uri,
 921273                        contentLength: default,
 921274                        version: Version.ToVersionString(),
 921275                        range: range.ToString(),
 921276                        leaseId: conditions?.LeaseId,
 921277                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 921278                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 921279                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 921280                        encryptionScope: EncryptionScope,
 921281                        ifSequenceNumberLessThanOrEqualTo: conditions?.IfSequenceNumberLessThanOrEqual,
 921282                        ifSequenceNumberLessThan: conditions?.IfSequenceNumberLessThan,
 921283                        ifSequenceNumberEqualTo: conditions?.IfSequenceNumberEqual,
 921284                        ifModifiedSince: conditions?.IfModifiedSince,
 921285                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 921286                        ifMatch: conditions?.IfMatch,
 921287                        ifNoneMatch: conditions?.IfNoneMatch,
 921288                        ifTags: conditions?.TagConditions,
 921289                        async: async,
 921290                        operationName: $"{nameof(PageBlobClient)}.{nameof(ClearPages)}",
 921291                        cancellationToken: cancellationToken)
 921292                        .ConfigureAwait(false);
 1293                }
 401294                catch (Exception ex)
 1295                {
 1296                    Pipeline.LogException(ex);
 401297                    throw;
 1298                }
 1299                finally
 1300                {
 1301                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 1302                }
 1303            }
 521304        }
 1305        #endregion ClearPages
 1306
 1307        #region GetPageRanges
 1308        /// <summary>
 1309        /// The <see cref="GetPageRanges"/> operation returns the list of
 1310        /// valid page ranges for a page blob or snapshot of a page blob.
 1311        ///
 1312        /// For more information, see
 1313        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1314        /// Get Page Ranges</see>.
 1315        /// </summary>
 1316        /// <param name="range">
 1317        /// Optionally specifies the range of bytes over which to list ranges,
 1318        /// inclusively. If omitted, then all ranges for the blob are returned.
 1319        /// </param>
 1320        /// <param name="snapshot">
 1321        /// Optionally specifies the blob snapshot to retrieve page ranges
 1322        /// information from. For more information on working with blob snapshots,
 1323        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1324        /// Create a snapshot of a blob</see>.
 1325        /// </param>
 1326        /// <param name="conditions">
 1327        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1328        /// conditions on getting page ranges for the this blob.
 1329        /// </param>
 1330        /// <param name="cancellationToken">
 1331        /// Optional <see cref="CancellationToken"/> to propagate
 1332        /// notifications that the operation should be cancelled.
 1333        /// </param>
 1334        /// <returns>
 1335        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1336        /// valid page ranges for this blob.
 1337        /// </returns>
 1338        /// <remarks>
 1339        /// A <see cref="RequestFailedException"/> will be thrown if
 1340        /// a failure occurs.
 1341        /// </remarks>
 1342        public virtual Response<PageRangesInfo> GetPageRanges(
 1343            HttpRange? range = default,
 1344            string snapshot = default,
 1345            PageBlobRequestConditions conditions = default,
 1346            CancellationToken cancellationToken = default) =>
 321347            GetPageRangesInternal(
 321348                range,
 321349                snapshot,
 321350                conditions,
 321351                false, // async
 321352                cancellationToken)
 321353                .EnsureCompleted();
 1354
 1355        /// <summary>
 1356        /// The <see cref="GetPageRangesAsync"/> operation returns the list of
 1357        /// valid page ranges for a page blob or snapshot of a page blob.
 1358        ///
 1359        /// For more information, see
 1360        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1361        /// Get Page Ranges</see>.
 1362        /// </summary>
 1363        /// <param name="range">
 1364        /// Optionally specifies the range of bytes over which to list ranges,
 1365        /// inclusively. If omitted, then all ranges for the blob are returned.
 1366        /// </param>
 1367        /// <param name="snapshot">
 1368        /// Optionally specifies the blob snapshot to retrieve page ranges
 1369        /// information from. For more information on working with blob snapshots,
 1370        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1371        /// Create a snapshot of a blob</see>.
 1372        /// </param>
 1373        /// <param name="conditions">
 1374        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1375        /// conditions on getting page ranges for the this blob.
 1376        /// </param>
 1377        /// <param name="cancellationToken">
 1378        /// Optional <see cref="CancellationToken"/> to propagate
 1379        /// notifications that the operation should be cancelled.
 1380        /// </param>
 1381        /// <returns>
 1382        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1383        /// valid page ranges for this blob.
 1384        /// </returns>
 1385        /// <remarks>
 1386        /// A <see cref="RequestFailedException"/> will be thrown if
 1387        /// a failure occurs.
 1388        /// </remarks>
 1389        public virtual async Task<Response<PageRangesInfo>> GetPageRangesAsync(
 1390            HttpRange? range = default,
 1391            string snapshot = default,
 1392            PageBlobRequestConditions conditions = default,
 1393            CancellationToken cancellationToken = default) =>
 321394            await GetPageRangesInternal(
 321395                range,
 321396                snapshot,
 321397                conditions,
 321398                true, // async
 321399                cancellationToken)
 321400                .ConfigureAwait(false);
 1401
 1402        /// <summary>
 1403        /// The <see cref="GetPageRangesInternal"/> operation returns the list
 1404        /// of valid page ranges for a page blob or snapshot of a page blob.
 1405        ///
 1406        /// For more information, see For more information, see
 1407        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1408        /// Get Page Ranges</see>.
 1409        /// </summary>
 1410        /// <param name="range">
 1411        /// Optionally specifies the range of bytes over which to list ranges,
 1412        /// inclusively. If omitted, then all ranges for the blob are returned.
 1413        /// </param>
 1414        /// <param name="snapshot">
 1415        /// Optionally specifies the blob snapshot to retrieve page ranges
 1416        /// information from. For more information on working with blob snapshots,
 1417        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1418        /// Create a snapshot of a blob</see>.
 1419        /// </param>
 1420        /// <param name="conditions">
 1421        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1422        /// conditions on getting page ranges for the this blob.
 1423        /// </param>
 1424        /// <param name="async">
 1425        /// Whether to invoke the operation asynchronously.
 1426        /// </param>
 1427        /// <param name="cancellationToken">
 1428        /// Optional <see cref="CancellationToken"/> to propagate
 1429        /// notifications that the operation should be cancelled.
 1430        /// </param>
 1431        /// <returns>
 1432        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1433        /// valid page ranges for this blob.
 1434        /// </returns>
 1435        /// <remarks>
 1436        /// A <see cref="RequestFailedException"/> will be thrown if
 1437        /// a failure occurs.
 1438        /// </remarks>
 1439        private async Task<Response<PageRangesInfo>> GetPageRangesInternal(
 1440            HttpRange? range,
 1441            string snapshot,
 1442            PageBlobRequestConditions conditions,
 1443            bool async,
 1444            CancellationToken cancellationToken)
 1445        {
 641446            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 1447            {
 1448                Pipeline.LogMethodEnter(
 1449                    nameof(PageBlobClient),
 1450                    message:
 1451                    $"{nameof(Uri)}: {Uri}\n" +
 1452                    $"{nameof(snapshot)}: {snapshot}\n" +
 1453                    $"{nameof(conditions)}: {conditions}");
 1454                try
 1455                {
 641456                    Response<PageRangesInfoInternal> response = await BlobRestClient.PageBlob.GetPageRangesAsync(
 641457                        ClientDiagnostics,
 641458                        Pipeline,
 641459                        Uri,
 641460                        version: Version.ToVersionString(),
 641461                        snapshot: snapshot,
 641462                        range: range?.ToString(),
 641463                        leaseId: conditions?.LeaseId,
 641464                        ifModifiedSince: conditions?.IfModifiedSince,
 641465                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 641466                        ifMatch: conditions?.IfMatch,
 641467                        ifNoneMatch: conditions?.IfNoneMatch,
 641468                        ifTags: conditions?.TagConditions,
 641469                        async: async,
 641470                        operationName: $"{nameof(PageBlobClient)}.{nameof(GetPageRanges)}",
 641471                        cancellationToken: cancellationToken)
 641472                        .ConfigureAwait(false);
 1473
 1474                    // Return an exploding Response on 304
 441475                    return response.IsUnavailable() ?
 441476                        response.GetRawResponse().AsNoBodyResponse<PageRangesInfo>() :
 441477                        Response.FromValue(new PageRangesInfo(response.Value), response.GetRawResponse());
 1478                }
 201479                catch (Exception ex)
 1480                {
 1481                    Pipeline.LogException(ex);
 201482                    throw;
 1483                }
 1484                finally
 1485                {
 1486                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 1487                }
 1488            }
 441489        }
 1490        #endregion GetPageRanges
 1491
 1492        #region GetPageRangesDiff
 1493        /// <summary>
 1494        /// The <see cref="GetPageRangesDiff"/>
 1495        /// operation returns the list of page ranges that differ between a
 1496        /// <paramref name="previousSnapshot"/> and this page blob. Changed pages
 1497        /// include both updated and cleared pages.
 1498        ///
 1499        /// For more information, see
 1500        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1501        /// Get Page Ranges</see>.
 1502        /// </summary>
 1503        /// <param name="range">
 1504        /// Optionally specifies the range of bytes over which to list ranges,
 1505        /// inclusively. If omitted, then all ranges for the blob are returned.
 1506        /// </param>
 1507        /// <param name="snapshot">
 1508        /// Optionally specifies the blob snapshot to retrieve page ranges
 1509        /// information from. For more information on working with blob snapshots,
 1510        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1511        /// Create a snapshot of a blob</see>.
 1512        /// </param>
 1513        /// <param name="previousSnapshot">
 1514        /// Specifies that the response will contain only pages that were
 1515        /// changed between target blob and previous snapshot.  Changed pages
 1516        /// include both updated and cleared pages. The target blob may be a
 1517        /// snapshot, as long as the snapshot specified by
 1518        /// <paramref name="previousSnapshot"/> is the older of the two.
 1519        /// </param>
 1520        /// <param name="conditions">
 1521        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1522        /// conditions on getting page ranges for the this blob.
 1523        /// </param>
 1524        /// <param name="cancellationToken">
 1525        /// Optional <see cref="CancellationToken"/> to propagate
 1526        /// notifications that the operation should be cancelled.
 1527        /// </param>
 1528        /// <returns>
 1529        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1530        /// valid page ranges for this blob.
 1531        /// </returns>
 1532        /// <remarks>
 1533        /// A <see cref="RequestFailedException"/> will be thrown if
 1534        /// a failure occurs.
 1535        /// </remarks>
 1536        public virtual Response<PageRangesInfo> GetPageRangesDiff(
 1537            HttpRange? range = default,
 1538            string snapshot = default,
 1539            string previousSnapshot = default,
 1540            PageBlobRequestConditions conditions = default,
 1541            CancellationToken cancellationToken = default) =>
 321542            GetPageRangesDiffInternal(
 321543                range,
 321544                snapshot,
 321545                previousSnapshot,
 321546                previousSnapshotUri: default,
 321547                conditions,
 321548                async: false,
 321549                operationName: $"{nameof(PageBlobClient)}.{nameof(GetPageRangesDiff)}",
 321550                cancellationToken)
 321551                .EnsureCompleted();
 1552
 1553        /// <summary>
 1554        /// The <see cref="GetPageRangesDiffAsync"/>
 1555        /// operation returns the list of page ranges that differ between a
 1556        /// <paramref name="previousSnapshot"/> and this page blob. Changed pages
 1557        /// include both updated and cleared pages.
 1558        ///
 1559        /// For more information, see
 1560        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1561        /// Get Page Ranges</see>.
 1562        /// </summary>
 1563        /// <param name="range">
 1564        /// Optionally specifies the range of bytes over which to list ranges,
 1565        /// inclusively. If omitted, then all ranges for the blob are returned.
 1566        /// </param>
 1567        /// <param name="snapshot">
 1568        /// Optionally specifies the blob snapshot to retrieve page ranges
 1569        /// information from. For more information on working with blob snapshots,
 1570        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1571        /// Create a snapshot of a blob</see>.
 1572        /// </param>
 1573        /// <param name="previousSnapshot">
 1574        /// Specifies that the response will contain only pages that were
 1575        /// changed between target blob and previous snapshot.  Changed pages
 1576        /// include both updated and cleared pages. The target blob may be a
 1577        /// snapshot, as long as the snapshot specified by
 1578        /// <paramref name="previousSnapshot"/> is the older of the two.
 1579        /// </param>
 1580        /// <param name="conditions">
 1581        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1582        /// conditions on getting page ranges for the this blob.
 1583        /// </param>
 1584        /// <param name="cancellationToken">
 1585        /// Optional <see cref="CancellationToken"/> to propagate
 1586        /// notifications that the operation should be cancelled.
 1587        /// </param>
 1588        /// <returns>
 1589        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1590        /// valid page ranges for this blob.
 1591        /// </returns>
 1592        /// <remarks>
 1593        /// A <see cref="RequestFailedException"/> will be thrown if
 1594        /// a failure occurs.
 1595        /// </remarks>
 1596        public virtual async Task<Response<PageRangesInfo>> GetPageRangesDiffAsync(
 1597            HttpRange? range = default,
 1598            string snapshot = default,
 1599            string previousSnapshot = default,
 1600            PageBlobRequestConditions conditions = default,
 1601            CancellationToken cancellationToken = default) =>
 321602            await GetPageRangesDiffInternal(
 321603                range,
 321604                snapshot,
 321605                previousSnapshot,
 321606                previousSnapshotUri: default,
 321607                conditions,
 321608                async: true,
 321609                operationName: $"{nameof(PageBlobClient)}.{nameof(GetPageRangesDiff)}",
 321610                cancellationToken)
 321611                .ConfigureAwait(false);
 1612
 1613        /// <summary>
 1614        /// The <see cref="GetPageRangesDiffInternal"/> operation returns the
 1615        /// list of page ranges that differ between a
 1616        /// <paramref name="previousSnapshot"/> and this page blob. Changed pages
 1617        /// include both updated and cleared pages.
 1618        ///
 1619        /// For more information, see
 1620        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1621        /// Get Page Ranges</see>.
 1622        /// </summary>
 1623        /// <param name="range">
 1624        /// Optionally specifies the range of bytes over which to list ranges,
 1625        /// inclusively. If omitted, then all ranges for the blob are returned.
 1626        /// </param>
 1627        /// <param name="snapshot">
 1628        /// Optionally specifies the blob snapshot to retrieve page ranges
 1629        /// information from. For more information on working with blob snapshots,
 1630        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1631        /// Create a snapshot of a blob</see>.
 1632        /// </param>
 1633        /// <param name="previousSnapshot">
 1634        /// Specifies that the response will contain only pages that were
 1635        /// changed between target blob and previous snapshot.  Changed pages
 1636        /// include both updated and cleared pages. The target blob may be a
 1637        /// snapshot, as long as the snapshot specified by
 1638        /// <paramref name="previousSnapshot"/> is the older of the two.
 1639        /// </param>
 1640        /// <param name="previousSnapshotUri">
 1641        /// This parameter only works with managed disk storage accounts.
 1642        /// Specifies that the response will contain only pages that were
 1643        /// changed between target blob and previous snapshot.  Changed pages
 1644        /// include both updated and cleared pages. The target blob may be a
 1645        /// snapshot, as long as the snapshot specified by
 1646        /// <paramref name="previousSnapshotUri"/> is the older of the two.
 1647        /// </param>
 1648        /// <param name="conditions">
 1649        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1650        /// conditions on getting page ranges for the this blob.
 1651        /// </param>
 1652        /// <param name="async">
 1653        /// Whether to invoke the operation asynchronously.
 1654        /// </param>
 1655        /// <param name="operationName">
 1656        /// The name of the operation.
 1657        /// </param>
 1658        /// <param name="cancellationToken">
 1659        /// Optional <see cref="CancellationToken"/> to propagate
 1660        /// notifications that the operation should be cancelled.
 1661        /// </param>
 1662        /// <returns>
 1663        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1664        /// valid page ranges for this blob.
 1665        /// </returns>
 1666        /// <remarks>
 1667        /// A <see cref="RequestFailedException"/> will be thrown if
 1668        /// a failure occurs.
 1669        /// </remarks>
 1670        private async Task<Response<PageRangesInfo>> GetPageRangesDiffInternal(
 1671            HttpRange? range,
 1672            string snapshot,
 1673            string previousSnapshot,
 1674            Uri previousSnapshotUri,
 1675            PageBlobRequestConditions conditions,
 1676            bool async,
 1677            string operationName,
 1678            CancellationToken cancellationToken)
 1679        {
 1201680            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 1681            {
 1682                Pipeline.LogMethodEnter(
 1683                    nameof(PageBlobClient),
 1684                    message:
 1685                    $"{nameof(Uri)}: {Uri}\n" +
 1686                    $"{nameof(snapshot)}: {snapshot}\n" +
 1687                    $"{nameof(previousSnapshot)}: {previousSnapshot}\n" +
 1688                    $"{nameof(previousSnapshotUri)}: {previousSnapshotUri}\n" +
 1689                    $"{nameof(conditions)}: {conditions}");
 1690                try
 1691                {
 1201692                    Response<PageRangesInfoInternal> response = await BlobRestClient.PageBlob.GetPageRangesDiffAsync(
 1201693                        ClientDiagnostics,
 1201694                        Pipeline,
 1201695                        Uri,
 1201696                        version: Version.ToVersionString(),
 1201697                        snapshot: snapshot,
 1201698                        prevsnapshot: previousSnapshot,
 1201699                        prevSnapshotUrl: previousSnapshotUri,
 1201700                        range: range?.ToString(),
 1201701                        leaseId: conditions?.LeaseId,
 1201702                        ifModifiedSince: conditions?.IfModifiedSince,
 1201703                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1201704                        ifMatch: conditions?.IfMatch,
 1201705                        ifNoneMatch: conditions?.IfNoneMatch,
 1201706                        ifTags: conditions?.TagConditions,
 1201707                        async: async,
 1201708                        operationName: operationName,
 1201709                        cancellationToken: cancellationToken)
 1201710                        .ConfigureAwait(false);
 1711
 1712                    // Return an exploding Response on 304
 841713                    return response.IsUnavailable() ?
 841714                        response.GetRawResponse().AsNoBodyResponse<PageRangesInfo>() :
 841715                        Response.FromValue(new PageRangesInfo(response.Value), response.GetRawResponse());
 1716                }
 361717                catch (Exception ex)
 1718                {
 1719                    Pipeline.LogException(ex);
 361720                    throw;
 1721                }
 1722                finally
 1723                {
 1724                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 1725                }
 1726            }
 841727        }
 1728        #endregion GetPageRangesDiff
 1729
 1730        #region GetManagedDiskPageRangesDiff
 1731        /// <summary>
 1732        /// The <see cref="GetManagedDiskPageRangesDiff"/>
 1733        /// operation returns the list of page ranges that differ between a
 1734        /// <paramref name="previousSnapshotUri"/> and this page blob. Changed pages
 1735        /// include both updated and cleared pages.  This API only works with
 1736        /// managed disk storage accounts.
 1737        ///
 1738        /// For more information, see
 1739        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1740        /// Get Page Ranges</see>.
 1741        /// </summary>
 1742        /// <param name="range">
 1743        /// Optionally specifies the range of bytes over which to list ranges,
 1744        /// inclusively. If omitted, then all ranges for the blob are returned.
 1745        /// </param>
 1746        /// <param name="snapshot">
 1747        /// Optionally specifies the blob snapshot to retrieve page ranges
 1748        /// information from. For more information on working with blob snapshots,
 1749        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1750        /// Create a snapshot of a blob</see>.
 1751        /// </param>
 1752        /// <param name="previousSnapshotUri">
 1753        /// This parameter only works with managed disk storage accounts.
 1754        /// Specifies that the response will contain only pages that were
 1755        /// changed between target blob and previous snapshot.  Changed pages
 1756        /// include both updated and cleared pages. The target blob may be a
 1757        /// snapshot, as long as the snapshot specified by
 1758        /// <paramref name="previousSnapshotUri"/> is the older of the two.
 1759        /// </param>
 1760        /// <param name="conditions">
 1761        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1762        /// conditions on getting page ranges for the this blob.
 1763        /// </param>
 1764        /// <param name="cancellationToken">
 1765        /// Optional <see cref="CancellationToken"/> to propagate
 1766        /// notifications that the operation should be cancelled.
 1767        /// </param>
 1768        /// <returns>
 1769        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1770        /// valid page ranges for this blob.
 1771        /// </returns>
 1772        /// <remarks>
 1773        /// A <see cref="RequestFailedException"/> will be thrown if
 1774        /// a failure occurs.
 1775        /// </remarks>
 1776        public virtual Response<PageRangesInfo> GetManagedDiskPageRangesDiff(
 1777            HttpRange? range = default,
 1778            string snapshot = default,
 1779            Uri previousSnapshotUri = default,
 1780            PageBlobRequestConditions conditions = default,
 1781            CancellationToken cancellationToken = default) =>
 281782            GetPageRangesDiffInternal(
 281783                range,
 281784                snapshot,
 281785                previousSnapshot: default,
 281786                previousSnapshotUri,
 281787                conditions,
 281788                async: false,
 281789                operationName: $"{nameof(PageBlobClient)}.{nameof(GetManagedDiskPageRangesDiff)}",
 281790                cancellationToken)
 281791                .EnsureCompleted();
 1792
 1793        /// <summary>
 1794        /// The <see cref="GetManagedDiskPageRangesDiffAsync"/>
 1795        /// operation returns the list of page ranges that differ between a
 1796        /// <paramref name="previousSnapshotUri"/> and this page blob. Changed pages
 1797        /// include both updated and cleared pages.  This API only works with
 1798        /// managed disk storage accounts.
 1799        ///
 1800        /// For more information, see
 1801        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-page-ranges">
 1802        /// Get Page Ranges</see>.
 1803        /// </summary>
 1804        /// <param name="range">
 1805        /// Optionally specifies the range of bytes over which to list ranges,
 1806        /// inclusively. If omitted, then all ranges for the blob are returned.
 1807        /// </param>
 1808        /// <param name="snapshot">
 1809        /// Optionally specifies the blob snapshot to retrieve page ranges
 1810        /// information from. For more information on working with blob snapshots,
 1811        /// <see href="https://docs.microsoft.com/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 1812        /// Create a snapshot of a blob</see>.
 1813        /// </param>
 1814        /// <param name="previousSnapshotUri">
 1815        /// This parameter only works with managed disk storage accounts.
 1816        /// Specifies that the response will contain only pages that were
 1817        /// changed between target blob and previous snapshot.  Changed pages
 1818        /// include both updated and cleared pages. The target blob may be a
 1819        /// snapshot, as long as the snapshot specified by
 1820        /// <paramref name="previousSnapshotUri"/> is the older of the two.
 1821        /// </param>
 1822        /// <param name="conditions">
 1823        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1824        /// conditions on getting page ranges for the this blob.
 1825        /// </param>
 1826        /// <param name="cancellationToken">
 1827        /// Optional <see cref="CancellationToken"/> to propagate
 1828        /// notifications that the operation should be cancelled.
 1829        /// </param>
 1830        /// <returns>
 1831        /// A <see cref="Response{PageRangesInfo}"/> describing the
 1832        /// valid page ranges for this blob.
 1833        /// </returns>
 1834        /// <remarks>
 1835        /// A <see cref="RequestFailedException"/> will be thrown if
 1836        /// a failure occurs.
 1837        /// </remarks>
 1838        public virtual async Task<Response<PageRangesInfo>> GetManagedDiskPageRangesDiffAsync(
 1839            HttpRange? range = default,
 1840            string snapshot = default,
 1841            Uri previousSnapshotUri = default,
 1842            PageBlobRequestConditions conditions = default,
 1843            CancellationToken cancellationToken = default) =>
 281844            await GetPageRangesDiffInternal(
 281845                range,
 281846                snapshot,
 281847                previousSnapshot: default,
 281848                previousSnapshotUri,
 281849                conditions,
 281850                async: true,
 281851                operationName: $"{nameof(PageBlobClient)}.{nameof(GetManagedDiskPageRangesDiff)}",
 281852                cancellationToken)
 281853                .ConfigureAwait(false);
 1854
 1855        #endregion GetManagedDiskPageRangesDiff
 1856
 1857        #region Resize
 1858        /// <summary>
 1859        /// The <see cref="Resize"/> operation resizes the page blob to
 1860        /// the specified size (which must be a multiple of 512).  If the
 1861        /// specified value is less than the current size of the blob, then
 1862        /// all pages above the specified value are cleared.
 1863        ///
 1864        /// For more information, see
 1865        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 1866        /// Set Blob Properties</see>.
 1867        /// </summary>
 1868        /// <param name="size">
 1869        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 1870        /// size must be aligned to a 512-byte boundary.  If the specified
 1871        /// value is less than the current size of the blob, then all pages
 1872        /// above the specified value are cleared.
 1873        /// </param>
 1874        /// <param name="conditions">
 1875        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1876        /// conditions on the resize of this page blob.
 1877        /// </param>
 1878        /// <param name="cancellationToken">
 1879        /// Optional <see cref="CancellationToken"/> to propagate
 1880        /// notifications that the operation should be cancelled.
 1881        /// </param>
 1882        /// <returns>
 1883        /// A <see cref="Response{PageBlobInfo}"/> describing the resized
 1884        /// page blob.
 1885        /// </returns>
 1886        /// <remarks>
 1887        /// A <see cref="RequestFailedException"/> will be thrown if
 1888        /// a failure occurs.
 1889        /// </remarks>
 1890        public virtual Response<PageBlobInfo> Resize(
 1891            long size,
 1892            PageBlobRequestConditions conditions = default,
 1893            CancellationToken cancellationToken = default) =>
 341894            ResizeInternal(
 341895                size,
 341896                conditions,
 341897                false, // async
 341898                cancellationToken)
 341899                .EnsureCompleted();
 1900
 1901        /// <summary>
 1902        /// The <see cref="ResizeAsync"/> operation resizes the page blob to
 1903        /// the specified size (which must be a multiple of 512).  If the
 1904        /// specified value is less than the current size of the blob, then
 1905        /// all pages above the specified value are cleared.
 1906        ///
 1907        /// For more information, see
 1908        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 1909        /// Set Blob Properties</see>.
 1910        /// </summary>
 1911        /// <param name="size">
 1912        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 1913        /// size must be aligned to a 512-byte boundary.  If the specified
 1914        /// value is less than the current size of the blob, then all pages
 1915        /// above the specified value are cleared.
 1916        /// </param>
 1917        /// <param name="conditions">
 1918        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1919        /// conditions on the resize of this page blob.
 1920        /// </param>
 1921        /// <param name="cancellationToken">
 1922        /// Optional <see cref="CancellationToken"/> to propagate
 1923        /// notifications that the operation should be cancelled.
 1924        /// </param>
 1925        /// <returns>
 1926        /// A <see cref="Response{PageBlobInfo}"/> describing the resized
 1927        /// page blob.
 1928        /// </returns>
 1929        /// <remarks>
 1930        /// A <see cref="RequestFailedException"/> will be thrown if
 1931        /// a failure occurs.
 1932        /// </remarks>
 1933        public virtual async Task<Response<PageBlobInfo>> ResizeAsync(
 1934            long size,
 1935            PageBlobRequestConditions conditions = default,
 1936            CancellationToken cancellationToken = default) =>
 341937            await ResizeInternal(
 341938                size,
 341939                conditions,
 341940                true, // async
 341941                cancellationToken)
 341942                .ConfigureAwait(false);
 1943
 1944        /// <summary>
 1945        /// The <see cref="ResizeAsync"/> operation resizes the page blob to
 1946        /// the specified size (which must be a multiple of 512).  If the
 1947        /// specified value is less than the current size of the blob, then
 1948        /// all pages above the specified value are cleared.
 1949        ///
 1950        /// For more information, see
 1951        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 1952        /// Set Blob Properties</see>.
 1953        /// </summary>
 1954        /// <param name="size">
 1955        /// Specifies the maximum size for the page blob, up to 8 TB.  The
 1956        /// size must be aligned to a 512-byte boundary.  If the specified
 1957        /// value is less than the current size of the blob, then all pages
 1958        /// above the specified value are cleared.
 1959        /// </param>
 1960        /// <param name="conditions">
 1961        /// Optional <see cref="PageBlobRequestConditions"/> to add
 1962        /// conditions on the resize of this page blob.
 1963        /// </param>
 1964        /// <param name="async">
 1965        /// Whether to invoke the operation asynchronously.
 1966        /// </param>
 1967        /// <param name="cancellationToken">
 1968        /// Optional <see cref="CancellationToken"/> to propagate
 1969        /// notifications that the operation should be cancelled.
 1970        /// </param>
 1971        /// <returns>
 1972        /// A <see cref="Response{PageBlobInfo}"/> describing the resized
 1973        /// page blob.
 1974        /// </returns>
 1975        /// <remarks>
 1976        /// A <see cref="RequestFailedException"/> will be thrown if
 1977        /// a failure occurs.
 1978        /// </remarks>
 1979        private async Task<Response<PageBlobInfo>> ResizeInternal(
 1980            long size,
 1981            PageBlobRequestConditions conditions,
 1982            bool async,
 1983            CancellationToken cancellationToken)
 1984        {
 681985            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 1986            {
 1987                Pipeline.LogMethodEnter(
 1988                    nameof(PageBlobClient),
 1989                    message:
 1990                    $"{nameof(Uri)}: {Uri}\n" +
 1991                    $"{nameof(size)}: {size}\n" +
 1992                    $"{nameof(conditions)}: {conditions}");
 1993                try
 1994                {
 681995                    return await BlobRestClient.PageBlob.ResizeAsync(
 681996                        ClientDiagnostics,
 681997                        Pipeline,
 681998                        Uri,
 681999                        blobContentLength: size,
 682000                        version: Version.ToVersionString(),
 682001                        leaseId: conditions?.LeaseId,
 682002                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 682003                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 682004                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 682005                        encryptionScope: EncryptionScope,
 682006                        ifModifiedSince: conditions?.IfModifiedSince,
 682007                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 682008                        ifMatch: conditions?.IfMatch,
 682009                        ifNoneMatch: conditions?.IfNoneMatch,
 682010                        ifTags: conditions?.TagConditions,
 682011                        async: async,
 682012                        operationName: $"{nameof(PageBlobClient)}.{nameof(Resize)}",
 682013                        cancellationToken: cancellationToken)
 682014                        .ConfigureAwait(false);
 2015                }
 282016                catch (Exception ex)
 2017                {
 2018                    Pipeline.LogException(ex);
 282019                    throw;
 2020                }
 2021                finally
 2022                {
 2023                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 2024                }
 2025            }
 402026        }
 2027        #endregion Resize
 2028
 2029        #region UpdateSequenceNumber
 2030        /// <summary>
 2031        /// The <see cref="UpdateSequenceNumber"/> operation changes the
 2032        /// sequence number <paramref name="action"/> and <paramref name="sequenceNumber"/>
 2033        /// for this page blob.
 2034        ///
 2035        /// For more information, see
 2036        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 2037        /// Set Blob Properties</see>.
 2038        /// </summary>
 2039        /// <param name="action">
 2040        /// Specifies how the service should modify the blob's sequence number.
 2041        /// <see cref="SequenceNumberAction.Max"/> sets the sequence number to
 2042        /// be the higher of the value included with the request and the value
 2043        /// currently stored for the blob.  <see cref="SequenceNumberAction.Update"/>
 2044        /// sets the sequence number to the <paramref name="sequenceNumber"/>
 2045        /// value.  <see cref="SequenceNumberAction.Increment"/> increments
 2046        /// the value of the sequence number by 1.  If specifying
 2047        /// <see cref="SequenceNumberAction.Increment"/>, do not include the
 2048        /// <paramref name="sequenceNumber"/> because that will throw a
 2049        /// <see cref="RequestFailedException"/>.
 2050        /// </param>
 2051        /// <param name="sequenceNumber">
 2052        /// An updated sequence number of your choosing, if
 2053        /// <paramref name="action"/> is <see cref="SequenceNumberAction.Max"/>
 2054        /// or <see cref="SequenceNumberAction.Update"/>.  The value should
 2055        /// not be provided if <paramref name="action"/> is
 2056        /// <see cref="SequenceNumberAction.Increment"/>.  The sequence number
 2057        /// is a user-controlled property that you can use to track requests
 2058        /// and manage concurrency issues via <see cref="PageBlobRequestConditions"/>.
 2059        /// </param>
 2060        /// <param name="conditions">
 2061        /// Optional <see cref="PageBlobRequestConditions"/> to add conditions
 2062        /// on updating the sequence number of this page blob.
 2063        /// </param>
 2064        /// <param name="cancellationToken">
 2065        /// Optional <see cref="CancellationToken"/> to propagate
 2066        /// notifications that the operation should be cancelled.
 2067        /// </param>
 2068        /// <returns>
 2069        /// A <see cref="Response{PageBlobInfo}"/> describing the updated
 2070        /// page blob.
 2071        /// </returns>
 2072        /// <remarks>
 2073        /// A <see cref="RequestFailedException"/> will be thrown if
 2074        /// a failure occurs.
 2075        /// </remarks>
 2076        public virtual Response<PageBlobInfo> UpdateSequenceNumber(
 2077            SequenceNumberAction action,
 2078            long? sequenceNumber = default,
 2079            PageBlobRequestConditions conditions = default,
 2080            CancellationToken cancellationToken = default) =>
 302081            UpdateSequenceNumberInternal(
 302082                action,
 302083                sequenceNumber,
 302084                conditions,
 302085                false, // async
 302086                cancellationToken)
 302087                .EnsureCompleted();
 2088
 2089        /// <summary>
 2090        /// The <see cref="UpdateSequenceNumberAsync"/> operation changes the
 2091        /// sequence number <paramref name="action"/> and <paramref name="sequenceNumber"/>
 2092        /// for this page blob.
 2093        ///
 2094        /// For more information, see
 2095        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 2096        /// Set Blob Properties</see>.
 2097        /// </summary>
 2098        /// <param name="action">
 2099        /// Specifies how the service should modify the blob's sequence number.
 2100        /// <see cref="SequenceNumberAction.Max"/> sets the sequence number to
 2101        /// be the higher of the value included with the request and the value
 2102        /// currently stored for the blob.  <see cref="SequenceNumberAction.Update"/>
 2103        /// sets the sequence number to the <paramref name="sequenceNumber"/>
 2104        /// value.  <see cref="SequenceNumberAction.Increment"/> increments
 2105        /// the value of the sequence number by 1.  If specifying
 2106        /// <see cref="SequenceNumberAction.Increment"/>, do not include the
 2107        /// <paramref name="sequenceNumber"/> because that will throw a
 2108        /// <see cref="RequestFailedException"/>.
 2109        /// </param>
 2110        /// <param name="sequenceNumber">
 2111        /// An updated sequence number of your choosing, if
 2112        /// <paramref name="action"/> is <see cref="SequenceNumberAction.Max"/>
 2113        /// or <see cref="SequenceNumberAction.Update"/>.  The value should
 2114        /// not be provided if <paramref name="action"/> is
 2115        /// <see cref="SequenceNumberAction.Increment"/>.  The sequence number
 2116        /// is a user-controlled property that you can use to track requests
 2117        /// and manage concurrency issues via <see cref="PageBlobRequestConditions"/>.
 2118        /// </param>
 2119        /// <param name="conditions">
 2120        /// Optional <see cref="PageBlobRequestConditions"/> to add conditions
 2121        /// on updating the sequence number of this page blob.
 2122        /// </param>
 2123        /// <param name="cancellationToken">
 2124        /// Optional <see cref="CancellationToken"/> to propagate
 2125        /// notifications that the operation should be cancelled.
 2126        /// </param>
 2127        /// <returns>
 2128        /// A <see cref="Response{PageBlobInfo}"/> describing the updated
 2129        /// page blob.
 2130        /// </returns>
 2131        /// <remarks>
 2132        /// A <see cref="RequestFailedException"/> will be thrown if
 2133        /// a failure occurs.
 2134        /// </remarks>
 2135        public virtual async Task<Response<PageBlobInfo>> UpdateSequenceNumberAsync(
 2136            SequenceNumberAction action,
 2137            long? sequenceNumber = default,
 2138            PageBlobRequestConditions conditions = default,
 2139            CancellationToken cancellationToken = default) =>
 302140            await UpdateSequenceNumberInternal(
 302141                action,
 302142                sequenceNumber,
 302143                conditions,
 302144                true, // async
 302145                cancellationToken)
 302146                .ConfigureAwait(false);
 2147
 2148        /// <summary>
 2149        /// The <see cref="UpdateSequenceNumberInternal"/> operation changes the
 2150        /// sequence number <paramref name="action"/> and <paramref name="sequenceNumber"/>
 2151        /// for this page blob.
 2152        ///
 2153        /// For more information, see
 2154        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 2155        /// Set Blob Properties</see>.
 2156        /// </summary>
 2157        /// <param name="action">
 2158        /// Specifies how the service should modify the blob's sequence number.
 2159        /// <see cref="SequenceNumberAction.Max"/> sets the sequence number to
 2160        /// be the higher of the value included with the request and the value
 2161        /// currently stored for the blob.  <see cref="SequenceNumberAction.Update"/>
 2162        /// sets the sequence number to the <paramref name="sequenceNumber"/>
 2163        /// value.  <see cref="SequenceNumberAction.Increment"/> increments
 2164        /// the value of the sequence number by 1.  If specifying
 2165        /// <see cref="SequenceNumberAction.Increment"/>, do not include the
 2166        /// <paramref name="sequenceNumber"/> because that will throw a
 2167        /// <see cref="RequestFailedException"/>.
 2168        /// </param>
 2169        /// <param name="sequenceNumber">
 2170        /// An updated sequence number of your choosing, if
 2171        /// <paramref name="action"/> is <see cref="SequenceNumberAction.Max"/>
 2172        /// or <see cref="SequenceNumberAction.Update"/>.  The value should
 2173        /// not be provided if <paramref name="action"/> is
 2174        /// <see cref="SequenceNumberAction.Increment"/>.  The sequence number
 2175        /// is a user-controlled property that you can use to track requests
 2176        /// and manage concurrency issues via <see cref="PageBlobRequestConditions"/>.
 2177        /// </param>
 2178        /// <param name="conditions">
 2179        /// Optional <see cref="PageBlobRequestConditions"/> to add conditions
 2180        /// on updating the sequence number of this page blob.
 2181        /// </param>
 2182        /// <param name="async">
 2183        /// Whether to invoke the operation asynchronously.
 2184        /// </param>
 2185        /// <param name="cancellationToken">
 2186        /// Optional <see cref="CancellationToken"/> to propagate
 2187        /// notifications that the operation should be cancelled.
 2188        /// </param>
 2189        /// <returns>
 2190        /// A <see cref="Response{PageBlobInfo}"/> describing the updated
 2191        /// page blob.
 2192        /// </returns>
 2193        /// <remarks>
 2194        /// A <see cref="RequestFailedException"/> will be thrown if
 2195        /// a failure occurs.
 2196        /// </remarks>
 2197        private async Task<Response<PageBlobInfo>> UpdateSequenceNumberInternal(
 2198            SequenceNumberAction action,
 2199            long? sequenceNumber,
 2200            PageBlobRequestConditions conditions,
 2201            bool async,
 2202            CancellationToken cancellationToken)
 2203        {
 602204            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 2205            {
 2206                Pipeline.LogMethodEnter(
 2207                    nameof(PageBlobClient),
 2208                    message:
 2209                    $"{nameof(Uri)}: {Uri}\n" +
 2210                    $"{nameof(action)}: {action}\n" +
 2211                    $"{nameof(sequenceNumber)}: {sequenceNumber}\n" +
 2212                    $"{nameof(conditions)}: {conditions}");
 2213                try
 2214                {
 602215                    return await BlobRestClient.PageBlob.UpdateSequenceNumberAsync(
 602216                        ClientDiagnostics,
 602217                        Pipeline,
 602218                        Uri,
 602219                        sequenceNumberAction: action,
 602220                        version: Version.ToVersionString(),
 602221                        blobSequenceNumber: sequenceNumber,
 602222                        leaseId: conditions?.LeaseId,
 602223                        ifModifiedSince: conditions?.IfModifiedSince,
 602224                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 602225                        ifMatch: conditions?.IfMatch,
 602226                        ifNoneMatch: conditions?.IfNoneMatch,
 602227                        ifTags: conditions?.TagConditions,
 602228                        operationName: $"{nameof(PageBlobClient)}.{nameof(UpdateSequenceNumber)}",
 602229                        async: async,
 602230                        cancellationToken: cancellationToken)
 602231                        .ConfigureAwait(false);
 2232                }
 282233                catch (Exception ex)
 2234                {
 2235                    Pipeline.LogException(ex);
 282236                    throw;
 2237                }
 2238                finally
 2239                {
 2240                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 2241                }
 2242            }
 322243        }
 2244        #endregion UpdateSequenceNumber
 2245
 2246        #region StartCopyIncremental
 2247        /// <summary>
 2248        /// The <see cref="StartCopyIncremental(Uri, string, PageBlobRequestConditions, CancellationToken)"/>
 2249        /// operation starts copying a snapshot of the sourceUri page blob to
 2250        /// this page blob.  The snapshot is copied such that only the
 2251        /// differential changes between the previously copied snapshot are
 2252        /// transferred to the destination.  The copied snapshots are complete
 2253        /// copies of the original snapshot and can be read or copied from as
 2254        /// usual.  You can check the <see cref="BlobProperties.CopyStatus"/>
 2255        /// returned from the <see cref="BlobBaseClient.GetProperties"/> to
 2256        /// determine if the copy has completed.
 2257        ///
 2258        /// For more information, see
 2259        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/incremental-copy-blob">
 2260        /// Incremental Copy Blob</see> and
 2261        /// <see href="https://docs.microsoft.com/azure/virtual-machines/windows/incremental-snapshots">
 2262        /// Back up Azure unmanaged VM disks with incremental snapshots</see>.
 2263        /// </summary>
 2264        /// <param name="sourceUri">
 2265        /// Specifies the to the source page blob as a <see cref="Uri"/> up to
 2266        /// 2 KB in length.  The source blob must either be public or must be
 2267        /// authenticated via a shared access signature.
 2268        /// </param>
 2269        /// <param name="snapshot">
 2270        /// The name of a snapshot to start copying from
 2271        /// sourceUri.
 2272        /// </param>
 2273        /// <param name="conditions">
 2274        /// Optional <see cref="PageBlobRequestConditions"/> to add
 2275        /// conditions on the incremental copy into this page blob.
 2276        /// </param>
 2277        /// <param name="cancellationToken">
 2278        /// Optional <see cref="CancellationToken"/> to propagate
 2279        /// notifications that the operation should be cancelled.
 2280        /// </param>
 2281        /// <returns>
 2282        /// A <see cref="CopyFromUriOperation"/> referencing the incremental
 2283        /// copy operation.
 2284        /// </returns>
 2285        /// <remarks>
 2286        /// A <see cref="RequestFailedException"/> will be thrown if
 2287        /// a failure occurs.
 2288        ///
 2289        /// The destination of an incremental copy must either not exist, or
 2290        /// must have been created with a previous incremental copy from the
 2291        /// same source blob.  Once created, the destination blob is
 2292        /// permanently associated with the source and may only be used for
 2293        /// incremental copies.
 2294        ///
 2295        /// The <see cref="BlobBaseClient.GetProperties"/>,
 2296        /// <see cref="BlobContainerClient.GetBlobs"/>, and
 2297        /// <see cref="BlobContainerClient.GetBlobsByHierarchy"/>
 2298        /// operations indicate whether the blob is an incremental copy blob
 2299        /// created in this way.  Incremental copy blobs may not be downloaded
 2300        /// directly.  The only supported operations are
 2301        /// <see cref="BlobBaseClient.GetProperties"/>,
 2302        /// <see cref="StartCopyIncremental(Uri, string, PageBlobRequestConditions, CancellationToken)"/>,
 2303        /// and <see cref="BlobBaseClient.Delete"/>.  The copied snapshots may
 2304        /// be read and deleted as usual.
 2305        ///
 2306        /// An incremental copy is performed asynchronously on the service and
 2307        /// must be polled for completion.  You can poll
 2308        /// <see cref="BlobBaseClient.GetProperties"/> and check
 2309        /// <see cref="BlobProperties.CopyStatus"/> to determine when the copy
 2310        /// has completed.  When the copy completes, the destination blob will
 2311        /// contain a new snapshot.  The <see cref="BlobBaseClient.GetProperties"/>
 2312        /// operation returns the snapshot time of the newly created snapshot.
 2313        ///
 2314        /// The first time an incremental copy is performed on a destination
 2315        /// blob, a new blob is created with a snapshot that is fully copied
 2316        /// from the source.  Each subsequent call to <see cref="StartCopyIncremental(Uri, string, PageBlobRequestCondit
 2317        /// will create a new snapshot by copying only the differential
 2318        /// changes from the previously copied snapshot.  The differential
 2319        /// changes are computed on the server by issuing a <see cref="GetPageRanges"/>
 2320        /// call on the source blob snapshot with prevSnapshot set to the most
 2321        /// recently copied snapshot. Therefore, the same restrictions on
 2322        /// <see cref="GetPageRanges"/> apply to
 2323        /// <see cref="StartCopyIncremental(Uri, string, PageBlobRequestConditions, CancellationToken)"/>.
 2324        /// Specifically, snapshots must be copied in ascending order and if
 2325        /// the source blob is recreated using <see cref="UploadPages"/> or
 2326        /// <see cref="BlobBaseClient.StartCopyFromUri(Uri, Metadata, AccessTier?, BlobRequestConditions, BlobRequestCon
 2327        /// then  <see cref="StartCopyIncremental(Uri, string, PageBlobRequestConditions, CancellationToken)"/>
 2328        /// on new snapshots will fail.
 2329        ///
 2330        /// The additional storage space consumed by the copied snapshot is
 2331        /// the size of the differential data transferred during the copy.
 2332        /// This can be determined by performing a
 2333        /// <see cref="GetPageRangesDiff"/>
 2334        /// call on the snapshot to compare it to the previous snapshot.
 2335        /// </remarks>
 2336        public virtual CopyFromUriOperation StartCopyIncremental(
 2337            Uri sourceUri,
 2338            string snapshot,
 2339            PageBlobRequestConditions conditions = default,
 2340            CancellationToken cancellationToken = default)
 2341        {
 562342            Response<BlobCopyInfo> response = StartCopyIncrementalInternal(
 562343                sourceUri,
 562344                snapshot,
 562345                conditions,
 562346                false, // async
 562347                cancellationToken)
 562348                .EnsureCompleted();
 422349            return new CopyFromUriOperation(
 422350                this,
 422351                response.Value.CopyId,
 422352                response.GetRawResponse(),
 422353                cancellationToken);
 2354        }
 2355
 2356        /// <summary>
 2357        /// The <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestConditions, CancellationToken)"/>
 2358        /// operation starts copying a snapshot of the sourceUri page blob to
 2359        /// this page blob.  The snapshot is copied such that only the
 2360        /// differential changes between the previously copied snapshot are
 2361        /// transferred to the destination. The copied snapshots are complete
 2362        /// copies of the original snapshot and can be read or copied from as
 2363        /// usual.  You can check the <see cref="BlobProperties.CopyStatus"/>
 2364        /// returned from the <see cref="BlobBaseClient.GetPropertiesAsync"/>
 2365        /// to determine if thecopy has completed.
 2366        ///
 2367        /// For more information, see
 2368        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/incremental-copy-blob">
 2369        /// Incremental Copy Blob</see> and
 2370        /// <see href="https://docs.microsoft.com/azure/virtual-machines/windows/incremental-snapshots">
 2371        /// Back up Azure unmanaged VM disks with incremental snapshots</see>.
 2372        /// </summary>
 2373        /// <param name="sourceUri">
 2374        /// Specifies the to the source page blob as a <see cref="Uri"/> up to
 2375        /// 2 KB in length.  The source blob must either be public or must be
 2376        /// authenticated via a shared access signature.
 2377        /// </param>
 2378        /// <param name="snapshot">
 2379        /// The name of a snapshot to start copying from
 2380        /// sourceUri.
 2381        /// </param>
 2382        /// <param name="conditions">
 2383        /// Optional <see cref="PageBlobRequestConditions"/> to add
 2384        /// conditions on the incremental copy into this page blob.
 2385        /// </param>
 2386        /// <param name="cancellationToken">
 2387        /// Optional <see cref="CancellationToken"/> to propagate
 2388        /// notifications that the operation should be cancelled.
 2389        /// </param>
 2390        /// <returns>
 2391        /// A <see cref="CopyFromUriOperation"/> describing the
 2392        /// state of the incremental copy operation.
 2393        /// </returns>
 2394        /// <remarks>
 2395        /// A <see cref="RequestFailedException"/> will be thrown if
 2396        /// a failure occurs.
 2397        ///
 2398        /// The destination of an incremental copy must either not exist, or
 2399        /// must have been created with a previous incremental copy from the
 2400        /// same source blob.  Once created, the destination blob is
 2401        /// permanently associated with the source and may only be used for
 2402        /// incremental copies.
 2403        ///
 2404        /// The <see cref="BlobBaseClient.GetPropertiesAsync"/>,
 2405        /// <see cref="BlobContainerClient.GetBlobsAsync"/>, and
 2406        /// <see cref="BlobContainerClient.GetBlobsByHierarchyAsync"/>
 2407        /// operations indicate whether the blob is an incremental copy blob
 2408        /// created in this way.  Incremental copy blobs may not be downloaded
 2409        /// directly.  The only supported operations are
 2410        /// <see cref="BlobBaseClient.GetPropertiesAsync"/>,
 2411        /// <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestConditions, CancellationToken)"/>,
 2412        /// and  <see cref="BlobBaseClient.DeleteAsync"/>.  The copied
 2413        /// snapshots may be read and deleted as usual.
 2414        ///
 2415        /// An incremental copy is performed asynchronously on the service and
 2416        /// must be polled for completion.  You can poll
 2417        /// <see cref="BlobBaseClient.GetPropertiesAsync"/> and check
 2418        /// <see cref="BlobProperties.CopyStatus"/> to determine when the copy
 2419        /// has completed.  When the copy completes, the destination blob will
 2420        /// contain a new snapshot.  The <see cref="BlobBaseClient.GetPropertiesAsync"/>
 2421        /// operation returns the snapshot time of the newly created snapshot.
 2422        ///
 2423        /// The first time an incremental copy is performed on a destination
 2424        /// blob, a new blob is created with a snapshot that is fully copied
 2425        /// from the source.  Each subsequent call to <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestC
 2426        /// will create a new snapshot by copying only the differential
 2427        /// changes from the previously copied snapshot.  The differential
 2428        /// changes are computed on the server by issuing a <see cref="GetPageRangesAsync"/>
 2429        /// call on the source blob snapshot with prevSnapshot set to the most
 2430        /// recently copied snapshot. Therefore, the same restrictions on
 2431        /// <see cref="GetPageRangesAsync"/> apply to
 2432        /// <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestConditions, CancellationToken)"/>.
 2433        /// Specifically, snapshots must be copied in ascending order and if
 2434        /// the source blob is recreated using <see cref="UploadPagesAsync"/> or
 2435        /// <see cref="BlobBaseClient.StartCopyFromUriAsync(Uri, Metadata, AccessTier?, BlobRequestConditions, BlobReque
 2436        /// then <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestConditions, CancellationToken)"/>
 2437        /// on new snapshots will fail.
 2438        ///
 2439        /// The additional storage space consumed by the copied snapshot is
 2440        /// the size of the differential data transferred during the copy.
 2441        /// This can be determined by performing a
 2442        /// <see cref="GetPageRangesDiffAsync"/>
 2443        /// call on the snapshot to compare it to the previous snapshot.
 2444        /// </remarks>
 2445        public virtual async Task<CopyFromUriOperation> StartCopyIncrementalAsync(
 2446            Uri sourceUri,
 2447            string snapshot,
 2448            PageBlobRequestConditions conditions = default,
 2449            CancellationToken cancellationToken = default)
 2450        {
 562451            Response<BlobCopyInfo> response = await StartCopyIncrementalInternal(
 562452                sourceUri,
 562453                snapshot,
 562454                conditions,
 562455                true, // async
 562456                cancellationToken)
 562457                .ConfigureAwait(false);
 422458            return new CopyFromUriOperation(
 422459                this,
 422460                response.Value.CopyId,
 422461                response.GetRawResponse(),
 422462                cancellationToken);
 422463        }
 2464
 2465        /// <summary>
 2466        /// The <see cref="StartCopyIncrementalInternal"/> operation starts
 2467        /// copying a snapshot of the
 2468        /// sourceUri page blob to this page blob.  The
 2469        /// snapshot is copied such that only the differential changes between
 2470        /// the previously copied snapshot are transferred to the destination.
 2471        /// The copied snapshots are complete copies of the original snapshot
 2472        /// and can be read or copied from as usual.  You can check the
 2473        /// <see cref="BlobProperties.CopyStatus"/> returned from the
 2474        /// <see cref="BlobBaseClient.GetPropertiesAsync"/> to determine if the
 2475        /// copy has completed.
 2476        ///
 2477        /// For more information, see
 2478        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/incremental-copy-blob">
 2479        /// Incremental Copy Blob</see> and
 2480        /// <see href="https://docs.microsoft.com/azure/virtual-machines/windows/incremental-snapshots">
 2481        /// Back up Azure unmanaged VM disks with incremental snapshots</see>.
 2482        /// </summary>
 2483        /// <param name="sourceUri">
 2484        /// Specifies the to the source page blob as a <see cref="Uri"/> up to
 2485        /// 2 KB in length.  The source blob must either be public or must be
 2486        /// authenticated via a shared access signature.
 2487        /// </param>
 2488        /// <param name="snapshot">
 2489        /// The name of a snapshot to start copying from
 2490        /// sourceUri.
 2491        /// </param>
 2492        /// <param name="conditions">
 2493        /// Optional <see cref="PageBlobRequestConditions"/> to add
 2494        /// conditions on the incremental copy into this page blob.
 2495        /// </param>
 2496        /// <param name="async">
 2497        /// Whether to invoke the operation asynchronously.
 2498        /// </param>
 2499        /// <param name="cancellationToken">
 2500        /// Optional <see cref="CancellationToken"/> to propagate
 2501        /// notifications that the operation should be cancelled.
 2502        /// </param>
 2503        /// <returns>
 2504        /// A <see cref="Response{BlobCopyInfo}"/> describing the
 2505        /// state of the incremental copy operation.
 2506        /// </returns>
 2507        /// <remarks>
 2508        /// A <see cref="RequestFailedException"/> will be thrown if
 2509        /// a failure occurs.
 2510        ///
 2511        /// The destination of an incremental copy must either not exist, or
 2512        /// must have been created with a previous incremental copy from the
 2513        /// same source blob.  Once created, the destination blob is
 2514        /// permanently associated with the source and may only be used for
 2515        /// incremental copies.
 2516        ///
 2517        /// The <see cref="BlobBaseClient.GetPropertiesAsync"/>,
 2518        /// <see cref="BlobContainerClient.GetBlobsAsync"/>, and
 2519        /// <see cref="BlobContainerClient.GetBlobsByHierarchyAsync"/>
 2520        /// operations indicate whether the blob is an incremental copy blob
 2521        /// created in this way.  Incremental copy blobs may not be downloaded
 2522        /// directly.  The only supported operations are
 2523        /// <see cref="BlobBaseClient.GetPropertiesAsync"/>,
 2524        /// <see cref="StartCopyIncremental(Uri, string, PageBlobRequestConditions, CancellationToken)"/>,
 2525        /// and  <see cref="BlobBaseClient.DeleteAsync"/>.  The copied
 2526        /// snapshots may be read and deleted as usual.
 2527        ///
 2528        /// An incremental copy is performed asynchronously on the service and
 2529        /// must be polled for completion.  You can poll
 2530        /// <see cref="BlobBaseClient.GetPropertiesAsync"/> and check
 2531        /// <see cref="BlobProperties.CopyStatus"/> to determine when the copy
 2532        /// has completed.  When the copy completes, the destination blob will
 2533        /// contain a new snapshot.  The <see cref="BlobBaseClient.GetPropertiesAsync"/>
 2534        /// operation returns the snapshot time of the newly created snapshot.
 2535        ///
 2536        /// The first time an incremental copy is performed on a destination
 2537        /// blob, a new blob is created with a snapshot that is fully copied
 2538        /// from the source.  Each subsequent call to <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestC
 2539        /// will create a new snapshot by copying only the differential
 2540        /// changes from the previously copied snapshot.  The differential
 2541        /// changes are computed on the server by issuing a <see cref="GetPageRangesAsync"/>
 2542        /// call on the source blob snapshot with prevSnapshot set to the most
 2543        /// recently copied snapshot. Therefore, the same restrictions on
 2544        /// <see cref="GetPageRangesAsync"/> apply to
 2545        /// <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestConditions, CancellationToken)"/>.
 2546        /// Specifically, snapshots must be copied in ascending order and if
 2547        /// the source blob is recreated using <see cref="UploadPagesAsync"/>
 2548        /// or  <see cref="BlobBaseClient.StartCopyFromUriAsync(Uri, Metadata, AccessTier?, BlobRequestConditions, BlobR
 2549        /// then <see cref="StartCopyIncrementalAsync(Uri, string, PageBlobRequestConditions, CancellationToken)"/>
 2550        /// on new snapshots will fail.
 2551        ///
 2552        /// The additional storage space consumed by the copied snapshot is
 2553        /// the size of the differential data transferred during the copy.
 2554        /// This can be determined by performing a
 2555        /// <see cref="GetPageRangesDiffInternal"/>
 2556        /// call on the snapshot to compare it to the previous snapshot.
 2557        /// </remarks>
 2558        private async Task<Response<BlobCopyInfo>> StartCopyIncrementalInternal(
 2559            Uri sourceUri,
 2560            string snapshot,
 2561            PageBlobRequestConditions conditions,
 2562            bool async,
 2563            CancellationToken cancellationToken)
 2564        {
 1122565            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 2566            {
 2567                Pipeline.LogMethodEnter(
 2568                    nameof(PageBlobClient),
 2569                    message:
 2570                    $"{nameof(Uri)}: {Uri}\n" +
 2571                    $"{nameof(sourceUri)}: {sourceUri}\n" +
 2572                    $"{nameof(snapshot)}: {snapshot}\n" +
 2573                    $"{nameof(conditions)}: {conditions}");
 2574                try
 2575                {
 2576                    // Create copySource Uri
 1122577                    PageBlobClient pageBlobUri = new PageBlobClient(
 1122578                        sourceUri,
 1122579                        Pipeline,
 1122580                        Version,
 1122581                        ClientDiagnostics,
 1122582                        CustomerProvidedKey,
 1122583                        EncryptionScope).WithSnapshot(snapshot);
 2584
 1122585                    return await BlobRestClient.PageBlob.CopyIncrementalAsync(
 1122586                        ClientDiagnostics,
 1122587                        Pipeline,
 1122588                        Uri,
 1122589                        copySource: pageBlobUri.Uri,
 1122590                        version: Version.ToVersionString(),
 1122591                        ifModifiedSince: conditions?.IfModifiedSince,
 1122592                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1122593                        ifMatch: conditions?.IfMatch,
 1122594                        ifNoneMatch: conditions?.IfNoneMatch,
 1122595                        ifTags: conditions?.TagConditions,
 1122596                        async: async,
 1122597                        operationName: $"{nameof(PageBlobClient)}.{nameof(StartCopyIncremental)}",
 1122598                        cancellationToken: cancellationToken)
 1122599                        .ConfigureAwait(false);
 2600                }
 282601                catch (Exception ex)
 2602                {
 2603                    Pipeline.LogException(ex);
 282604                    throw;
 2605                }
 2606                finally
 2607                {
 2608                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 2609                }
 2610            }
 842611        }
 2612        #endregion StartCopyIncremental
 2613
 2614        #region UploadPagesFromUri
 2615        /// <summary>
 2616        /// The <see cref="UploadPagesFromUri"/> operation writes a range
 2617        /// of pages to a page blob where the contents are read from
 2618        /// sourceUri.
 2619        ///
 2620        /// For more information, see
 2621        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/put-page-from-url">
 2622        /// Put Page From URL</see>.
 2623        /// </summary>
 2624        /// <param name="sourceUri">
 2625        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 2626        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 2627        /// blob.  The source blob must either be public or must be
 2628        /// authenticated via a shared access signature.  If the source blob
 2629        /// is public, no authentication is required to perform the operation.
 2630        /// </param>
 2631        /// <param name="sourceRange">
 2632        /// Optionally only upload the bytes of the blob in the
 2633        /// sourceUri in the specified range.
 2634        /// </param>
 2635        /// <param name="range">
 2636        /// Specifies the range to be written as a page. Both the start and
 2637        /// end of the range must be specified and can be up to 4MB in size.
 2638        /// Given that pages must be aligned with 512-byte boundaries, the
 2639        /// start of the range must be a modulus of 512 and the end of the
 2640        /// range must be a modulus of 512 â€“ 1.  Examples of valid byte ranges
 2641        /// are 0-511, 512-1023, etc.
 2642        /// </param>
 2643        /// <param name="sourceContentHash">
 2644        /// Optional MD5 hash of the page block content from the
 2645        /// sourceUri.  This hash is used to verify the
 2646        /// integrity of the block during transport of the data from the Uri.
 2647        /// When this hash is specified, the storage service compares the hash
 2648        /// of the content that has arrived from the sourceUri
 2649        /// with this value.  Note that this md5 hash is not stored with the
 2650        /// blob.  If the two hashes do not match, the operation will fail
 2651        /// with a <see cref="RequestFailedException"/>.
 2652        /// </param>
 2653        /// <param name="conditions">
 2654        /// Optional <see cref="AppendBlobRequestConditions"/> to add
 2655        /// conditions on the copying of data to this page blob.
 2656        /// </param>
 2657        /// <param name="sourceConditions">
 2658        /// Optional <see cref="AppendBlobRequestConditions"/> to add
 2659        /// conditions on the copying of data from this source blob.
 2660        /// </param>
 2661        /// <param name="cancellationToken">
 2662        /// Optional <see cref="CancellationToken"/> to propagate
 2663        /// notifications that the operation should be cancelled.
 2664        /// </param>
 2665        /// <returns>
 2666        /// A <see cref="Response{PageInfo}"/> describing the
 2667        /// state of the updated pages.
 2668        /// </returns>
 2669        /// <remarks>
 2670        /// A <see cref="RequestFailedException"/> will be thrown if
 2671        /// a failure occurs.
 2672        /// </remarks>
 2673        public virtual Response<PageInfo> UploadPagesFromUri(
 2674            Uri sourceUri,
 2675            HttpRange sourceRange,
 2676            HttpRange range,
 2677            byte[] sourceContentHash = default,
 2678            PageBlobRequestConditions conditions = default,
 2679            PageBlobRequestConditions sourceConditions = default,
 2680            CancellationToken cancellationToken = default) =>
 682681            UploadPagesFromUriInternal(
 682682                sourceUri,
 682683                sourceRange,
 682684                range,
 682685                sourceContentHash,
 682686                conditions,
 682687                sourceConditions,
 682688                false, // async
 682689                cancellationToken)
 682690                .EnsureCompleted();
 2691
 2692        /// <summary>
 2693        /// The <see cref="UploadPagesFromUriAsync"/> operation writes a range
 2694        /// of pages to a page blob where the contents are read from
 2695        /// sourceUri.
 2696        ///
 2697        /// For more information, see
 2698        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/put-page-from-url">
 2699        /// Put Page From URL</see>.
 2700        /// </summary>
 2701        /// <param name="sourceUri">
 2702        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 2703        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 2704        /// blob.  The source blob must either be public or must be
 2705        /// authenticated via a shared access signature.  If the source blob
 2706        /// is public, no authentication is required to perform the operation.
 2707        /// </param>
 2708        /// <param name="sourceRange">
 2709        /// Optionally only upload the bytes of the blob in the
 2710        /// sourceUri in the specified range.
 2711        /// </param>
 2712        /// <param name="range">
 2713        /// Specifies the range to be written as a page. Both the start and
 2714        /// end of the range must be specified and can be up to 4MB in size.
 2715        /// Given that pages must be aligned with 512-byte boundaries, the
 2716        /// start of the range must be a modulus of 512 and the end of the
 2717        /// range must be a modulus of 512 â€“ 1.  Examples of valid byte ranges
 2718        /// are 0-511, 512-1023, etc.
 2719        /// </param>
 2720        /// <param name="sourceContentHash">
 2721        /// Optional MD5 hash of the page block content from the
 2722        /// sourceUri.  This hash is used to verify the
 2723        /// integrity of the block during transport of the data from the Uri.
 2724        /// When this hash is specified, the storage service compares the hash
 2725        /// of the content that has arrived from the sourceUri
 2726        /// with this value.  Note that this md5 hash is not stored with the
 2727        /// blob.  If the two hashes do not match, the operation will fail
 2728        /// with a <see cref="RequestFailedException"/>.
 2729        /// </param>
 2730        /// <param name="conditions">
 2731        /// Optional <see cref="AppendBlobRequestConditions"/> to add
 2732        /// conditions on the copying of data to this page blob.
 2733        /// </param>
 2734        /// <param name="sourceConditions">
 2735        /// Optional <see cref="AppendBlobRequestConditions"/> to add
 2736        /// conditions on the copying of data from this source blob.
 2737        /// </param>
 2738        /// <param name="cancellationToken">
 2739        /// Optional <see cref="CancellationToken"/> to propagate
 2740        /// notifications that the operation should be cancelled.
 2741        /// </param>
 2742        /// <returns>
 2743        /// A <see cref="Response{PageInfo}"/> describing the
 2744        /// state of the updated pages.
 2745        /// </returns>
 2746        /// <remarks>
 2747        /// A <see cref="RequestFailedException"/> will be thrown if
 2748        /// a failure occurs.
 2749        /// </remarks>
 2750        public virtual async Task<Response<PageInfo>> UploadPagesFromUriAsync(
 2751            Uri sourceUri,
 2752            HttpRange sourceRange,
 2753            HttpRange range,
 2754            byte[] sourceContentHash = default,
 2755            PageBlobRequestConditions conditions = default,
 2756            PageBlobRequestConditions sourceConditions = default,
 2757            CancellationToken cancellationToken = default) =>
 682758            await UploadPagesFromUriInternal(
 682759                sourceUri,
 682760                sourceRange,
 682761                range,
 682762                sourceContentHash,
 682763                conditions,
 682764                sourceConditions,
 682765                true, // async
 682766                cancellationToken)
 682767                .ConfigureAwait(false);
 2768
 2769        /// <summary>
 2770        /// The <see cref="UploadPagesFromUriInternal"/> operation writes a
 2771        /// range of pages to a page blob where the contents are read from
 2772        /// sourceUri.
 2773        ///
 2774        /// For more information, see
 2775        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/put-page-from-url">
 2776        /// Put Page From URL</see>.
 2777        /// </summary>
 2778        /// <param name="sourceUri">
 2779        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 2780        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 2781        /// blob.  The source blob must either be public or must be
 2782        /// authenticated via a shared access signature.  If the source blob
 2783        /// is public, no authentication is required to perform the operation.
 2784        /// </param>
 2785        /// <param name="sourceRange">
 2786        /// Optionally only upload the bytes of the blob in the
 2787        /// sourceUri in the specified range.
 2788        /// </param>
 2789        /// <param name="range">
 2790        /// Specifies the range to be written as a page. Both the start and
 2791        /// end of the range must be specified and can be up to 4MB in size.
 2792        /// Given that pages must be aligned with 512-byte boundaries, the
 2793        /// start of the range must be a modulus of 512 and the end of the
 2794        /// range must be a modulus of 512 â€“ 1.  Examples of valid byte ranges
 2795        /// are 0-511, 512-1023, etc.
 2796        /// </param>
 2797        /// <param name="sourceContentHash">
 2798        /// Optional MD5 hash of the page block content from the
 2799        /// sourceUri.  This hash is used to verify the
 2800        /// integrity of the block during transport of the data from the Uri.
 2801        /// When this hash is specified, the storage service compares the hash
 2802        /// of the content that has arrived from the sourceUri
 2803        /// with this value.  Note that this md5 hash is not stored with the
 2804        /// blob.  If the two hashes do not match, the operation will fail
 2805        /// with a <see cref="RequestFailedException"/>.
 2806        /// </param>
 2807        /// <param name="conditions">
 2808        /// Optional <see cref="AppendBlobRequestConditions"/> to add
 2809        /// conditions on the copying of data to this page blob.
 2810        /// </param>
 2811        /// <param name="sourceConditions">
 2812        /// Optional <see cref="AppendBlobRequestConditions"/> to add
 2813        /// conditions on the copying of data from this source blob.
 2814        /// </param>
 2815        /// <param name="async">
 2816        /// Whether to invoke the operation asynchronously.
 2817        /// </param>
 2818        /// <param name="cancellationToken">
 2819        /// Optional <see cref="CancellationToken"/> to propagate
 2820        /// notifications that the operation should be cancelled.
 2821        /// </param>
 2822        /// <returns>
 2823        /// A <see cref="Response{PageInfo}"/> describing the
 2824        /// state of the updated pages.
 2825        /// </returns>
 2826        /// <remarks>
 2827        /// A <see cref="RequestFailedException"/> will be thrown if
 2828        /// a failure occurs.
 2829        /// </remarks>
 2830        private async Task<Response<PageInfo>> UploadPagesFromUriInternal(
 2831            Uri sourceUri,
 2832            HttpRange sourceRange,
 2833            HttpRange range,
 2834            byte[] sourceContentHash,
 2835            PageBlobRequestConditions conditions,
 2836            PageBlobRequestConditions sourceConditions,
 2837            bool async,
 2838            CancellationToken cancellationToken)
 2839        {
 1362840            using (Pipeline.BeginLoggingScope(nameof(PageBlobClient)))
 2841            {
 2842                Pipeline.LogMethodEnter(
 2843                    nameof(PageBlobClient),
 2844                    message:
 2845                    $"{nameof(Uri)}: {Uri}\n" +
 2846                    $"{nameof(sourceUri)}: {sourceUri}");
 2847                try
 2848                {
 1362849                    return await BlobRestClient.PageBlob.UploadPagesFromUriAsync(
 1362850                        ClientDiagnostics,
 1362851                        Pipeline,
 1362852                        Uri,
 1362853                        sourceUri: sourceUri,
 1362854                        sourceRange: sourceRange.ToString(),
 1362855                        sourceContentHash: sourceContentHash,
 1362856                        contentLength: default,
 1362857                        version: Version.ToVersionString(),
 1362858                        timeout: default,
 1362859                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 1362860                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 1362861                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 1362862                        encryptionScope: EncryptionScope,
 1362863                        range: range.ToString(),
 1362864                        leaseId: conditions?.LeaseId,
 1362865                        ifSequenceNumberLessThanOrEqualTo: conditions?.IfSequenceNumberLessThanOrEqual,
 1362866                        ifSequenceNumberLessThan: conditions?.IfSequenceNumberLessThan,
 1362867                        ifSequenceNumberEqualTo: conditions?.IfSequenceNumberEqual,
 1362868                        ifModifiedSince: conditions?.IfModifiedSince,
 1362869                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1362870                        ifMatch: conditions?.IfMatch,
 1362871                        ifNoneMatch: conditions?.IfNoneMatch,
 1362872                        ifTags: conditions?.TagConditions,
 1362873                        sourceIfModifiedSince: sourceConditions?.IfModifiedSince,
 1362874                        sourceIfUnmodifiedSince: sourceConditions?.IfUnmodifiedSince,
 1362875                        sourceIfMatch: sourceConditions?.IfMatch,
 1362876                        sourceIfNoneMatch: sourceConditions?.IfNoneMatch,
 1362877                        async: async,
 1362878                        operationName: $"{nameof(PageBlobClient)}.{nameof(UploadPagesFromUri)}",
 1362879                        cancellationToken: cancellationToken)
 1362880                        .ConfigureAwait(false);
 2881                }
 562882                catch (Exception ex)
 2883                {
 2884                    Pipeline.LogException(ex);
 562885                    throw;
 2886                }
 2887                finally
 2888                {
 2889                    Pipeline.LogMethodExit(nameof(PageBlobClient));
 2890                }
 2891            }
 802892        }
 2893        #endregion UploadPagesFromUri
 2894    }
 2895
 2896    /// <summary>
 2897    /// Add easy to discover methods to <see cref="BlobContainerClient"/> for
 2898    /// creating <see cref="PageBlobClient"/> instances.
 2899    /// </summary>
 2900    public static partial class SpecializedBlobExtensions
 2901    {
 2902        /// <summary>
 2903        /// Create a new <see cref="PageBlobClient"/> object by
 2904        /// concatenating <paramref name="blobName"/> to
 2905        /// the end of the <paramref name="client"/>'s
 2906        /// <see cref="BlobContainerClient.Uri"/>. The new
 2907        /// <see cref="PageBlobClient"/>
 2908        /// uses the same request policy pipeline as the
 2909        /// <see cref="BlobContainerClient"/>.
 2910        /// </summary>
 2911        /// <param name="client">The <see cref="BlobContainerClient"/>.</param>
 2912        /// <param name="blobName">The name of the page blob.</param>
 2913        /// <returns>A new <see cref="PageBlobClient"/> instance.</returns>
 2914        public static PageBlobClient GetPageBlobClient(
 2915            this BlobContainerClient client,
 2916            string blobName)
 2917        {
 2918            if (client.ClientSideEncryption != default)
 2919            {
 2920                throw Errors.ClientSideEncryption.TypeNotSupported(typeof(PageBlobClient));
 2921            }
 2922
 2923            BlobUriBuilder blobUriBuilder = new BlobUriBuilder(client.Uri)
 2924            {
 2925                BlobName = blobName
 2926            };
 2927
 2928            return new PageBlobClient(
 2929                blobUriBuilder.ToUri(),
 2930                client.Pipeline,
 2931                client.Version,
 2932                client.ClientDiagnostics,
 2933                client.CustomerProvidedKey,
 2934                client.EncryptionScope);
 2935        }
 2936    }
 2937}