private async Task ReadFromBlobAsync(UnmanagedMemoryStream stream, CloudPageBlob blob, long sourceAddress, long destinationAddress, uint readLength) { Debug.WriteLine($"AzureStorageDevice.ReadFromBlobAsync Called target={blob.Name}"); try { await BlobManager.AsyncStorageReadMaxConcurrency.WaitAsync().ConfigureAwait(false); int numAttempts = 0; while (true) // retry loop { numAttempts++; try { if (this.underLease) { await this.BlobManager.ConfirmLeaseAsync().ConfigureAwait(false); } Debug.WriteLine($"starting download target={blob.Name} readLength={readLength} sourceAddress={sourceAddress}"); if (readLength > 0) { await blob.DownloadRangeToStreamAsync(stream, sourceAddress, readLength, accessCondition : null, options : this.BlobRequestOptionsWithoutRetry, operationContext : null, cancellationToken : this.BlobManager.CancellationToken) .ConfigureAwait(BlobManager.ConfigureAwaitForStorage); } Debug.WriteLine($"finished download target={blob.Name} readLength={readLength} sourceAddress={sourceAddress}"); if (stream.Position != readLength) { throw new InvalidDataException($"wrong amount of data received from page blob, expected={readLength}, actual={stream.Position}"); } break; } catch (StorageException e) when(this.underLease && IsTransientStorageError(e) && numAttempts < BlobManager.MaxRetries) { TimeSpan nextRetryIn = TimeSpan.FromSeconds(1 + Math.Pow(2, (numAttempts - 1))); this.BlobManager?.HandleBlobError(nameof(ReadFromBlobAsync), $"could not write to page blob, will retry in {nextRetryIn}s", blob?.Name, e, false); await Task.Delay(nextRetryIn).ConfigureAwait(false); stream.Seek(0, SeekOrigin.Begin); // must go back to original position before retrying continue; } catch (Exception exception) when(!IsFatal(exception)) { this.BlobManager?.HandleBlobError(nameof(ReadFromBlobAsync), "could not read from page blob", blob?.Name, exception, false); throw; } } } finally { BlobManager.AsyncStorageReadMaxConcurrency.Release(); stream.Dispose(); } }
async Task ReadFromBlobAsync(UnmanagedMemoryStream stream, CloudPageBlob blob, long sourceAddress, uint readLength) { using (stream) { long offset = 0; while (readLength > 0) { var length = Math.Min(readLength, MAX_DOWNLOAD_SIZE); await this.BlobManager.PerformWithRetriesAsync( BlobManager.AsynchronousStorageReadMaxConcurrency, true, "CloudPageBlob.DownloadRangeToStreamAsync", "ReadFromDevice", $"readLength={length} sourceAddress={sourceAddress + offset}", blob.Name, 1000 + (int)length / 1000, true, async (numAttempts) => { if (numAttempts > 0) { stream.Seek(offset, SeekOrigin.Begin); // must go back to original position before retrying } if (length > 0) { var blobRequestOptions = (numAttempts > 1 || length == MAX_DOWNLOAD_SIZE) ? BlobManager.BlobRequestOptionsDefault : BlobManager.BlobRequestOptionsAggressiveTimeout; await blob .DownloadRangeToStreamAsync(stream, sourceAddress + offset, length, accessCondition: null, options: blobRequestOptions, operationContext: null, cancellationToken: this.PartitionErrorHandler.Token) .ConfigureAwait(false); } if (stream.Position != offset + length) { throw new InvalidDataException($"wrong amount of data received from page blob, expected={length}, actual={stream.Position}"); } return(length); }); readLength -= length; offset += length; } } }
public async Task DownloadRangeToStreamAsync(Stream stream, long offset, int length) { Require.NotNull("stream", stream); Require.ZeroOrGreater("offset", offset); Require.Positive("length", length); try { await _blob.DownloadRangeToStreamAsync(stream, offset, length).ConfigureAwait(false); } catch (StorageException ex) { // if forbidden, then we might have an expired SAS token if (ex.RequestInformation != null && ex.RequestInformation.HttpStatusCode == 403) { throw new ForbiddenException("Can't read blob", ex); } throw; } }
private async Task ReadFromBlobAsync(UnmanagedMemoryStream stream, CloudPageBlob blob, long sourceAddress, long destinationAddress, uint readLength) { Debug.WriteLine($"AzureStorageDevice.ReadFromBlobAsync Called target={blob.Name}"); try { if (this.underLease) { Debug.WriteLine($"confirm lease"); await this.BlobManager.ConfirmLeaseAsync().ConfigureAwait(false); Debug.WriteLine($"confirm lease done"); } Debug.WriteLine($"starting download target={blob.Name} readLength={readLength} sourceAddress={sourceAddress}"); await blob.DownloadRangeToStreamAsync(stream, sourceAddress, readLength, accessCondition : null, options : this.BlobRequestOptions, operationContext : null, cancellationToken : this.BlobManager.CancellationToken); Debug.WriteLine($"finished download target={blob.Name} readLength={readLength} sourceAddress={sourceAddress}"); if (stream.Position != readLength) { throw new InvalidDataException($"wrong amount of data received from page blob, expected={readLength}, actual={stream.Position}"); } } catch (Exception exception) { this.BlobManager?.HandleBlobError(nameof(ReadFromBlobAsync), "could not read from page blob", blob?.Name, exception, true); throw new FasterException(nameof(ReadFromBlobAsync) + "could not read from page blob " + blob?.Name, exception); } finally { stream.Dispose(); } }
public async Task DownloadRangeToStreamAsync(Stream stream, long offset, int length) { Require.NotNull("stream", stream); Require.ZeroOrGreater("offset", offset); Require.Positive("length", length); try { var context = new OperationContext(); context.SendingRequest += (sender, e) => { e.Request.Headers["if-match"] = "*"; }; await _blob.DownloadRangeToStreamAsync(stream, offset, length, null, null, context).ConfigureAwait(false); } catch (StorageException ex) { // if forbidden, then we might have an expired SAS token if (ex.RequestInformation != null && ex.RequestInformation.HttpStatusCode == 403) { throw new ForbiddenException("Can't read blob", ex); } throw; } }