private static void EndGetRequestStream <T>(IAsyncResult getRequestStreamResult)
        {
            ExecutionState <T> executionState = (ExecutionState <T>)getRequestStreamResult.AsyncState;

            executionState.CurrentOperation = ExecutorOperation.EndGetRequestStream;

            try
            {
                executionState.UpdateCompletedSynchronously(getRequestStreamResult.CompletedSynchronously);

                executionState.ReqStream = executionState.Req.EndGetRequestStream(getRequestStreamResult);

                executionState.CurrentOperation = ExecutorOperation.BeginUploadRequest;
                Logger.LogInformational(executionState.OperationContext, SR.TraceUpload);
                MultiBufferMemoryStream multiBufferMemoryStream = executionState.RestCMD.SendStream as MultiBufferMemoryStream;
                if (multiBufferMemoryStream != null && !executionState.RestCMD.SendStreamLength.HasValue)
                {
                    multiBufferMemoryStream.BeginFastCopyTo(executionState.ReqStream, executionState.OperationExpiryTime, EndFastCopyTo <T>, executionState);
                }
                else
                {
                    // don't calculate md5 here as we should have already set this for auth purposes
                    executionState.RestCMD.SendStream.WriteToAsync(executionState.ReqStream, executionState.RestCMD.SendStreamLength, null /* maxLength */, false, executionState, null /* streamCopyState */, EndSendStreamCopy);
                }
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TraceUploadError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
                Executor.EndOperation(executionState);
            }
        }
        public static void InitRequest <T>(ExecutionState <T> executionState)
        {
            try
            {
                executionState.Init();

                // 0. Begin Request
                Executor.StartRequestAttempt(executionState);

                // Steps 1 - 4
                Logger.LogInformational(executionState.OperationContext, SR.TraceStartRequestAsync, executionState.Cmd.Uri);
                Executor.ProcessStartOfRequest(executionState);

                if (Executor.CheckTimeout <T>(executionState, false))
                {
                    Executor.EndOperation(executionState);
                    return;
                }

                lock (executionState.CancellationLockerObject)
                {
                    if (Executor.CheckCancellation(executionState))
                    {
                        Executor.EndOperation(executionState);
                        return;
                    }

                    // 5. potentially upload data
                    if (executionState.RestCMD.SendStream != null)
                    {
                        Executor.BeginGetRequestStream(executionState);
                    }
                    else
                    {
                        Executor.BeginGetResponse(executionState);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(executionState.OperationContext, SR.TraceInitRequestError, ex.Message);

                // Store exception and invoke callback here. All operations in this try would be non-retryable by default
                StorageException storageEx = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                storageEx.IsRetryable       = false;
                executionState.ExceptionRef = storageEx;
                executionState.OnComplete();
            }
        }
        private static void EndResponseStreamCopy <T>(ExecutionState <T> executionState)
        {
            // At this time, the response/error stream has been read. So try to parse the error if there was en exception
            if (executionState.RestCMD.ErrorStream != null)
            {
                executionState.RestCMD.ErrorStream.Seek(0, SeekOrigin.Begin);
                if (executionState.Cmd.ParseError != null)
                {
                    executionState.ExceptionRef = StorageException.TranslateExceptionWithPreBufferedStream(executionState.ExceptionRef, executionState.Cmd.CurrentResult, stream => executionState.Cmd.ParseError(stream, executionState.Resp, null), executionState.RestCMD.ErrorStream);
                }
                else
                {
                    executionState.ExceptionRef = StorageException.TranslateExceptionWithPreBufferedStream(executionState.ExceptionRef, executionState.Cmd.CurrentResult, null, executionState.RestCMD.ErrorStream);
                }

                // Dispose the stream and end the operation
                try
                {
                    executionState.RestCMD.ErrorStream.Dispose();
                    executionState.RestCMD.ErrorStream = null;
                }
                catch (Exception)
                {
                    // no-op
                }
            }

            // Dispose the stream and end the operation
            try
            {
                if (executionState.RestCMD.ResponseStream != null)
                {
                    executionState.RestCMD.ResponseStream.Dispose();
                    executionState.RestCMD.ResponseStream = null;
                }
            }
            catch (Exception)
            {
                // no-op, because HttpWebResponse.Close should take care of it
            }

            executionState.CurrentOperation = ExecutorOperation.EndDownloadResponse;

            Executor.EndOperation(executionState);
        }
        private static void EndResponseStreamCopy <T>(ExecutionState <T> executionState)
        {
            try
            {
                if (executionState.RestCMD.ResponseStream != null)
                {
                    executionState.RestCMD.ResponseStream.Dispose();
                    executionState.RestCMD.ResponseStream = null;
                }
            }
            catch (Exception)
            {
                // no-op, because HttpWebResponse.Close should take care of it
            }

            executionState.CurrentOperation = ExecutorOperation.EndDownloadResponse;
            Executor.EndOperation(executionState);
        }
        private static void EndFastCopyTo <T>(IAsyncResult fastCopyToResult)
        {
            ExecutionState <T> executionState = (ExecutionState <T>)fastCopyToResult.AsyncState;

            try
            {
                executionState.UpdateCompletedSynchronously(fastCopyToResult.CompletedSynchronously);

                MultiBufferMemoryStream multiBufferMemoryStream = (MultiBufferMemoryStream)executionState.RestCMD.SendStream;
                multiBufferMemoryStream.EndFastCopyTo(fastCopyToResult);

                Executor.EndSendStreamCopy(executionState);
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TraceUploadError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
                Executor.EndOperation(executionState);
            }
        }
        private static void BeginGetResponse <T>(ExecutionState <T> executionState)
        {
            executionState.CurrentOperation = ExecutorOperation.BeginGetResponse;
            Logger.LogInformational(executionState.OperationContext, SR.TraceGetResponse);

            try
            {
                APMWithTimeout.RunWithTimeout(
                    executionState.Req.BeginGetResponse,
                    Executor.EndGetResponse <T>,
                    Executor.AbortRequest <T>,
                    executionState,
                    executionState.RemainingTimeout);
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TraceGetResponseError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
                Executor.EndOperation(executionState);
            }
        }
        private static void BeginGetRequestStream <T>(ExecutionState <T> executionState)
        {
            executionState.CurrentOperation = ExecutorOperation.BeginGetRequestStream;
            Logger.LogInformational(executionState.OperationContext, SR.TracePrepareUpload);

            try
            {
                APMWithTimeout.RunWithTimeout(
                    executionState.Req.BeginGetRequestStream,
                    Executor.EndGetRequestStream <T>,
                    Executor.AbortRequest <T>,
                    executionState,
                    executionState.RemainingTimeout);
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TracePrepareUploadError, ex.Message);
                executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                Executor.EndOperation(executionState);
            }
        }
        private static void EndSendStreamCopy <T>(ExecutionState <T> executionState)
        {
            executionState.CurrentOperation = ExecutorOperation.EndUploadRequest;

            lock (executionState.CancellationLockerObject)
            {
                Executor.CheckCancellation(executionState);

                if (executionState.ExceptionRef != null)
                {
                    try
                    {
                        executionState.Req.Abort();
                    }
                    catch (Exception)
                    {
                        // No op
                    }

                    Executor.EndOperation(executionState);
                }
                else
                {
                    try
                    {
                        executionState.ReqStream.Flush();
                        executionState.ReqStream.Dispose();
                        executionState.ReqStream = null;
                    }
                    catch (Exception)
                    {
                        // If we could not flush/dispose the request stream properly,
                        // BeginGetResponse will fail with a more meaningful error anyway.
                    }

                    Executor.BeginGetResponse(executionState);
                }
            }
        }
        private static void EndGetResponse <T>(IAsyncResult getResponseResult)
        {
            ExecutionState <T> executionState = (ExecutionState <T>)getResponseResult.AsyncState;

            executionState.CurrentOperation = ExecutorOperation.EndGetResponse;

            try
            {
                executionState.UpdateCompletedSynchronously(getResponseResult.CompletedSynchronously);

                try
                {
                    executionState.Resp = executionState.Req.EndGetResponse(getResponseResult) as HttpWebResponse;
                }
                catch (WebException ex)
                {
                    Logger.LogWarning(executionState.OperationContext, SR.TraceGetResponseError, ex.Message);
                    executionState.Resp = (HttpWebResponse)ex.Response;

                    if (ex.Status == WebExceptionStatus.Timeout || executionState.ReqTimedOut)
                    {
                        throw new TimeoutException();
                    }

                    if (executionState.Resp == null)
                    {
                        throw;
                    }
                    else
                    {
                        // Store this exception for now. It will be parsed/thrown after the stream is read in step 8
                        executionState.ExceptionRef = ex;
                    }
                }

                Logger.LogInformational(executionState.OperationContext, SR.TraceResponse, executionState.Cmd.CurrentResult.HttpStatusCode, executionState.Cmd.CurrentResult.ServiceRequestID, executionState.Cmd.CurrentResult.ContentMd5, executionState.Cmd.CurrentResult.Etag);
                Executor.FireResponseReceived(executionState);

                // 7. Do Response parsing (headers etc, no stream available here)
                if (executionState.RestCMD.PreProcessResponse != null)
                {
                    executionState.CurrentOperation = ExecutorOperation.PreProcess;

                    try
                    {
                        executionState.Result = executionState.RestCMD.PreProcessResponse(executionState.RestCMD, executionState.Resp, executionState.ExceptionRef, executionState.OperationContext);

                        // clear exception
                        executionState.ExceptionRef = null;
                        Logger.LogInformational(executionState.OperationContext, SR.TracePreProcessDone);
                    }
                    catch (Exception ex)
                    {
                        executionState.ExceptionRef = ex;
                    }
                }

                Executor.CheckCancellation(executionState);

                executionState.CurrentOperation       = ExecutorOperation.GetResponseStream;
                executionState.RestCMD.ResponseStream = executionState.Resp.GetResponseStream();

                // 8. (Potentially reads stream from server)
                if (executionState.ExceptionRef != null)
                {
                    executionState.CurrentOperation = ExecutorOperation.BeginDownloadResponse;
                    Logger.LogInformational(executionState.OperationContext, SR.TraceDownloadError);

                    executionState.RestCMD.ErrorStream = new MemoryStream();
                    executionState.RestCMD.ResponseStream.WriteToAsync(executionState.RestCMD.ErrorStream, null /* copyLength */, null /* maxLength */, false /* calculateMd5 */, executionState, new StreamDescriptor(), EndResponseStreamCopy);
                }
                else
                {
                    if (!executionState.RestCMD.RetrieveResponseStream)
                    {
                        executionState.RestCMD.DestinationStream = Stream.Null;
                    }

                    if (executionState.RestCMD.DestinationStream != null)
                    {
                        if (executionState.RestCMD.StreamCopyState == null)
                        {
                            executionState.RestCMD.StreamCopyState = new StreamDescriptor();
                        }

                        executionState.CurrentOperation = ExecutorOperation.BeginDownloadResponse;
                        Logger.LogInformational(executionState.OperationContext, SR.TraceDownload);
                        executionState.RestCMD.ResponseStream.WriteToAsync(executionState.RestCMD.DestinationStream, null /* copyLength */, null /* maxLength */, executionState.RestCMD.CalculateMd5ForResponseStream, executionState, executionState.RestCMD.StreamCopyState, EndResponseStreamCopy);
                    }
                    else
                    {
                        // Dont want to copy stream, just want to consume it so end
                        Executor.EndOperation(executionState);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TracePreProcessError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
                Executor.EndOperation(executionState);
            }
        }