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);
        }
示例#2
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);
        }
        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);
        }
示例#5
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);
            }
        }
示例#6
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);
            }
        }
示例#7
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);
        }
示例#8
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);
        }