protected async Task <InternalPageBlobSizeInfo> PreparePageBlobAsync(CloudPageBlob pageBlob, int sourceBufferByteCountToWrite, CancellationToken cancellationToken) { EnsureBlobExistsResult result = await this.EnsureBlobExistsAsync(pageBlob, byteCountToWrite : sourceBufferByteCountToWrite); InternalPageBlobSizeInfo sizeInfo; switch (result) { case EnsureBlobExistsResult.Created: sizeInfo = new InternalPageBlobSizeInfo(); break; case EnsureBlobExistsResult.AlreadyExisted: sizeInfo = await this.ResizePageBlobIfNeededAsync(pageBlob, sourceBufferByteCountToWrite, cancellationToken); break; default: throw new NotSupportedException($"Unrecognized enum value ({result}) returned from the method {nameof(this.EnsureBlobExistsAsync)}."); } return(sizeInfo); }
protected async Task <InternalPageBlobSizeInfo> ResizePageBlobIfNeededAsync(CloudPageBlob pageBlob, int sourceBufferByteCountToWrite, CancellationToken cancellationToken) { BlobProperties blobProperties = await this.GetPropertiesAsync(pageBlob, cancellationToken); int offsetOfLastPage = CalculateOffsetOfLastPage((int)blobProperties.Length); byte[] usedBytesFromLastPage = await this.GetUsedBytesWrittenToLastPageAsync(pageBlob, offsetOfLastPage, cancellationToken); var sizeInfo = new InternalPageBlobSizeInfo(offsetOfLastPage, usedBytesFromLastPage); int currentTotalBytesUsed = CalculateTotalBytesUsed((int)blobProperties.Length, usedBytesFromLastPage.Length); await this.ResizePageBlobIfNeededAsync(pageBlob, (int)blobProperties.Length, currentTotalBytesUsed, sourceBufferByteCountToWrite, cancellationToken); return(sizeInfo); }
internal async Task <BlobSegmentInfo> AppendImplAsync(Stream sourceStreamToWrite, CancellationToken?cancellationToken = null, Func <Task> concurrencyTestFunc = null) { if (cancellationToken == null) { cancellationToken = CancellationToken.None; } this.EnsureInitialized(); CloudPageBlob pageBlob = this.BlobContainer.GetPageBlobReference(this.BlobPath); // Note: We only force the use of a buffer here if the stream that is passed cannot seek. We need the // length to fill out the page with null characters, so it must support seeking unless we find a // different algorithm. if (!sourceStreamToWrite.CanSeek) { sourceStreamToWrite = await BuildMemoryStreamThatCanSeekAsync(sourceStreamToWrite, cancellationToken.Value); } InternalPageBlobSizeInfo pageBlobSizeInfo = await this.PreparePageBlobAsync(pageBlob, (int)sourceStreamToWrite.Length, cancellationToken.Value); Stream streamToWrite = BuildStreamOfPagesToWrite(sourceStreamToWrite, pageBlobSizeInfo); int byteOffset = pageBlobSizeInfo.OffsetOfLastPage + pageBlobSizeInfo.UsedBytesFromLastPage.Length; int streamLength = (int)sourceStreamToWrite.Length; if (concurrencyTestFunc != null) { await concurrencyTestFunc(); } await pageBlob.WritePagesAsync(streamToWrite, pageBlobSizeInfo.OffsetOfLastPage, null, CreateAccessCondition(pageBlob), this.RequestOptions, this.OperationContext, cancellationToken.Value); return(new BlobSegmentInfo(byteOffset, streamLength)); }
protected static Stream BuildStreamOfPagesToWrite(Stream sourceStreamToWrite, InternalPageBlobSizeInfo sizeInfo) { int updatedUsedByteCount = sizeInfo.UsedBytesFromLastPage.Length + (int)sourceStreamToWrite.Length; int updatedUsedToFullPageByteCount = CalculateBlobLengthThroughEndOfPage(updatedUsedByteCount); var streamForPreviouslyUsedBytes = new MemoryStream(sizeInfo.UsedBytesFromLastPage, false); if (updatedUsedByteCount == updatedUsedToFullPageByteCount) { return(new ConcatenatedStream(new[] { streamForPreviouslyUsedBytes, sourceStreamToWrite })); } var streamToFillOutLastPage = new MemoryStream(FullPageOfNullChars, 0, (int)(updatedUsedToFullPageByteCount - updatedUsedByteCount)); return(new ConcatenatedStream(new[] { streamForPreviouslyUsedBytes, sourceStreamToWrite, streamToFillOutLastPage })); }