/// <summary>
        /// Demonstrates how to do backup using incremental snapshots. See this article on
        /// backing up Azure virtual machine disks with incremental snapshots:
        /// https://azure.microsoft.com/en-us/documentation/articles/storage-incremental-snapshots/
        /// The article also describes how to restore a disk from incremental snapshots.
        /// </summary>
        /// <returns>Task</returns>
        public static async Task IncrementalSnapshotBackupAsync()
        {
            const int TotalBlobSize     = 512 * 6;              // The total amount of data in the blob
            const int UpdateWriteSize   = 512 * 2;              // The amount of data to update in the blob
            const int UpdateWriteOffset = 512 * 2;              // The offset at which to write updated data
            const int ClearPagesOffset  = 512 * 5;              // The offset at which to begin clearing page data
            const int ClearPagesSize    = 512;                  // The amount of data to clear in the blob

            string SimulationID  = Guid.NewGuid().ToString();   // The simulation ID
            string ContainerName = "container-" + SimulationID; // The name of the primary container
            string PageBlobName  = "binary-data";               // The name of the primary page blob

            // Retrieve storage account information from connection strings
            // How to create storage connection strings - http://msdn.microsoft.com/en-us/library/azure/ee758697.aspx
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
                CloudConfigurationManager.GetSetting("StorageConnectionString"));
            CloudStorageAccount backupStorageAccount = CloudStorageAccount.Parse(
                CloudConfigurationManager.GetSetting("BackupStorageConnectionString"));

            // Create blob clients for interacting with the blob service.
            CloudBlobClient blobClient       = storageAccount.CreateCloudBlobClient();
            CloudBlobClient backupBlobClient = backupStorageAccount.CreateCloudBlobClient();

            // Create containers for organizing blobs within the storage accounts.
            container       = blobClient.GetContainerReference(ContainerName);
            backupContainer = backupBlobClient.GetContainerReference("copy-of-" + ContainerName);
            try
            {
                // The call below will fail if the sample is configured to use the storage emulator
                // in the connection string, but the emulator is not running.
                BlobRequestOptions requestOptions = new BlobRequestOptions()
                {
                    RetryPolicy = new NoRetry()
                };
                await container.CreateIfNotExistsAsync(requestOptions, null);

                await backupContainer.CreateIfNotExistsAsync(requestOptions, null);
            }
            catch (StorageException)
            {
                Console.WriteLine("If you are running with the default connection string, please make " +
                                  "sure you have started the storage emulator. Press the Windows key and type Azure " +
                                  "Storage to select and run it from the list of applications - then restart the sample.");
                Console.ReadLine();
                throw;
            }

            // Create, write to, and snapshot a page blob in the newly created container.
            CloudPageBlob pageBlob = container.GetPageBlobReference(PageBlobName);
            await pageBlob.CreateAsync(TotalBlobSize);

            byte[] samplePagedata = new byte[TotalBlobSize];
            Random random         = new Random();

            random.NextBytes(samplePagedata);
            await pageBlob.UploadFromByteArrayAsync(samplePagedata, 0, samplePagedata.Length);

            CloudPageBlob pageBlobSnap = await pageBlob.CreateSnapshotAsync();

            // Create a blob in the backup account
            CloudPageBlob pageBlobBackup = backupContainer.GetPageBlobReference("copy-of-" + PageBlobName);

            // Copy to the blob in the backup account. Notice that the <isServiceCopy> flag here is
            // set to 'false'. This forces data to be first downloaded from the source, then uploaded
            // to the destination. If <isServiceCopy> were set to 'true' we could avoid the I/O of
            // downloading and then uploading, but could not guarantee  that the copy completed even
            // after the local task completed. Since the remainder of this sample depends on the
            // successful completion of this operation, we must set <isServiceCopy> to 'false.'
            await TransferManager.CopyAsync(pageBlobSnap, pageBlobBackup, false);

            // Snapshot the backup copy
            CloudPageBlob pageBlobBackupSnap = await pageBlob.CreateSnapshotAsync();

            // Change the contents of the original page blob (note: we must convert the byte array to a
            // stream in order to write to a non-zero offset in the page blob) and snapshot.
            byte[] updatePageData = new byte[UpdateWriteSize];
            random.NextBytes(updatePageData);
            Stream updatePageDataStream = new MemoryStream(updatePageData);
            await pageBlob.WritePagesAsync(updatePageDataStream, UpdateWriteOffset, null);

            await pageBlob.ClearPagesAsync(ClearPagesOffset, ClearPagesSize);

            CloudPageBlob newPageBlobSnap = await pageBlob.CreateSnapshotAsync();

            // Get the incremental changes and write to the backup.
            IEnumerable <PageDiffRange> changedPages =
                await newPageBlobSnap.GetPageRangesDiffAsync(pageBlobSnap.SnapshotTime.Value);

            foreach (PageDiffRange pageRange in changedPages)
            {
                // If this page range is cleared, remove the old data in the backup.
                if (pageRange.IsClearedPageRange)
                {
                    await pageBlobBackup.ClearPagesAsync(
                        pageRange.StartOffset, pageRange.EndOffset - pageRange.StartOffset + 1);
                }

                // If this page range is not cleared, write the new data to the backup.
                else
                {
                    byte[] toWrite = new byte[pageRange.EndOffset - pageRange.StartOffset + 1];
                    await newPageBlobSnap.DownloadRangeToByteArrayAsync(
                        toWrite, 0, pageRange.StartOffset, pageRange.EndOffset - pageRange.StartOffset + 1);

                    Stream toWriteStream = new MemoryStream(toWrite);
                    await pageBlobBackup.WritePagesAsync(toWriteStream, pageRange.StartOffset, null);
                }
            }
            // Snapshot the backup blob and delete the old snapshot from the primary account
            CloudPageBlob pageBlobBackupSnapv2 = await pageBlobBackup.CreateSnapshotAsync();

            await pageBlobSnap.DeleteAsync();
        }