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;
                }
            }
        }
示例#3
0
        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;
            }
        }
示例#4
0
        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();
            }
        }
示例#5
0
        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;
            }
        }