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 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(); }
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 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 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 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 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 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 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) { 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); } }