private void RunUploadLoop(
            BlobTransferContext transferContext,
            FileStream fileStream,
            int numThreads)
        {
            SpinWait spinWait = new SpinWait();

            while (!transferContext.IsComplete && !transferContext.CancellationToken.IsCancellationRequested)
            {
                if (!transferContext.IsReadingOrWriting)
                {
                    DoSequentialRead(transferContext, fileStream);
                }

                if (!transferContext.IsComplete &&
                    transferContext.NumInProgressUploadDownloads < numThreads)
                {
                    TryUploadingBlocks(transferContext);
                }
                spinWait.SpinOnce();
            }

            while (transferContext.NumInProgressUploadDownloads > 0 || transferContext.IsReadingOrWriting)
            {
                spinWait.SpinOnce();
            }

            foreach (var memoryStream in transferContext.BufferStreams.Values)
            {
                memoryStream.Dispose();
            }

            transferContext.OnComplete();
        }
        private void BeginUploadStream(
            BlobTransferContext transferContext,
            KeyValuePair <long, int> startAndLength,
            MemoryStream memoryStream,
            byte[] streamBuffer)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            memoryStream.Seek(0, SeekOrigin.Begin);

            OperationContext operationContext = new OperationContext();

            operationContext.ClientRequestID = transferContext.ClientRequestId;

            Interlocked.Increment(ref transferContext.NumInProgressUploadDownloads);

            string blockId =
                Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "BlockId{0:d7}", (startAndLength.Key / transferContext.BlockSize))));

            memoryStream.SetLength(startAndLength.Value);

            transferContext.Blob.BeginPutBlock(
                blockId,
                memoryStream,
                null,
                AccessCondition.GenerateEmptyCondition(),
                transferContext.BlobRequestOptions,
                operationContext,
                ar =>
            {
                SuccessfulOrRetryableResult wasWriteSuccessful = EndPutBlock(transferContext, ar);
                Interlocked.Decrement(ref transferContext.NumInProgressUploadDownloads);

                if (wasWriteSuccessful.IsRetryable)
                {
                    BeginUploadStream(transferContext, startAndLength, memoryStream, streamBuffer);
                    return;
                }

                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);

                if (!wasWriteSuccessful.IsSuccessful)
                {
                    return;
                }

                Interlocked.Add(ref transferContext.BytesBlobIOCompleted, startAndLength.Value);

                InvokeProgressCallback(transferContext, transferContext.BytesBlobIOCompleted, startAndLength.Value);

                if (transferContext.BytesBlobIOCompleted >= transferContext.Length)
                {
                    BeginPutBlockList(transferContext);
                }
            },
                state: null);
        }
示例#3
0
        private void TryDownloadingBlocks(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            byte[] streamBuffer = transferContext.MemoryManager.RequireBuffer();

            if (streamBuffer == null)
            {
                return;
            }

            MemoryStream memoryStream = GetMemoryStream(transferContext.BufferStreams, streamBuffer);

            KeyValuePair <long, int> startAndLength;

            if (transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
            {
                BeginDownloadStream(transferContext, memoryStream, startAndLength, streamBuffer);
            }
            else
            {
                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
            }
        }
示例#4
0
        private void RunUploadLoop(
            BlobTransferContext transferContext,
            Stream fileStream,
            int numThreads)
        {
            SpinWait spinWait = new SpinWait();

            while (!transferContext.IsComplete && !transferContext.CancellationToken.IsCancellationRequested)
            {
                if (!transferContext.IsReadingOrWriting)
                {
                    DoSequentialRead(transferContext, fileStream);
                }

                if (!transferContext.IsComplete &&
                    transferContext.NumInProgressUploadDownloads < numThreads)
                {
                    TryUploadingBlocks(transferContext);
                }
                spinWait.SpinOnce();
            }

            while (transferContext.NumInProgressUploadDownloads > 0 || transferContext.IsReadingOrWriting)
            {
                spinWait.SpinOnce();
            }

            //Release any buffers that are still in queue to be written to file but could not because there was
            // a complete signal for this file upload due to some error in the one of the other block uploads in the same transfer context.
            //If this is not cleaned, used buffers will hit the cap of 16 and future uploads will hang for lack of memory buffers.
            for (int currentBlock = transferContext.NextFileIOBlock; currentBlock <= transferContext.BlocksForFileIO.Count(); currentBlock++)
            {
                byte[] buffer = null;

                if (transferContext.BlocksForFileIO.TryGetValue(currentBlock, out buffer) && (buffer != null))
                {
                    try
                    {
                        transferContext.MemoryManager.ReleaseBuffer(buffer);
                    }
                    catch (ArgumentException ex)
                    {
                        Debug.WriteLine("Exception occured while releasing memory buffer ", ex.Message);
                    }
                }
            }
            foreach (var memoryStream in transferContext.BufferStreams.Values)
            {
                memoryStream.Dispose();
            }

            transferContext.OnComplete();
        }
示例#5
0
        protected SuccessfulOrRetryableResult IsActionSuccessfulOrRetryable <T>(
            BlobTransferContext transferContext,
            Func <T> action,
            out T returnValue)
        {
            T value = default(T);

            SuccessfulOrRetryableResult result =
                IsActionSuccessfulOrRetryable(
                    transferContext,
                    () => value = action());

            returnValue = value;

            return(result);
        }
        private void BeginPutBlockList(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            OperationContext operationContext = new OperationContext();

            operationContext.ClientRequestID = transferContext.ClientRequestId;

            List <string> blockids = new List <string>();

            for (int i = 0; i < (transferContext.Length + transferContext.BlockSize - 1) / transferContext.BlockSize; i++)
            {
                blockids.Add(
                    Convert.ToBase64String(
                        Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "BlockId{0:d7}", i))));
            }

            transferContext.Blob.BeginPutBlockList(
                blockids,
                AccessCondition.GenerateEmptyCondition(),
                transferContext.BlobRequestOptions,
                operationContext,
                ar =>
            {
                SuccessfulOrRetryableResult wasWriteSuccessful = EndPutBlockList(transferContext, ar);
                Interlocked.Decrement(ref transferContext.NumInProgressUploadDownloads);

                if (wasWriteSuccessful.IsRetryable)
                {
                    BeginPutBlockList(transferContext);
                    return;
                }

                transferContext.IsComplete = true;
            },
                state: null);
        }
示例#7
0
        protected void InvokeProgressCallback(BlobTransferContext transferContext, long bytesProcessed, long lastBlockSize)
        {
            if (transferContext == null)
            {
                throw new ArgumentNullException("transferContext");
            }

            int    progress = (int)((double)bytesProcessed / transferContext.Length * 100);
            double speed    = _uploadDownloadSpeedCalculator.UpdateCountersAndCalculateSpeed(bytesProcessed);

            BlobTransferProgressChangedEventArgs eArgs = new BlobTransferProgressChangedEventArgs(
                bytesProcessed,
                lastBlockSize,
                transferContext.Length,
                progress,
                speed,
                transferContext.Blob.Uri,
                transferContext.LocalFilePath,
                null);

            OnTaskProgressChanged(eArgs);
        }
        private void TryUploadingBlocks(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (transferContext.NextFileIOBlock >= transferContext.BlocksForFileIO.Count)
            {
                return;
            }

            byte[] streamBuffer;
            int    nextBlock = transferContext.NextFileIOBlock;

            if (transferContext.BlocksForFileIO.TryGetValue(nextBlock, out streamBuffer) &&
                streamBuffer != null)
            {
                Interlocked.Increment(ref transferContext.NextFileIOBlock);

                MemoryStream memoryStream = GetMemoryStream(transferContext.BufferStreams, streamBuffer);

                long beginFilePosition     = (long)nextBlock * transferContext.BlockSize;
                long nextBeginFilePosition = beginFilePosition + transferContext.BlockSize;

                nextBeginFilePosition =
                    nextBeginFilePosition > transferContext.Length
                        ? transferContext.Length
                        : nextBeginFilePosition;

                int bytesToRead = (int)(nextBeginFilePosition - beginFilePosition);

                BeginUploadStream(
                    transferContext,
                    new KeyValuePair <long, int>(beginFilePosition, bytesToRead),
                    memoryStream,
                    streamBuffer);
            }
        }
        private void TryDownloadingBlocks(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }
            //This is where memory is allocated, any code after this should make sure releasebuffer happens on all positive/negative conditions
            byte[] streamBuffer = transferContext.MemoryManager.RequireBuffer();

            if (streamBuffer == null)
            {
                return;
            }
            // Catch any exceptions and cleanup the buffer. Otherwise uncleaned buffers will result in hang for future
            // downloads as memorymanager is being shared.
            // Also mark the transfer as complete and add exceptions to the transfercontext exception list.
            try
            {
                MemoryStream             memoryStream = GetMemoryStream(transferContext.BufferStreams, streamBuffer);
                KeyValuePair <long, int> startAndLength;
                if (transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
                {
                    BeginDownloadStream(transferContext, memoryStream, startAndLength, streamBuffer);
                }
                else
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                }
            }
            catch (Exception ex)
            {
                transferContext.IsComplete = true;
                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                transferContext.Exceptions.Add(ex);
            }
        }
示例#10
0
        private void DoSequentialWrite(
            BlobTransferContext transferContext,
            FileStream stream)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            byte[] buffer = null;

            if (transferContext.BlocksForFileIO.TryGetValue(transferContext.NextFileIOBlock, out buffer) && buffer != null)
            {
                transferContext.IsReadingOrWriting = true;
                long endOfRange = transferContext.Length + transferContext.InitialOffset;

                long beginFilePosition = (long)transferContext.NextFileIOBlock * transferContext.BlockSize + transferContext.InitialOffset;
                beginFilePosition = beginFilePosition > endOfRange
                    ? endOfRange
                    : beginFilePosition;

                long nextBeginFilePosition = (transferContext.NextFileIOBlock + 1) * (long)transferContext.BlockSize + transferContext.InitialOffset;
                nextBeginFilePosition = nextBeginFilePosition > endOfRange
                                            ? endOfRange
                                            : nextBeginFilePosition;

                int bytesToWrite = (int)(nextBeginFilePosition - beginFilePosition);

                ApplyEncryptionTransform(transferContext.FileEncryption, transferContext.InitializationVector, beginFilePosition, buffer, bytesToWrite);

                stream.BeginWrite(
                    buffer,
                    0,
                    bytesToWrite,
                    result3 =>
                {
                    SuccessfulOrRetryableResult wasWriteSuccessful =
                        IsActionSuccessfulOrRetryable(transferContext, () => stream.EndWrite(result3));

                    transferContext.MemoryManager.ReleaseBuffer(buffer);

                    if (!wasWriteSuccessful.IsSuccessful)
                    {
                        transferContext.IsReadingOrWriting = false;
                        return;
                    }

                    transferContext.NextFileIOBlock++;

                    Interlocked.Add(ref transferContext.BytesWrittenOrReadToFile, bytesToWrite);

                    InvokeProgressCallback(transferContext, transferContext.BytesWrittenOrReadToFile, bytesToWrite);

                    transferContext.IsReadingOrWriting = false;

                    if (transferContext.BytesWrittenOrReadToFile >= transferContext.Length)
                    {
                        transferContext.IsComplete = true;
                        transferContext.OnComplete();
                    }
                },
                    null);
            }
        }
        private void BeginUploadStream(
            BlobTransferContext transferContext,
            KeyValuePair<long, int> startAndLength,
            MemoryStream memoryStream,
            byte[] streamBuffer)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            memoryStream.Seek(0, SeekOrigin.Begin);

            OperationContext operationContext = new OperationContext();
            operationContext.ClientRequestID = transferContext.ClientRequestId;

            Interlocked.Increment(ref transferContext.NumInProgressUploadDownloads);

            string blockId =
                Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "BlockId{0:d7}", (startAndLength.Key / transferContext.BlockSize))));

            memoryStream.SetLength(startAndLength.Value);

            transferContext.Blob.BeginPutBlock(
                blockId,
                memoryStream,
                null,
                AccessCondition.GenerateEmptyCondition(),
                transferContext.BlobRequestOptions,
                operationContext,
                ar =>
                {
                    SuccessfulOrRetryableResult wasWriteSuccessful = EndPutBlock(transferContext, ar);
                    Interlocked.Decrement(ref transferContext.NumInProgressUploadDownloads);

                    if (wasWriteSuccessful.IsRetryable)
                    {
                        BeginUploadStream(transferContext, startAndLength, memoryStream, streamBuffer);
                        return;
                    }

                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);

                    if (!wasWriteSuccessful.IsSuccessful)
                    {
                        return;
                    }

                    Interlocked.Add(ref transferContext.BytesBlobIOCompleted, startAndLength.Value);

                    InvokeProgressCallback(transferContext, transferContext.BytesBlobIOCompleted, startAndLength.Value);

                    if (transferContext.BytesBlobIOCompleted >= transferContext.Length)
                    {
                        BeginPutBlockList(transferContext);
                    }

                },
                state: null);
        }
示例#12
0
        private void DownloadFileFromBlob(
            Uri uri,
            string localFile,
            FileEncryption fileEncryption,
            ulong initializationVector,
            CloudBlobClient client,
            CancellationToken cancellationToken,
            IRetryPolicy retryPolicy,
            Func <string> getSharedAccessSignature,
            bool shouldDoFileIO = true,
            long start          = 0,
            long length         = -1)
        {
            int numThreads = Environment.ProcessorCount * ParallelUploadDownloadThreadCountMultiplier;
            ManualResetEvent   downloadCompletedSignal = new ManualResetEvent(false);
            BlobRequestOptions blobRequestOptions      = new BlobRequestOptions {
                RetryPolicy = retryPolicy
            };

            CloudBlockBlob blob = GetCloudBlockBlob(uri, client, retryPolicy, getSharedAccessSignature);

            long initialOffset  = start;
            long sizeToDownload = blob.Properties.Length;

            if (length != -1)
            {
                if (length > blob.Properties.Length)
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Size {0} is beyond the Length of Blob {1}", length, blob.Properties.Length));
                }

                if (start + length > blob.Properties.Length)
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Size {0} plus offset {1} is beyond the Length of Blob {2}", length, start, blob.Properties.Length));
                }

                sizeToDownload = length;
            }

            if (sizeToDownload == 0)
            {
                using (FileStream stream =
                           new FileStream(
                               localFile,
                               FileMode.OpenOrCreate,
                               FileAccess.Write,
                               FileShare.Read
                               ))
                {
                }

                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    null,
                    BlobTransferType.Download,
                    localFile,
                    uri);
            }
            else
            {
                int blockSize = GetBlockSize(blob.Properties.Length);

                BlobTransferContext transferContext = new BlobTransferContext();

                transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(sizeToDownload, blockSize, ref numThreads, initialOffset);

                transferContext.BlocksForFileIO = new ConcurrentDictionary <int, byte[]>();
                for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                {
                    transferContext.BlocksForFileIO[i] = null;
                }
                transferContext.BlockSize         = blockSize;
                transferContext.CancellationToken = cancellationToken;
                transferContext.Blob = blob;
                transferContext.BlobRequestOptions = blobRequestOptions;
                transferContext.Length             = sizeToDownload;

                transferContext.LocalFilePath            = localFile;
                transferContext.OnComplete               = () => downloadCompletedSignal.Set();
                transferContext.MemoryManager            = MemoryManagerFactory.GetMemoryManager(blockSize);
                transferContext.Client                   = client;
                transferContext.RetryPolicy              = retryPolicy;
                transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                transferContext.ShouldDoFileIO           = shouldDoFileIO;
                transferContext.BufferStreams            = new ConcurrentDictionary <byte[], MemoryStream>();
                transferContext.ClientRequestId          = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                transferContext.Exceptions               = new ConcurrentBag <Exception>();
                transferContext.FileEncryption           = fileEncryption;
                transferContext.InitializationVector     = initializationVector;
                transferContext.InitialOffset            = start;

                using (FileStream stream = new FileStream(
                           transferContext.LocalFilePath,
                           FileMode.OpenOrCreate,
                           FileAccess.Write,
                           FileShare.Read
                           ))
                {
                    stream.SetLength(sizeToDownload);
                    RunDownloadLoop(transferContext, stream, numThreads);
                }

                transferContext.MemoryManager.ReleaseUnusedBuffers();

                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    transferContext.Exceptions != null && transferContext.Exceptions.Count > 0 ? new AggregateException(transferContext.Exceptions) : null,
                    BlobTransferType.Download,
                    localFile,
                    uri);
            }
        }
        private void DoSequentialRead(
            BlobTransferContext transferContext,
            FileStream stream,
            byte[] streamBuffer = null,
            KeyValuePair <long, int>?inputStartAndLength = null)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (streamBuffer == null)
            {
                streamBuffer = transferContext.MemoryManager.RequireBuffer();
            }

            if (streamBuffer == null)
            {
                return;
            }

            KeyValuePair <long, int> startAndLength;

            if (inputStartAndLength == null)
            {
                if (!transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                    return;
                }
            }
            else
            {
                startAndLength = inputStartAndLength.Value;
            }

            if (!transferContext.PartialFileIOState.ContainsKey(startAndLength.Key))
            {
                transferContext.PartialFileIOState[startAndLength.Key] = 0;
            }

            transferContext.IsReadingOrWriting = true;

            long beginFilePosition     = startAndLength.Key;
            long nextBeginFilePosition = startAndLength.Key + transferContext.BlockSize;

            nextBeginFilePosition =
                nextBeginFilePosition > transferContext.Length
                    ? transferContext.Length
                    : nextBeginFilePosition;

            beginFilePosition = beginFilePosition + transferContext.PartialFileIOState[startAndLength.Key];
            int bytesToRead = (int)(nextBeginFilePosition - beginFilePosition);

            stream.BeginRead(
                streamBuffer,
                transferContext.PartialFileIOState[startAndLength.Key],
                bytesToRead,
                result3 =>
            {
                int bytesRead;

                SuccessfulOrRetryableResult wasReadSuccessful =
                    IsActionSuccessfulOrRetryable(transferContext, () => stream.EndRead(result3), out bytesRead);

                if (!wasReadSuccessful.IsSuccessful)
                {
                    transferContext.IsReadingOrWriting = false;

                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                }
                else if (bytesRead != bytesToRead)
                {
                    transferContext.PartialFileIOState[startAndLength.Key] += bytesRead;

                    DoSequentialRead(transferContext, stream, streamBuffer, startAndLength);
                }
                else
                {
                    transferContext.IsReadingOrWriting = false;

                    ApplyEncryptionTransform(
                        transferContext.FileEncryption,
                        Path.GetFileName(transferContext.LocalFilePath),
                        beginFilePosition,
                        streamBuffer,
                        bytesToRead);

                    transferContext.BlocksForFileIO[(int)(startAndLength.Key / transferContext.BlockSize)] = streamBuffer;
                }
            },
                null);
        }
        private void UploadFileToBlob(
            CancellationToken cancellationToken,
            Uri uri,
            string localFile,
            string contentType,
            string subDirectory,
            FileEncryption fileEncryption,
            CloudBlobClient client,
            IRetryPolicy retryPolicy,
            Func<string> getSharedAccessSignature,
            int parallelTransferThreadCount,
            bool shouldDoFileIO = true)
        {
            BlobTransferContext transferContext = new BlobTransferContext();
            transferContext.Exceptions = new ConcurrentBag<Exception>();
            try
            {
                    ManualResetEvent uploadCompletedSignal = new ManualResetEvent(false);
                    BlobRequestOptions blobRequestOptions = new BlobRequestOptions
                    {
                        RetryPolicy = retryPolicy,
                        ServerTimeout = TimeSpan.FromSeconds(90)
                    };
                    //attempt to open the file first so that we throw an exception before getting into the async work
                    using (FileStream fileStream = new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                    }
                    CloudBlockBlob blob = GetCloudBlockBlob(uri, client, subDirectory, localFile, contentType,
                        getSharedAccessSignature);
                    BlobPolicyActivationWait(() => blob.DeleteIfExists(options: blobRequestOptions));

                    FileInfo file = new FileInfo(localFile);
                    long fileSize = file.Length;
                    transferContext.Length = fileSize;
                    transferContext.LocalFilePath = localFile;
                    transferContext.OnComplete = () => uploadCompletedSignal.Set();
                    transferContext.Blob = blob;
                    transferContext.FileEncryption = fileEncryption;
                    if (fileSize == 0)
                    {
                        blob.UploadFromByteArray(new byte[1], 0, 0, options: blobRequestOptions);
                    }
                    else if (fileSize < cloudBlockBlobUploadDownloadSizeLimit)
                    {
                        AccessCondition accessCondition = AccessCondition.GenerateEmptyCondition();
                        OperationContext operationContext = new OperationContext();
                        operationContext.ClientRequestID = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                        using (FileStream fileStream = new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                               using (var memoryStream = new MemoryStream())
                                     {
                                         fileStream.CopyTo(memoryStream);
                                         byte[] fileContent = memoryStream.ToArray();
                                         ApplyEncryptionTransform(
                                                     transferContext.FileEncryption,
                                                     Path.GetFileName(transferContext.LocalFilePath),
                                                     0,
                                                     fileContent,
                                                     Convert.ToInt32(fileStream.Length));
                                         using (var uploadMemoryStream = new MemoryStream(fileContent))
                                         {
                                             blob.UploadFromStream(uploadMemoryStream, accessCondition: accessCondition, options: blobRequestOptions, operationContext: operationContext);
                                         }
                                     }
                        }
                        InvokeProgressCallback(transferContext, fileSize, fileSize);
                        transferContext.OnComplete();
                    }
                    else
                    {
                        int numThreads = parallelTransferThreadCount;
                        int blockSize = GetBlockSize(fileSize);

                        transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(fileSize, blockSize, ref numThreads);

                        transferContext.BlocksForFileIO = new ConcurrentDictionary<int, byte[]>();
                        for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                        {
                            transferContext.BlocksForFileIO[i] = null;
                        }
                        transferContext.BlockSize = blockSize;
                        transferContext.CancellationToken = cancellationToken;
                        transferContext.BlobRequestOptions = blobRequestOptions;
                        transferContext.MemoryManager = MemoryManagerFactory.GetMemoryManager(blockSize);
                        transferContext.Client = client;
                        transferContext.RetryPolicy = retryPolicy;
                        transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                        transferContext.ShouldDoFileIO = shouldDoFileIO;
                        transferContext.BufferStreams = new ConcurrentDictionary<byte[], MemoryStream>();
                        transferContext.ClientRequestId = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                        transferContext.ContentType = contentType;
                        transferContext.BlobSubFolder = subDirectory;
                        transferContext.NextFileIOBlock = 0;
                        transferContext.PartialFileIOState = new ConcurrentDictionary<long, int>();

                        using (
                            FileStream stream = new FileStream(localFile, FileMode.Open, FileAccess.Read,
                                FileShare.ReadWrite))
                        {
                            RunUploadLoop(transferContext, stream, numThreads);
                        }
                }
            }
            catch (Exception e)
            {
                //Add the exception to the exception list.
                transferContext.Exceptions.Add(e);
            }
            finally
            {
                // We should to be able to releaseunusedbuffers if memorymanager was initialized by then
                if (transferContext.MemoryManager != null)
                {
                    transferContext.MemoryManager.ReleaseUnusedBuffers();

                }
                //TaskCompletedCallback should be called to populate exceptions if relevant and other eventargs for the user.
                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    transferContext.Exceptions != null && transferContext.Exceptions.Count > 0
                        ? new AggregateException(transferContext.Exceptions)
                        : null,
                    BlobTransferType.Upload,
                    localFile,
                    uri);
            }
        }
        private void DownloadFileFromBlob(
            Uri uri,
            string localFile,
            FileEncryption fileEncryption,
            ulong initializationVector,
            CloudBlobClient client,
            CancellationToken cancellationToken,
            IRetryPolicy retryPolicy,
            Func <string> getSharedAccessSignature,
            bool shouldDoFileIO             = true,
            long start                      = 0,
            long length                     = -1,
            int parallelTransferThreadCount = 10)
        {
            ManualResetEvent   downloadCompletedSignal = new ManualResetEvent(false);
            BlobRequestOptions blobRequestOptions      = new BlobRequestOptions {
                RetryPolicy = retryPolicy
            };
            CloudBlockBlob      blob            = null;
            BlobTransferContext transferContext = new BlobTransferContext();

            transferContext.Exceptions = new ConcurrentBag <Exception>();

            try
            {
                blob = GetCloudBlockBlob(uri, client, retryPolicy, getSharedAccessSignature);

                long initialOffset  = start;
                long sizeToDownload = blob.Properties.Length;

                if (length != -1)
                {
                    if (length > blob.Properties.Length)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                                                                  "Size {0} is beyond the Length of Blob {1}", length, blob.Properties.Length));
                    }

                    if (start + length > blob.Properties.Length)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                                                                  "Size {0} plus offset {1} is beyond the Length of Blob {2}", length, start,
                                                                  blob.Properties.Length));
                    }

                    sizeToDownload = length;
                }
                transferContext.Length               = sizeToDownload;
                transferContext.LocalFilePath        = localFile;
                transferContext.OnComplete           = () => downloadCompletedSignal.Set();
                transferContext.Blob                 = blob;
                transferContext.FileEncryption       = fileEncryption;
                transferContext.InitializationVector = initializationVector;
                transferContext.InitialOffset        = start;

                if (sizeToDownload == 0)
                {
                    using (FileStream stream =
                               new FileStream(
                                   localFile,
                                   FileMode.OpenOrCreate,
                                   FileAccess.Write,
                                   FileShare.Read
                                   ))
                    {
                    }
                }
                else if (sizeToDownload < cloudBlockBlobUploadDownloadSizeLimit)
                {
                    AccessCondition  accessCondition  = AccessCondition.GenerateEmptyCondition();
                    OperationContext operationContext = new OperationContext();
                    operationContext.ClientRequestID = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                    using (FileStream fileStream = new FileStream(
                               transferContext.LocalFilePath,
                               FileMode.OpenOrCreate,
                               FileAccess.ReadWrite,
                               FileShare.Read
                               ))
                    {
                        blob.DownloadToStream(fileStream, accessCondition: accessCondition, options: blobRequestOptions, operationContext: operationContext);
                        if (fileEncryption != null)
                        {
                            using (MemoryStream msDecrypt = new MemoryStream())
                            {
                                //Using CryptoTransform APIs per Quintin's suggestion.
                                using (FileEncryptionTransform fileEncryptionTransform = fileEncryption.GetTransform(initializationVector, 0))
                                {
                                    fileStream.Position = 0;
                                    fileStream.CopyTo(msDecrypt);
                                    msDecrypt.Position  = 0;
                                    fileStream.Position = 0;
                                    using (CryptoStream csEncrypt = new CryptoStream(msDecrypt, fileEncryptionTransform, CryptoStreamMode.Read))
                                    {
                                        csEncrypt.CopyTo(fileStream);
                                    }
                                }
                            }
                        }
                    }
                    InvokeProgressCallback(transferContext, sizeToDownload, sizeToDownload);
                    transferContext.OnComplete();
                }
                else
                {
                    int numThreads = parallelTransferThreadCount;
                    int blockSize  = GetBlockSize(blob.Properties.Length);

                    transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(sizeToDownload, blockSize,
                                                                                  ref numThreads, initialOffset);

                    transferContext.BlocksForFileIO = new ConcurrentDictionary <int, byte[]>();
                    for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                    {
                        transferContext.BlocksForFileIO[i] = null;
                    }
                    transferContext.BlockSize                = blockSize;
                    transferContext.CancellationToken        = cancellationToken;
                    transferContext.BlobRequestOptions       = blobRequestOptions;
                    transferContext.MemoryManager            = MemoryManagerFactory.GetMemoryManager(blockSize);
                    transferContext.Client                   = client;
                    transferContext.RetryPolicy              = retryPolicy;
                    transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                    transferContext.ShouldDoFileIO           = shouldDoFileIO;
                    transferContext.BufferStreams            = new ConcurrentDictionary <byte[], MemoryStream>();
                    transferContext.ClientRequestId          = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);

                    using (FileStream stream = new FileStream(
                               transferContext.LocalFilePath,
                               FileMode.OpenOrCreate,
                               FileAccess.Write,
                               FileShare.Read
                               ))
                    {
                        stream.SetLength(sizeToDownload);
                        RunDownloadLoop(transferContext, stream, numThreads);
                    }
                }
            }
            catch (Exception e)
            {
                //Add the exception to the exception list.
                transferContext.Exceptions.Add(e);
            }
            finally
            {
                // We should to be able to releaseunusedbuffers if memorymanager was initialized by then
                if (transferContext.MemoryManager != null)
                {
                    transferContext.MemoryManager.ReleaseUnusedBuffers();
                }
                //TaskCompletedCallback should be called to populate exceptions if relevant and other eventargs for the user.
                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    transferContext.Exceptions != null && transferContext.Exceptions.Count > 0
                            ? new AggregateException(transferContext.Exceptions)
                            : null,
                    BlobTransferType.Download,
                    localFile,
                    uri);
            }
        }
        private void DownloadFileFromBlob(
            Uri uri,
            string localFile,
            FileEncryption fileEncryption,
            ulong initializationVector,
            CloudBlobClient client,
            CancellationToken cancellationToken,
            IRetryPolicy retryPolicy,
            Func<string> getSharedAccessSignature,
            bool shouldDoFileIO = true,
            long start = 0,
            long length = -1,
            int parallelTransferThreadCount = 10)
        {
            int numThreads = Environment.ProcessorCount * parallelTransferThreadCount;
            ManualResetEvent downloadCompletedSignal = new ManualResetEvent(false);
            BlobRequestOptions blobRequestOptions = new BlobRequestOptions { RetryPolicy = retryPolicy };
            CloudBlockBlob blob = null;
            BlobTransferContext transferContext = new BlobTransferContext();
            transferContext.Exceptions = new ConcurrentBag<Exception>();
            try
            {
                blob = GetCloudBlockBlob(uri, client, retryPolicy, getSharedAccessSignature);

                long initialOffset = start;
                long sizeToDownload = blob.Properties.Length;

                if (length != -1)
                {
                    if (length > blob.Properties.Length)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                            "Size {0} is beyond the Length of Blob {1}", length, blob.Properties.Length));
                    }

                    if (start + length > blob.Properties.Length)
                    {
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                            "Size {0} plus offset {1} is beyond the Length of Blob {2}", length, start,
                            blob.Properties.Length));
                    }

                    sizeToDownload = length;
                }
                if (sizeToDownload == 0)
                {
                    using (FileStream stream =
                        new FileStream(
                            localFile,
                            FileMode.OpenOrCreate,
                            FileAccess.Write,
                            FileShare.Read
                            ))
                    {
                    }

                }
                else
                {
                    int blockSize = GetBlockSize(blob.Properties.Length);

                    transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(sizeToDownload, blockSize,
                        ref numThreads, initialOffset);

                    transferContext.BlocksForFileIO = new ConcurrentDictionary<int, byte[]>();
                    for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                    {
                        transferContext.BlocksForFileIO[i] = null;
                    }
                    transferContext.BlockSize = blockSize;
                    transferContext.CancellationToken = cancellationToken;
                    transferContext.Blob = blob;
                    transferContext.BlobRequestOptions = blobRequestOptions;
                    transferContext.Length = sizeToDownload;

                    transferContext.LocalFilePath = localFile;
                    transferContext.OnComplete = () => downloadCompletedSignal.Set();
                    transferContext.MemoryManager = MemoryManagerFactory.GetMemoryManager(blockSize);
                    transferContext.Client = client;
                    transferContext.RetryPolicy = retryPolicy;
                    transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                    transferContext.ShouldDoFileIO = shouldDoFileIO;
                    transferContext.BufferStreams = new ConcurrentDictionary<byte[], MemoryStream>();
                    transferContext.ClientRequestId = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                    transferContext.FileEncryption = fileEncryption;
                    transferContext.InitializationVector = initializationVector;
                    transferContext.InitialOffset = start;

                    using (FileStream stream = new FileStream(
                        transferContext.LocalFilePath,
                        FileMode.OpenOrCreate,
                        FileAccess.Write,
                        FileShare.Read
                        ))
                    {
                        stream.SetLength(sizeToDownload);
                        RunDownloadLoop(transferContext, stream, numThreads);
                    }
                }
            }
            catch(Exception e)
            {
                //Add the exception to the exception list.
                transferContext.Exceptions.Add(e);
            }
            finally
            {
                 // We should to be able to releaseunusedbuffers if memorymanager was initialized by then
                if (transferContext.MemoryManager != null)
                {
                    transferContext.MemoryManager.ReleaseUnusedBuffers();
                }
                //TaskCompletedCallback should be called to populate exceptions if relevant and other eventargs for the user.
                    TaskCompletedCallback(
                        cancellationToken.IsCancellationRequested,
                        transferContext.Exceptions != null && transferContext.Exceptions.Count > 0
                            ? new AggregateException(transferContext.Exceptions)
                            : null,
                        BlobTransferType.Download,
                        localFile,
                        uri);
            }
        }
        private void RunUploadLoop(
            BlobTransferContext transferContext,
            FileStream fileStream,
            int numThreads)
        {
            SpinWait spinWait = new SpinWait();

            while (!transferContext.IsComplete && !transferContext.CancellationToken.IsCancellationRequested)
            {
                if (!transferContext.IsReadingOrWriting)
                {
                    DoSequentialRead(transferContext, fileStream);
                }

                if (!transferContext.IsComplete &&
                    transferContext.NumInProgressUploadDownloads < numThreads)
                {
                    TryUploadingBlocks(transferContext);
                }
                spinWait.SpinOnce();
            }

            while (transferContext.NumInProgressUploadDownloads > 0 || transferContext.IsReadingOrWriting)
            {
                spinWait.SpinOnce();
            }

            //Release any buffers that are still in queue to be written to file but could not because there was
            // a complete signal for this file upload due to some error in the one of the other block uploads in the same transfer context.
            //If this is not cleaned, used buffers will hit the cap of 16 and future uploads will hang for lack of memory buffers.
            for (int currentBlock = transferContext.NextFileIOBlock; currentBlock <= transferContext.BlocksForFileIO.Count(); currentBlock++)
            {
                byte[] buffer = null;

                if (transferContext.BlocksForFileIO.TryGetValue(currentBlock, out buffer) && (buffer != null))
                {
                    try
                    {
                        transferContext.MemoryManager.ReleaseBuffer(buffer);
                    }
                    catch (ArgumentException ex)
                    {
                        Debug.WriteLine("Exception occured while releasing memory buffer ", ex.Message);
                    }

                }
            }
            foreach (var memoryStream in transferContext.BufferStreams.Values)
            {
                memoryStream.Dispose();
            }

            transferContext.OnComplete();
        }
        private void BeginDownloadStream(
            BlobTransferContext transferContext,
            MemoryStream memoryStream,
            KeyValuePair<long, int> startAndLength,
            byte[] streamBuffer)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            memoryStream.Seek(0, SeekOrigin.Begin);

            OperationContext operationContext = new OperationContext();
            operationContext.ClientRequestID = transferContext.ClientRequestId;

            Interlocked.Increment(ref transferContext.NumInProgressUploadDownloads);

            transferContext.Blob.BeginDownloadRangeToStream(
                memoryStream,
                startAndLength.Key,
                startAndLength.Value,
                AccessCondition.GenerateEmptyCondition(),
                transferContext.BlobRequestOptions,
                operationContext,
                ar =>
                {

                    SuccessfulOrRetryableResult wasWriteSuccessful = EndDownloadStream(transferContext, ar);

                    Interlocked.Decrement(ref transferContext.NumInProgressUploadDownloads);

                    if (wasWriteSuccessful.IsRetryable)
                    {
                        BeginDownloadStream(transferContext, memoryStream, startAndLength, streamBuffer);
                        return;
                    }

                    if (!wasWriteSuccessful.IsSuccessful)
                    {
                        transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                        return;
                    }
                    Interlocked.Add(ref transferContext.BytesBlobIOCompleted, startAndLength.Value);

                    TryDownloadingBlocks(transferContext);

                    if (transferContext.ShouldDoFileIO)
                    {
                        transferContext.BlocksForFileIO[(int)(startAndLength.Key / transferContext.BlockSize)] = streamBuffer;
                    }
                    else
                    {
                        transferContext.MemoryManager.ReleaseBuffer(streamBuffer);

                        if (transferContext.BytesBlobIOCompleted >= transferContext.Length)
                        {
                            transferContext.IsComplete = true;
                        }
                    }
                },
                null);
        }
        private void DoSequentialWrite(
            BlobTransferContext transferContext,
            FileStream stream)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            byte[] buffer = null;

            if (transferContext.BlocksForFileIO.TryGetValue(transferContext.NextFileIOBlock, out buffer) && buffer != null)
            {
                transferContext.IsReadingOrWriting = true;
                long endOfRange = transferContext.Length + transferContext.InitialOffset;

                long beginFilePosition = (long)transferContext.NextFileIOBlock * transferContext.BlockSize + transferContext.InitialOffset;
                beginFilePosition = beginFilePosition > endOfRange
                    ? endOfRange
                    : beginFilePosition;

                long nextBeginFilePosition = (transferContext.NextFileIOBlock + 1) * (long)transferContext.BlockSize + transferContext.InitialOffset;
                nextBeginFilePosition = nextBeginFilePosition > endOfRange
                                            ? endOfRange
                                            : nextBeginFilePosition;

                int bytesToWrite = (int)(nextBeginFilePosition - beginFilePosition);

                ApplyEncryptionTransform(transferContext.FileEncryption, transferContext.InitializationVector, beginFilePosition, buffer, bytesToWrite);

                stream.BeginWrite(
                    buffer,
                    0,
                    bytesToWrite,
                    result3 =>
                    {

                        SuccessfulOrRetryableResult wasWriteSuccessful =
                            IsActionSuccessfulOrRetryable(transferContext, () => stream.EndWrite(result3));

                        transferContext.MemoryManager.ReleaseBuffer(buffer);

                        if (!wasWriteSuccessful.IsSuccessful)
                        {
                            transferContext.IsReadingOrWriting = false;
                            return;
                        }

                        transferContext.NextFileIOBlock++;

                        Interlocked.Add(ref transferContext.BytesWrittenOrReadToFile, bytesToWrite);

                        InvokeProgressCallback(transferContext, transferContext.BytesWrittenOrReadToFile, bytesToWrite);

                        transferContext.IsReadingOrWriting = false;

                        if (transferContext.BytesWrittenOrReadToFile >= transferContext.Length)
                        {
                            transferContext.IsComplete = true;
                            transferContext.OnComplete();
                        }
                    },
                    null);
            }
        }
        private void UploadFileToBlob(
            CancellationToken cancellationToken, 
            Uri uri, 
            string localFile, 
            string contentType, 
            string subDirectory, 
            FileEncryption fileEncryption, 
            CloudBlobClient client, 
            IRetryPolicy retryPolicy, 
            Func<string> getSharedAccessSignature,
            bool shouldDoFileIO = true)
        {
            //attempt to open the file first so that we throw an exception before getting into the async work
            using (new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
            }

            SetConnectionLimits(uri);

            ManualResetEvent uploadCompletedSignal = new ManualResetEvent(false);
            BlobRequestOptions blobRequestOptions = new BlobRequestOptions
                {
                    RetryPolicy = retryPolicy,
                    ServerTimeout = TimeSpan.FromSeconds(90)
                };

            CloudBlockBlob blob = GetCloudBlockBlob(uri, client, subDirectory, localFile, contentType, getSharedAccessSignature);
            BlobPolicyActivationWait(() => blob.DeleteIfExists(options: blobRequestOptions));

            FileInfo file = new FileInfo(localFile);
            long fileSize = file.Length;

            if (fileSize == 0)
            {
                blob.UploadFromByteArray(new byte[1], 0, 0, options: blobRequestOptions);

                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    null,
                    BlobTransferType.Upload,
                    localFile,
                    uri);
            }
            else
            {
                int numThreads = Environment.ProcessorCount*ParallelUploadDownloadThreadCountMultiplier;
                int blockSize = GetBlockSize(fileSize);

                BlobTransferContext transferContext = new BlobTransferContext();
                transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(fileSize, blockSize, ref numThreads);

                transferContext.BlocksForFileIO = new ConcurrentDictionary<int, byte[]>();
                for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                {
                    transferContext.BlocksForFileIO[i] = null;
                }
                transferContext.BlockSize = blockSize;
                transferContext.CancellationToken = cancellationToken;
                transferContext.Blob = blob;
                transferContext.BlobRequestOptions = blobRequestOptions;
                transferContext.Length = fileSize;
                transferContext.LocalFilePath = localFile;
                transferContext.OnComplete = () => uploadCompletedSignal.Set();
                transferContext.MemoryManager = MemoryManagerFactory.GetMemoryManager(blockSize);
                transferContext.Client = client;
                transferContext.RetryPolicy = retryPolicy;
                transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                transferContext.ShouldDoFileIO = shouldDoFileIO;
                transferContext.BufferStreams = new ConcurrentDictionary<byte[], MemoryStream>();
                transferContext.ClientRequestId = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                transferContext.Exceptions = new ConcurrentBag<Exception>();
                transferContext.FileEncryption = fileEncryption;
                transferContext.ContentType = contentType;
                transferContext.BlobSubFolder = subDirectory;
                transferContext.NextFileIOBlock = 0;
                transferContext.PartialFileIOState = new ConcurrentDictionary<long, int>();

                using (
                    FileStream stream = new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    RunUploadLoop(transferContext, stream, numThreads);
                }

                transferContext.MemoryManager.ReleaseUnusedBuffers();

                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    transferContext.Exceptions != null && transferContext.Exceptions.Count > 0 ? new AggregateException(transferContext.Exceptions) : null,
                    BlobTransferType.Upload,
                    localFile,
                    uri);
            }
        }
        private void RunUploadLoop(
            BlobTransferContext transferContext,
            FileStream fileStream,
            int numThreads)
        {
            SpinWait spinWait = new SpinWait();

            while (!transferContext.IsComplete && !transferContext.CancellationToken.IsCancellationRequested)
            {
                if (!transferContext.IsReadingOrWriting)
                {
                    DoSequentialRead(transferContext, fileStream);
                }

                if (!transferContext.IsComplete &&
                    transferContext.NumInProgressUploadDownloads < numThreads)
                {
                    TryUploadingBlocks(transferContext);
                }
                spinWait.SpinOnce();
            }

            while (transferContext.NumInProgressUploadDownloads > 0 || transferContext.IsReadingOrWriting)
            {
                spinWait.SpinOnce();
            }

            foreach (var memoryStream in transferContext.BufferStreams.Values)
            {
                memoryStream.Dispose();
            }

            transferContext.OnComplete();
        }
        private void DoSequentialRead(
            BlobTransferContext transferContext,
            FileStream stream,
            byte[] streamBuffer = null,
            KeyValuePair<long, int>? inputStartAndLength = null)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (streamBuffer == null)
            {
                streamBuffer = transferContext.MemoryManager.RequireBuffer();
            }

            if (streamBuffer == null)
            {
                return;
            }

            KeyValuePair<long, int> startAndLength;

            if (inputStartAndLength == null)
            {
                if (!transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                    return;
                }
            }
            else
            {
                startAndLength = inputStartAndLength.Value;
            }

            if (!transferContext.PartialFileIOState.ContainsKey(startAndLength.Key))
            {
                transferContext.PartialFileIOState[startAndLength.Key] = 0;
            }

            transferContext.IsReadingOrWriting = true;

            long beginFilePosition = startAndLength.Key;
            long nextBeginFilePosition = startAndLength.Key + transferContext.BlockSize;

            nextBeginFilePosition =
                nextBeginFilePosition > transferContext.Length
                    ? transferContext.Length
                    : nextBeginFilePosition;

            beginFilePosition = beginFilePosition + transferContext.PartialFileIOState[startAndLength.Key];
            int bytesToRead = (int)(nextBeginFilePosition - beginFilePosition);

            stream.BeginRead(
                streamBuffer,
                transferContext.PartialFileIOState[startAndLength.Key],
                bytesToRead,
                result3 =>
                    {
                        int bytesRead;

                        SuccessfulOrRetryableResult wasReadSuccessful =
                            IsActionSuccessfulOrRetryable(transferContext, () => stream.EndRead(result3), out bytesRead);

                        if (!wasReadSuccessful.IsSuccessful)
                        {
                            transferContext.IsReadingOrWriting = false;

                            transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                        }
                        else if (bytesRead != bytesToRead)
                        {
                            transferContext.PartialFileIOState[startAndLength.Key] += bytesRead;

                            DoSequentialRead(transferContext, stream, streamBuffer, startAndLength);
                        }
                        else
                        {
                            transferContext.IsReadingOrWriting = false;

                            ApplyEncryptionTransform(
                                transferContext.FileEncryption,
                                Path.GetFileName(transferContext.LocalFilePath),
                                beginFilePosition,
                                streamBuffer,
                                bytesToRead);

                            transferContext.BlocksForFileIO[(int) (startAndLength.Key/transferContext.BlockSize)] = streamBuffer;
                        }
                    },
                null);
        }
        private void DoSequentialRead(
            BlobTransferContext transferContext,
            FileStream stream,
            byte[] streamBuffer = null,
            KeyValuePair<long, int>? inputStartAndLength = null)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (streamBuffer == null)
            {
                streamBuffer = transferContext.MemoryManager.RequireBuffer();
            }

            if (streamBuffer == null)
            {
                return;
            }

            KeyValuePair<long, int> startAndLength;

            if (inputStartAndLength == null)
            {
                if (!transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                    return;
                }
            }
            else
            {
                startAndLength = inputStartAndLength.Value;
            }
            // Catch any exceptions and cleanup the buffer. Otherwise uncleaned buffers will result in hang for future
            // uploads as memorymanager is being shared.
            // Also mark the transfer as complete and add exceptions to the transfercontext exception list.
            try
            {
                if (!transferContext.PartialFileIOState.ContainsKey(startAndLength.Key))
                {
                    transferContext.PartialFileIOState[startAndLength.Key] = 0;
                }

                transferContext.IsReadingOrWriting = true;

                long beginFilePosition = startAndLength.Key;
                long nextBeginFilePosition = startAndLength.Key + transferContext.BlockSize;

                nextBeginFilePosition =
                    nextBeginFilePosition > transferContext.Length
                        ? transferContext.Length
                        : nextBeginFilePosition;

                beginFilePosition = beginFilePosition + transferContext.PartialFileIOState[startAndLength.Key];
                int bytesToRead = (int)(nextBeginFilePosition - beginFilePosition);

                stream.BeginRead(
                    streamBuffer,
                    transferContext.PartialFileIOState[startAndLength.Key],
                    bytesToRead,
                    result3 =>
                    {
                        int bytesRead;

                        SuccessfulOrRetryableResult wasReadSuccessful =
                            IsActionSuccessfulOrRetryable(transferContext, () => stream.EndRead(result3), out bytesRead);

                        if (!wasReadSuccessful.IsSuccessful)
                        {
                            transferContext.IsReadingOrWriting = false;

                            transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                        }
                        else if (bytesRead != bytesToRead)
                        {
                            transferContext.PartialFileIOState[startAndLength.Key] += bytesRead;

                            DoSequentialRead(transferContext, stream, streamBuffer, startAndLength);
                        }
                        else
                        {
                            transferContext.IsReadingOrWriting = false;

                            ApplyEncryptionTransform(
                                transferContext.FileEncryption,
                                Path.GetFileName(transferContext.LocalFilePath),
                                beginFilePosition,
                                streamBuffer,
                                bytesToRead);

                            transferContext.BlocksForFileIO[(int)(startAndLength.Key / transferContext.BlockSize)] = streamBuffer;
                        }
                    },
                    null);
            }
            catch (Exception ex)
            {
                transferContext.IsComplete = true;
                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                transferContext.Exceptions.Add(ex);
            }
        }
        private void TryDownloadingBlocks(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }
            //This is where memory is allocated, any code after this should make sure releasebuffer happens on all positive/negative conditions
            byte[] streamBuffer = transferContext.MemoryManager.RequireBuffer();

            if (streamBuffer == null)
            {
                return;
            }
            // Catch any exceptions and cleanup the buffer. Otherwise uncleaned buffers will result in hang for future
            // downloads as memorymanager is being shared.
            // Also mark the transfer as complete and add exceptions to the transfercontext exception list.
            try
            {
                MemoryStream memoryStream = GetMemoryStream(transferContext.BufferStreams, streamBuffer);
                KeyValuePair<long, int> startAndLength;
                if (transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
                {
                    BeginDownloadStream(transferContext, memoryStream, startAndLength, streamBuffer);
                }
                else
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                }
            }
            catch (Exception ex)
            {
                transferContext.IsComplete = true;
                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                transferContext.Exceptions.Add(ex);
            }
        }
 private SuccessfulOrRetryableResult EndPutBlockList(BlobTransferContext transferContext, IAsyncResult ar)
 {
     return IsActionSuccessfulOrRetryable(transferContext, () => transferContext.Blob.EndPutBlockList(ar));
 }
 protected virtual SuccessfulOrRetryableResult EndDownloadStream(BlobTransferContext transferContext, IAsyncResult ar)
 {
     return IsActionSuccessfulOrRetryable(transferContext, () => transferContext.Blob.EndDownloadRangeToStream(ar));
 }
        private void TryUploadingBlocks(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (transferContext.NextFileIOBlock >= transferContext.BlocksForFileIO.Count)
            {
                return;
            }

            byte[] streamBuffer;
            int nextBlock = transferContext.NextFileIOBlock;

            if (transferContext.BlocksForFileIO.TryGetValue(nextBlock, out streamBuffer)
                && streamBuffer != null)
            {
                Interlocked.Increment(ref transferContext.NextFileIOBlock);

                MemoryStream memoryStream = GetMemoryStream(transferContext.BufferStreams, streamBuffer);

                long beginFilePosition = (long)nextBlock * transferContext.BlockSize;
                long nextBeginFilePosition = beginFilePosition + transferContext.BlockSize;

                nextBeginFilePosition =
                    nextBeginFilePosition > transferContext.Length
                        ? transferContext.Length
                        : nextBeginFilePosition;

                int bytesToRead = (int)(nextBeginFilePosition - beginFilePosition);

                BeginUploadStream(
                    transferContext,
                    new KeyValuePair<long, int>(beginFilePosition, bytesToRead),
                    memoryStream,
                    streamBuffer);
            }
        }
 protected virtual SuccessfulOrRetryableResult EndPutBlock(BlobTransferContext transferContext, IAsyncResult ar)
 {
     return(IsActionSuccessfulOrRetryable(transferContext, () => transferContext.Blob.EndPutBlock(ar)));
 }
 protected virtual SuccessfulOrRetryableResult EndPutBlock(BlobTransferContext transferContext, IAsyncResult ar)
 {
     return IsActionSuccessfulOrRetryable(transferContext, () => transferContext.Blob.EndPutBlock(ar));
 }
示例#30
0
        protected SuccessfulOrRetryableResult IsActionSuccessfulOrRetryable(BlobTransferContext transferContext, Action action)
        {
            if (transferContext == null)
            {
                throw new ArgumentNullException("transferContext");
            }
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }


            SuccessfulOrRetryableResult result =
                new SuccessfulOrRetryableResult
            {
                IsRetryable  = false,
                IsSuccessful = false
            };

            try
            {
                action();
            }
            catch (Exception exception)
            {
                WebException webEx = exception.FindInnerException <WebException>();

                if (webEx == null)
                {
                    transferContext.Exceptions.Add(exception);
                    transferContext.IsComplete = true;
                    return(result);
                }

                if (transferContext.GetSharedAccessSignature != null)
                {
                    if (webEx.Response is HttpWebResponse)
                    {
                        var httpex = (HttpWebResponse)webEx.Response;
                        if (httpex.StatusCode == HttpStatusCode.Forbidden)
                        {
                            Interlocked.Increment(ref transferContext.SasRetryCount);

                            if (transferContext.SasRetryCount > MaxSasSignatureRetry)
                            {
                                transferContext.Exceptions.Add(exception);
                                transferContext.IsComplete = true;
                                return(result);
                            }

                            Thread.Sleep(SasSignatureRetryTime);
                            result.IsRetryable = true;
                            return(result);
                        }
                    }
                }

                transferContext.Exceptions.Add(exception);
                transferContext.IsComplete = true;
                return(result);
            }

            result.IsSuccessful = true;
            return(result);
        }
        private void TryDownloadingBlocks(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            byte[] streamBuffer = transferContext.MemoryManager.RequireBuffer();

            if (streamBuffer == null)
            {
                return;
            }

            MemoryStream memoryStream = GetMemoryStream(transferContext.BufferStreams, streamBuffer);

            KeyValuePair<long, int> startAndLength;
            if (transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
            {
                BeginDownloadStream(transferContext, memoryStream, startAndLength, streamBuffer);
            }
            else
            {
                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
            }
        }
示例#32
0
        private void BeginDownloadStream(
            BlobTransferContext transferContext,
            MemoryStream memoryStream,
            KeyValuePair <long, int> startAndLength,
            byte[] streamBuffer)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            memoryStream.Seek(0, SeekOrigin.Begin);

            OperationContext operationContext = new OperationContext();

            operationContext.ClientRequestID = transferContext.ClientRequestId;

            Interlocked.Increment(ref transferContext.NumInProgressUploadDownloads);

            transferContext.Blob.BeginDownloadRangeToStream(
                memoryStream,
                startAndLength.Key,
                startAndLength.Value,
                AccessCondition.GenerateEmptyCondition(),
                transferContext.BlobRequestOptions,
                operationContext,
                ar =>
            {
                SuccessfulOrRetryableResult wasWriteSuccessful = EndDownloadStream(transferContext, ar);
                Interlocked.Decrement(ref transferContext.NumInProgressUploadDownloads);

                if (wasWriteSuccessful.IsRetryable)
                {
                    BeginDownloadStream(transferContext, memoryStream, startAndLength, streamBuffer);
                    return;
                }

                if (!wasWriteSuccessful.IsSuccessful)
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);

                    return;
                }

                Interlocked.Add(ref transferContext.BytesBlobIOCompleted, startAndLength.Value);

                TryDownloadingBlocks(transferContext);

                if (transferContext.ShouldDoFileIO)
                {
                    transferContext.BlocksForFileIO[(int)(startAndLength.Key / transferContext.BlockSize)] = streamBuffer;
                }
                else
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);

                    if (transferContext.BytesBlobIOCompleted >= transferContext.Length)
                    {
                        transferContext.IsComplete = true;
                    }
                }
            },
                null);
        }
示例#33
0
        private void DoSequentialRead(
            BlobTransferContext transferContext,
            Stream stream,
            byte[] streamBuffer = null,
            KeyValuePair <long, int>?inputStartAndLength = null)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (streamBuffer == null)
            {
                streamBuffer = transferContext.MemoryManager.RequireBuffer();
            }

            if (streamBuffer == null)
            {
                return;
            }

            KeyValuePair <long, int> startAndLength;

            if (inputStartAndLength == null)
            {
                if (!transferContext.BlocksToTransfer.TryDequeue(out startAndLength))
                {
                    transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                    return;
                }
            }
            else
            {
                startAndLength = inputStartAndLength.Value;
            }
            // Catch any exceptions and cleanup the buffer. Otherwise uncleaned buffers will result in hang for future
            // uploads as memorymanager is being shared.
            // Also mark the transfer as complete and add exceptions to the transfercontext exception list.
            try
            {
                if (!transferContext.PartialFileIOState.ContainsKey(startAndLength.Key))
                {
                    transferContext.PartialFileIOState[startAndLength.Key] = 0;
                }

                transferContext.IsReadingOrWriting = true;

                long beginFilePosition     = startAndLength.Key;
                long nextBeginFilePosition = startAndLength.Key + transferContext.BlockSize;

                nextBeginFilePosition =
                    nextBeginFilePosition > transferContext.Length
                        ? transferContext.Length
                        : nextBeginFilePosition;

                beginFilePosition = beginFilePosition + transferContext.PartialFileIOState[startAndLength.Key];
                int bytesToRead = (int)(nextBeginFilePosition - beginFilePosition);

                stream.BeginRead(
                    streamBuffer,
                    transferContext.PartialFileIOState[startAndLength.Key],
                    bytesToRead,
                    result3 =>
                {
                    int bytesRead;

                    SuccessfulOrRetryableResult wasReadSuccessful =
                        IsActionSuccessfulOrRetryable(transferContext, () => stream.EndRead(result3), out bytesRead);

                    if (!wasReadSuccessful.IsSuccessful)
                    {
                        transferContext.IsReadingOrWriting = false;

                        transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                    }
                    else if (bytesRead != bytesToRead)
                    {
                        transferContext.PartialFileIOState[startAndLength.Key] += bytesRead;

                        DoSequentialRead(transferContext, stream, streamBuffer, startAndLength);
                    }
                    else
                    {
                        transferContext.IsReadingOrWriting = false;

                        ApplyEncryptionTransform(
                            transferContext.FileEncryption,
                            Path.GetFileName(transferContext.LocalFilePath),
                            beginFilePosition,
                            streamBuffer,
                            bytesToRead);

                        transferContext.BlocksForFileIO[(int)(startAndLength.Key / transferContext.BlockSize)] = streamBuffer;
                    }
                },
                    null);
            }
            catch (Exception ex)
            {
                transferContext.IsComplete = true;
                transferContext.MemoryManager.ReleaseBuffer(streamBuffer);
                transferContext.Exceptions.Add(ex);
            }
        }
示例#34
0
        private void UploadFileToBlob(
            CancellationToken cancellationToken,
            Uri uri,
            string name,
            Stream stream,
            string contentType,
            string subDirectory,
            FileEncryption fileEncryption,
            CloudBlobClient client,
            IRetryPolicy retryPolicy,
            Func <string> getSharedAccessSignature,
            int parallelTransferThreadCount,
            bool shouldDoFileIO = true)
        {
            BlobTransferContext transferContext = new BlobTransferContext();

            transferContext.Exceptions = new ConcurrentBag <Exception>();
            try
            {
                ManualResetEvent   uploadCompletedSignal = new ManualResetEvent(false);
                BlobRequestOptions blobRequestOptions    = new BlobRequestOptions
                {
                    RetryPolicy   = retryPolicy,
                    ServerTimeout = TimeSpan.FromSeconds(90)
                };

                CloudBlockBlob blob = GetCloudBlockBlob(uri, client, subDirectory, name, contentType, getSharedAccessSignature);

                transferContext.Length         = stream.Length;
                transferContext.LocalFilePath  = name;
                transferContext.OnComplete     = () => uploadCompletedSignal.Set();
                transferContext.Blob           = blob;
                transferContext.FileEncryption = fileEncryption;
                if (stream.Length == 0)
                {
                    blob.UploadFromByteArray(new byte[1], 0, 0, options: blobRequestOptions);
                }
                else if (stream.Length < cloudBlockBlobUploadDownloadSizeLimit)
                {
                    AccessCondition  accessCondition  = AccessCondition.GenerateEmptyCondition();
                    OperationContext operationContext = new OperationContext();
                    operationContext.ClientRequestID = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);

                    using (var memoryStream = new MemoryStream())
                    {
                        stream.CopyTo(memoryStream);
                        byte[] fileContent = memoryStream.ToArray();
                        ApplyEncryptionTransform(
                            transferContext.FileEncryption,
                            Path.GetFileName(transferContext.LocalFilePath),
                            0,
                            fileContent,
                            Convert.ToInt32(stream.Length));

                        using (var uploadMemoryStream = new MemoryStream(fileContent))
                        {
                            blob.UploadFromStream(uploadMemoryStream, accessCondition: accessCondition, options: blobRequestOptions, operationContext: operationContext);
                        }
                    }
                    InvokeProgressCallback(transferContext, stream.Length, stream.Length);
                    transferContext.OnComplete();
                }
                else
                {
                    int numThreads = parallelTransferThreadCount;
                    int blockSize  = GetBlockSize(stream.Length);

                    transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(stream.Length, blockSize, ref numThreads);

                    transferContext.BlocksForFileIO = new ConcurrentDictionary <int, byte[]>();
                    for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                    {
                        transferContext.BlocksForFileIO[i] = null;
                    }
                    transferContext.BlockSize                = blockSize;
                    transferContext.CancellationToken        = cancellationToken;
                    transferContext.BlobRequestOptions       = blobRequestOptions;
                    transferContext.MemoryManager            = MemoryManagerFactory.GetMemoryManager(blockSize);
                    transferContext.Client                   = client;
                    transferContext.RetryPolicy              = retryPolicy;
                    transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                    transferContext.ShouldDoFileIO           = shouldDoFileIO;
                    transferContext.BufferStreams            = new ConcurrentDictionary <byte[], MemoryStream>();
                    transferContext.ClientRequestId          = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                    transferContext.ContentType              = contentType;
                    transferContext.BlobSubFolder            = subDirectory;
                    transferContext.NextFileIOBlock          = 0;
                    transferContext.PartialFileIOState       = new ConcurrentDictionary <long, int>();

                    RunUploadLoop(transferContext, stream, numThreads);
                }
            }
            catch (Exception e)
            {
                //Add the exception to the exception list.
                transferContext.Exceptions.Add(e);
            }
            finally
            {
                // We should to be able to releaseunusedbuffers if memorymanager was initialized by then
                if (transferContext.MemoryManager != null)
                {
                    transferContext.MemoryManager.ReleaseUnusedBuffers();
                }
                //TaskCompletedCallback should be called to populate exceptions if relevant and other eventargs for the user.
                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    transferContext.Exceptions != null && transferContext.Exceptions.Count > 0
                        ? new AggregateException(transferContext.Exceptions)
                        : null,
                    BlobTransferType.Upload,
                    name,
                    uri);
            }
        }
 private SuccessfulOrRetryableResult EndPutBlockList(BlobTransferContext transferContext, IAsyncResult ar)
 {
     return(IsActionSuccessfulOrRetryable(transferContext, () => transferContext.Blob.EndPutBlockList(ar)));
 }
        private void BeginPutBlockList(BlobTransferContext transferContext)
        {
            if (transferContext.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            OperationContext operationContext = new OperationContext();
            operationContext.ClientRequestID = transferContext.ClientRequestId;

            List<string> blockids = new List<string>();
            for (int i = 0; i < (transferContext.Length + transferContext.BlockSize - 1) / transferContext.BlockSize; i++)
            {
                blockids.Add(
                    Convert.ToBase64String(
                        Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "BlockId{0:d7}", i))));
            }

            transferContext.Blob.BeginPutBlockList(
                blockids,
                AccessCondition.GenerateEmptyCondition(),
                transferContext.BlobRequestOptions,
                operationContext,
                ar =>
                {
                    SuccessfulOrRetryableResult wasWriteSuccessful = EndPutBlockList(transferContext, ar);
                    Interlocked.Decrement(ref transferContext.NumInProgressUploadDownloads);

                    if (wasWriteSuccessful.IsRetryable)
                    {
                        BeginPutBlockList(transferContext);
                        return;
                    }

                    transferContext.IsComplete = true;
                },
                state: null);
        }
        private void UploadFileToBlob(
            CancellationToken cancellationToken,
            Uri uri,
            string localFile,
            string contentType,
            string subDirectory,
            FileEncryption fileEncryption,
            CloudBlobClient client,
            IRetryPolicy retryPolicy,
            Func <string> getSharedAccessSignature,
            bool shouldDoFileIO = true)
        {
            //attempt to open the file first so that we throw an exception before getting into the async work
            using (new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
            }

            SetConnectionLimits(uri);

            ManualResetEvent   uploadCompletedSignal = new ManualResetEvent(false);
            BlobRequestOptions blobRequestOptions    = new BlobRequestOptions
            {
                RetryPolicy   = retryPolicy,
                ServerTimeout = TimeSpan.FromSeconds(90)
            };

            CloudBlockBlob blob = GetCloudBlockBlob(uri, client, subDirectory, localFile, contentType, getSharedAccessSignature);

            BlobPolicyActivationWait(() => blob.DeleteIfExists(options: blobRequestOptions));

            FileInfo file     = new FileInfo(localFile);
            long     fileSize = file.Length;

            if (fileSize == 0)
            {
                blob.UploadFromByteArray(new byte[1], 0, 0, options: blobRequestOptions);

                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    null,
                    BlobTransferType.Upload,
                    localFile,
                    uri);
            }
            else
            {
                int numThreads = Environment.ProcessorCount * ParallelUploadDownloadThreadCountMultiplier;
                int blockSize  = GetBlockSize(fileSize);

                BlobTransferContext transferContext = new BlobTransferContext();
                transferContext.BlocksToTransfer = PrepareUploadDownloadQueue(fileSize, blockSize, ref numThreads);

                transferContext.BlocksForFileIO = new ConcurrentDictionary <int, byte[]>();
                for (int i = 0; i < transferContext.BlocksToTransfer.Count(); i++)
                {
                    transferContext.BlocksForFileIO[i] = null;
                }
                transferContext.BlockSize         = blockSize;
                transferContext.CancellationToken = cancellationToken;
                transferContext.Blob = blob;
                transferContext.BlobRequestOptions       = blobRequestOptions;
                transferContext.Length                   = fileSize;
                transferContext.LocalFilePath            = localFile;
                transferContext.OnComplete               = () => uploadCompletedSignal.Set();
                transferContext.MemoryManager            = MemoryManagerFactory.GetMemoryManager(blockSize);
                transferContext.Client                   = client;
                transferContext.RetryPolicy              = retryPolicy;
                transferContext.GetSharedAccessSignature = getSharedAccessSignature;
                transferContext.ShouldDoFileIO           = shouldDoFileIO;
                transferContext.BufferStreams            = new ConcurrentDictionary <byte[], MemoryStream>();
                transferContext.ClientRequestId          = DateTime.UtcNow.ToString("s", CultureInfo.InvariantCulture);
                transferContext.Exceptions               = new ConcurrentBag <Exception>();
                transferContext.FileEncryption           = fileEncryption;
                transferContext.ContentType              = contentType;
                transferContext.BlobSubFolder            = subDirectory;
                transferContext.NextFileIOBlock          = 0;
                transferContext.PartialFileIOState       = new ConcurrentDictionary <long, int>();

                using (
                    FileStream stream = new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    RunUploadLoop(transferContext, stream, numThreads);
                }

                transferContext.MemoryManager.ReleaseUnusedBuffers();

                TaskCompletedCallback(
                    cancellationToken.IsCancellationRequested,
                    transferContext.Exceptions != null && transferContext.Exceptions.Count > 0 ? new AggregateException(transferContext.Exceptions) : null,
                    BlobTransferType.Upload,
                    localFile,
                    uri);
            }
        }
示例#38
0
 protected virtual SuccessfulOrRetryableResult EndDownloadStream(BlobTransferContext transferContext, IAsyncResult ar)
 {
     return(IsActionSuccessfulOrRetryable(transferContext, () => transferContext.Blob.EndDownloadRangeToStream(ar)));
 }