示例#1
0
        private static void EndSendStreamCopy <T>(ExecutionState <T> executionState)
        {
            lock (executionState.CancellationLockerObject)
            {
                if (Executor.CheckCancellation(executionState))
                {
                    if (executionState.Req != null)
                    {
                        try
                        {
                            executionState.Req.Abort();
                        }
                        catch (Exception)
                        {
                            // No op
                        }
                    }
                }

                if (executionState.ExceptionRef != null)
                {
                    EndOperation(executionState);
                }
                else
                {
                    BeginGetResponse(executionState);
                }
            }
        }
示例#2
0
        // Note for future maintainers:
        // In EndOperation<T> above, this method is called and sync-Wait()'d on, with runPostProcess set to false.
        // This means that, if 'runPostProcess' is ever false, this method must never hit an await point.
        // This restriction is irrelevant in future versions of the library that only have an async executor.
        private static async Task EndOperationAsync <T>(ExecutionState <T> executionState, bool runPostProcess)
        {
            Executor.FinishRequestAttempt(executionState);

            try
            {
                // If an operation has been canceled of timed out this should overwrite any exception
                Executor.CheckCancellation(executionState);
                Executor.CheckTimeout(executionState, true);

                // Success
                if (executionState.ExceptionRef == null)
                {
                    if (runPostProcess)
                    {
                        // Step 9 - This will not be called if an exception is raised during stream copying
                        await Executor.RunPostProcessAsync(executionState);
                    }
                    DisposeAndEnd <T>(executionState);
                    executionState.OnComplete();
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TracePostProcessError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
            }
            finally
            {
                try
                {
                    if (executionState.ReqStream != null)
                    {
                        executionState.ReqStream.Dispose();
                        executionState.ReqStream = null;
                    }

                    if (executionState.Resp != null)
                    {
                        executionState.Resp.Close();
                        executionState.Resp = null;
                    }
                }
                catch (Exception)
                {
                    // no op
                }
            }

            ConsiderRetry <T>(executionState);
        }
示例#3
0
        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();
            }
        }
示例#4
0
        private static void EndSendStreamCopy <T>(ExecutionState <T> executionState)
        {
            lock (executionState.CancellationLockerObject)
            {
                if (Executor.CheckCancellation(executionState))
                {
                    if (executionState.Req != null)
                    {
                        try
                        {
                            executionState.Req.Abort();
                        }
                        catch (Exception)
                        {
                            // No op
                        }
                    }
                }

                if (executionState.ExceptionRef != null)
                {
                    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.
                    }

                    BeginGetResponse(executionState);
                }
            }
        }
        private static void EndSendStreamCopy <T>(ExecutionState <T> executionState)
        {
            executionState.CurrentOperation = ExecutorOperation.EndUploadRequest;

            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 EndOperation <T>(ExecutionState <T> executionState)
        {
            Executor.FinishRequestAttempt(executionState);

            try
            {
                // If an operation has been canceled of timed out this should overwrite any exception
                Executor.CheckCancellation(executionState);
                Executor.CheckTimeout(executionState, true);

                // Success
                if (executionState.ExceptionRef == null)
                {
                    // Step 9 - This will not be called if an exception is raised during stream copying
                    Executor.ProcessEndOfRequest(executionState);
                    executionState.OnComplete();
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.LogWarning(executionState.OperationContext, SR.TracePostProcessError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
            }
            finally
            {
                try
                {
                    if (executionState.ReqStream != null)
                    {
                        executionState.ReqStream.Dispose();
                        executionState.ReqStream = null;
                    }

                    if (executionState.Resp != null)
                    {
                        executionState.Resp.Close();
                        executionState.Resp = null;
                    }
                }
                catch (Exception)
                {
                    // no op
                }
            }

            // Handle Retry
            try
            {
                StorageException translatedException = TranslateExceptionBasedOnParseError(executionState.ExceptionRef, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
                executionState.ExceptionRef = translatedException;
                Logger.LogInformational(executionState.OperationContext, SR.TraceRetryCheck, executionState.RetryCount, executionState.Cmd.CurrentResult.HttpStatusCode, translatedException.IsRetryable ? "yes" : "no", translatedException.Message);

                bool     shouldRetry = false;
                TimeSpan delay       = TimeSpan.Zero;
                if (translatedException.IsRetryable && (executionState.RetryPolicy != null))
                {
                    executionState.CurrentLocation = Executor.GetNextLocation(executionState.CurrentLocation, executionState.RestCMD.LocationMode);
                    Logger.LogInformational(executionState.OperationContext, SR.TraceNextLocation, executionState.CurrentLocation);

                    IExtendedRetryPolicy extendedRetryPolicy = executionState.RetryPolicy as IExtendedRetryPolicy;
                    if (extendedRetryPolicy != null)
                    {
                        RetryContext retryContext = new RetryContext(
                            executionState.RetryCount++,
                            executionState.Cmd.CurrentResult,
                            executionState.CurrentLocation,
                            executionState.RestCMD.LocationMode);

                        RetryInfo retryInfo = extendedRetryPolicy.Evaluate(retryContext, executionState.OperationContext);
                        if (retryInfo != null)
                        {
                            Logger.LogInformational(executionState.OperationContext, SR.TraceRetryInfo, retryInfo.TargetLocation, retryInfo.UpdatedLocationMode);
                            shouldRetry = true;
                            executionState.CurrentLocation      = retryInfo.TargetLocation;
                            executionState.RestCMD.LocationMode = retryInfo.UpdatedLocationMode;
                            delay = retryInfo.RetryInterval;
                        }
                    }
                    else
                    {
                        shouldRetry = executionState.RetryPolicy.ShouldRetry(
                            executionState.RetryCount++,
                            executionState.Cmd.CurrentResult.HttpStatusCode,
                            executionState.ExceptionRef,
                            out delay,
                            executionState.OperationContext);
                    }

                    if ((delay < TimeSpan.Zero) || (delay > Constants.MaximumRetryBackoff))
                    {
                        delay = Constants.MaximumRetryBackoff;
                    }
                }

                if (!shouldRetry || (executionState.OperationExpiryTime.HasValue && (DateTime.Now + delay).CompareTo(executionState.OperationExpiryTime.Value) > 0))
                {
                    Logger.LogError(executionState.OperationContext, shouldRetry ? SR.TraceRetryDecisionTimeout : SR.TraceRetryDecisionPolicy, executionState.ExceptionRef.Message);

                    // No Retry
                    executionState.OnComplete();
                }
                else
                {
                    if (executionState.Cmd.RecoveryAction != null)
                    {
                        // I.E. Rewind stream etc.
                        executionState.Cmd.RecoveryAction(executionState.Cmd, executionState.ExceptionRef, executionState.OperationContext);
                    }

                    if (delay > TimeSpan.Zero)
                    {
                        Logger.LogInformational(executionState.OperationContext, SR.TraceRetryDelay, (int)delay.TotalMilliseconds);

                        executionState.UpdateCompletedSynchronously(false);
                        if (executionState.BackoffTimer == null)
                        {
                            executionState.BackoffTimer = new Timer(
                                Executor.RetryRequest <T>,
                                executionState,
                                (int)delay.TotalMilliseconds,
                                Timeout.Infinite);
                        }
                        else
                        {
                            executionState.BackoffTimer.Change((int)delay.TotalMilliseconds, Timeout.Infinite);
                        }

                        executionState.CancelDelegate = () =>
                        {
                            // Disabling the timer here, but there is still a scenario where the user calls cancel after
                            // the timer starts the next retry but before it sets the CancelDelegate back to null. However, even
                            // if that happens, next retry will start and then stop immediately because of the cancelled flag.
                            Timer backoffTimer = executionState.BackoffTimer;
                            if (backoffTimer != null)
                            {
                                executionState.BackoffTimer = null;
                                backoffTimer.Dispose();
                            }

                            Logger.LogWarning(executionState.OperationContext, SR.TraceAbortRetry);
                            Executor.CheckCancellation(executionState);
                            executionState.OnComplete();
                        };
                    }
                    else
                    {
                        // Start next request immediately
                        Executor.RetryRequest <T>(executionState);
                    }
                }
            }
            catch (Exception ex)
            {
                // Catch all ( i.e. users retry policy throws etc.)
                Logger.LogWarning(executionState.OperationContext, SR.TraceRetryError, ex.Message);
                executionState.ExceptionRef = ExecutorBase.TranslateExceptionBasedOnParseError(ex, executionState.Cmd.CurrentResult, executionState.Resp, executionState.Cmd.ParseError);
                executionState.OnComplete();
            }
        }
        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);
            }
        }
示例#8
0
        private static void EndOperation <T>(ExecutionState <T> executionState)
        {
            Executor.FinishRequestAttempt(executionState);

            lock (executionState.CancellationLockerObject)
            {
                try
                {
                    // If an operation has been canceled of timed out this should overwtie any exception
                    Executor.CheckCancellation(executionState);
                    Executor.CheckTimeout(executionState, true);

                    // Success
                    if (executionState.ExceptionRef == null)
                    {
                        // Step 9 - This will not be called if an exception is raised during stream copying
                        Executor.ProcessEndOfRequest(executionState, executionState.ExceptionRef);
                        executionState.OnComplete();
                        return;
                    }
                }
                catch (Exception ex)
                {
                    executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                }
                finally
                {
                    try
                    {
                        if (executionState.Resp != null)
                        {
                            executionState.Resp.Close();
                            executionState.Resp = null;
                        }
                    }
                    catch (Exception)
                    {
                        // no op
                    }
                }
            }

            // Handle Retry
            try
            {
                StorageException translatedException = StorageException.TranslateException(executionState.ExceptionRef, executionState.Cmd.CurrentResult);
                executionState.ExceptionRef = translatedException;

                TimeSpan delay       = TimeSpan.FromMilliseconds(0);
                bool     shouldRetry = translatedException.IsRetryable &&
                                       executionState.RetryPolicy != null?
                                       executionState.RetryPolicy.ShouldRetry(
                    executionState.RetryCount++,
                    executionState.Cmd.CurrentResult.HttpStatusCode,
                    executionState.ExceptionRef,
                    out delay,
                    executionState.OperationContext)
                                           : false;

                delay = delay.TotalMilliseconds <0 || delay> Constants.MaximumRetryBackoff ? Constants.MaximumRetryBackoff : delay;

                if (!shouldRetry || (executionState.OperationExpiryTime.HasValue && (DateTime.Now + delay).CompareTo(executionState.OperationExpiryTime.Value) > 0))
                {
                    // No Retry
                    executionState.OnComplete();
                }
                else
                {
                    if (executionState.Cmd.RecoveryAction != null)
                    {
                        // I.E. Rewind stream etc.
                        executionState.Cmd.RecoveryAction(executionState.Cmd, executionState.ExceptionRef, executionState.OperationContext);
                    }

                    if (delay > TimeSpan.Zero)
                    {
                        Timer backoffTimer = null;

                        backoffTimer = new Timer(
                            (obj) =>
                        {
                            executionState.CompletedSynchronously = false;
                            backoffTimer.Change(Timeout.Infinite, Timeout.Infinite);
                            backoffTimer.Dispose();
                            InitRequest(executionState);
                        },
                            null /* state */,
                            (int)delay.TotalMilliseconds,
                            Timeout.Infinite);
                    }
                    else
                    {
                        // Start Next Request Immediately
                        InitRequest(executionState);
                    }
                }
            }
            catch (Exception ex)
            {
                // Catch all ( i.e. users retry policy throws etc.)
                executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                executionState.OnComplete();
            }
        }
示例#9
0
        private static void BeginGetRequestStream <T>(ExecutionState <T> executionState)
        {
            try
            {
                APMWithTimeout.RunWithTimeout(
                    executionState.Req.BeginGetRequestStream,
                    (getRequestStreamResp) =>
                {
                    executionState.CompletedSynchronously = executionState.CompletedSynchronously && getRequestStreamResp.CompletedSynchronously;

                    try
                    {
                        executionState.ReqStream = executionState.Req.EndGetRequestStream(getRequestStreamResp);

                        // don't calculate md5 here as we should have already set this for auth purposes
                        executionState.RestCMD.SendStream.WriteToAsync(executionState.ReqStream, null /* maxLength */, executionState.OperationExpiryTime, false, executionState, executionState.OperationContext, null /* streamCopyState */, EndSendStreamCopy);
                    }
                    catch (WebException ex)
                    {
                        if (ex.Status == WebExceptionStatus.RequestCanceled)
                        {
                            // If the below condition is true, ExceptionRef is set anyway, so don't touch it
                            if (!Executor.CheckCancellation(executionState))
                            {
                                executionState.ExceptionRef = Exceptions.GenerateTimeoutException(executionState.Cmd.CurrentResult, null);
                            }
                        }
                        else
                        {
                            executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                        }

                        EndOperation(executionState);
                    }
                    catch (Exception ex)
                    {
                        executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                        EndOperation(executionState);
                    }
                },
                    null,
                    executionState.RemainingTimeout,
                    (getRequestStreamResp) =>
                {
                    try
                    {
                        executionState.ReqTimedOut = true;
                        executionState.Req.Abort();
                    }
                    catch (Exception)
                    {
                        // no op
                    }
                });
            }
            catch (Exception ex)
            {
                executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                EndOperation(executionState);
            }
        }