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); }
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); }
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, 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); } }
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 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); }
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); }