예제 #1
0
 public ExecutionState(StorageCommandBase <T> cmd, IRetryPolicy policy, OperationContext operationContext)
 {
     throw new System.NotImplementedException();
 }
        /// <summary>
        /// Apply timeout options to StorageCommandBase
        /// </summary>
        /// <typeparam name="T">Return value type of StorageCommandBase</typeparam>
        /// <param name="requestOptions">The request options.</param>
        /// <param name="cmd">An instance of StorageCommandBase to apply options to</param>
        internal static void ApplyToStorageCommand <T>(this TableRequestOptions requestOptions, StorageCommandBase <T> cmd)
        {
            if (requestOptions.MaximumExecutionTime.HasValue)
            {
                cmd.ClientMaxTimeout = requestOptions.MaximumExecutionTime.Value;
            }

            if (requestOptions.ServerTimeout.HasValue)
            {
                cmd.ServerTimeoutInSeconds = (int)requestOptions.ServerTimeout.Value.TotalSeconds;
            }
        }
예제 #3
0
        public static T ExecuteSync <T>(StorageCommandBase <T> cmd, IRetryPolicy policy, OperationContext operationContext)
        {
            // Note all code below will reference state, not params directly, this will allow common code with async executor
            ExecutionState <T> executionState = new ExecutionState <T>(cmd, policy, operationContext);
            bool shouldRetry = false;

            do
            {
                try
                {
                    executionState.Init();

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

                    // Steps 1-4
                    Executor.ProcessStartOfRequest(executionState);

                    Executor.CheckTimeout <T>(executionState, true);

                    // Enter Retryable Section of execution
                    // 5. potentially upload data
                    if (executionState.RestCMD.SendStream != null)
                    {
                        // Reset timeout
                        executionState.Req.Timeout = executionState.RemainingTimeout;
                        executionState.ReqStream   = executionState.Req.GetRequestStream();
                        executionState.RestCMD.SendStream.WriteToSync(executionState.ReqStream, null /* maxLength */, executionState.OperationExpiryTime, false, true, executionState.OperationContext, null /* streamCopyState */); // don't calculate md5 here as we should have already set this for auth purposes
                    }

                    // 6. Get response
                    try
                    {
                        // Reset timeout
                        executionState.Req.Timeout = executionState.RemainingTimeout;
                        executionState.Resp        = (HttpWebResponse)executionState.Req.GetResponse();
                    }
                    catch (WebException ex)
                    {
                        executionState.Resp = (HttpWebResponse)ex.Response;
                        if (executionState.Resp == null)
                        {
                            throw;
                        }
                        else
                        {
                            executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                        }
                    }

                    // Response
                    Executor.FireResponseReceived(executionState);

                    // 7. Do Response parsing (headers etc, no stream available here)
                    if (executionState.RestCMD.PreProcessResponse != null)
                    {
                        executionState.Result = executionState.RestCMD.PreProcessResponse(executionState.RestCMD, executionState.Resp, executionState.ExceptionRef, executionState.OperationContext);

                        // clear exception
                        executionState.ExceptionRef = null;
                    }

                    // 8. (Potentially reads stream from server)
                    if (executionState.RestCMD.RetrieveResponseStream)
                    {
                        executionState.RestCMD.ResponseStream = executionState.Resp.GetResponseStream();
                    }

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

                            executionState.RestCMD.ResponseStream.WriteToSync(executionState.RestCMD.DestinationStream, null /* maxLength */, executionState.OperationExpiryTime, executionState.RestCMD.CalculateMd5ForResponseStream, false, executionState.OperationContext, executionState.RestCMD.StreamCopyState);
                        }
                        finally
                        {
                            executionState.RestCMD.ResponseStream.Dispose();
                        }
                    }

                    // Step 9 - This will not be called if an exception is raised during stream copying
                    Executor.ProcessEndOfRequest(executionState, executionState.ExceptionRef);

                    Executor.FinishRequestAttempt(executionState);

                    return(executionState.Result);
                }
                catch (Exception e)
                {
                    Executor.FinishRequestAttempt(executionState);

                    StorageException translatedException = StorageException.TranslateException(e, executionState.Cmd.CurrentResult);
                    executionState.ExceptionRef = translatedException;

                    TimeSpan delay = TimeSpan.FromMilliseconds(0);
                    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))
                    {
                        throw executionState.ExceptionRef;
                    }
                    else
                    {
                        if (executionState.Cmd.RecoveryAction != null)
                        {
                            // I.E. Rewind stream etc.
                            executionState.Cmd.RecoveryAction(executionState.Cmd, executionState.ExceptionRef, executionState.OperationContext);
                        }

                        if (delay > TimeSpan.Zero)
                        {
                            Thread.Sleep(delay);
                        }
                    }
                }
                finally
                {
                    if (executionState.Resp != null)
                    {
                        executionState.Resp.Close();
                        executionState.Resp = null;
                    }
                }
            }while (shouldRetry);

            // should never get here, either return, or throw;
            throw new NotImplementedException(SR.InternalStorageError);
        }
예제 #4
0
 internal static void RewindStream <T>(StorageCommandBase <T> cmd, Exception ex, OperationContext ctx)
 {
     SeekStream(cmd, ex, ctx, 0);
 }
예제 #5
0
 internal static void RewindStream <T>(StorageCommandBase <T> cmd, Exception ex, OperationContext ctx)
 {
     RecoveryActions.SeekStream(cmd, 0);
 }
예제 #6
0
        public static T ExecuteSync <T>(StorageCommandBase <T> cmd, IRetryPolicy policy, OperationContext operationContext)
        {
            // Note all code below will reference state, not params directly, this will allow common code with async executor
            using (ExecutionState <T> executionState = new ExecutionState <T>(cmd, policy, operationContext))
            {
                bool     shouldRetry = false;
                TimeSpan delay       = TimeSpan.Zero;

                do
                {
                    try
                    {
                        executionState.Init();

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

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

                        Executor.CheckTimeout <T>(executionState, true);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(executionState.OperationContext, SR.TraceInitRequestError, ex.Message);

                        // Store exception and throw 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;
                        throw executionState.ExceptionRef;
                    }

                    // Enter Retryable Section of execution
                    try
                    {
                        // 5. potentially upload data
                        if (executionState.RestCMD.SendStream != null)
                        {
                            executionState.CurrentOperation = ExecutorOperation.BeginGetRequestStream;
                            Logger.LogInformational(executionState.OperationContext, SR.TracePrepareUpload);
                            executionState.Req.Timeout = (int)executionState.RemainingTimeout.TotalMilliseconds;
                            executionState.ReqStream   = executionState.Req.GetRequestStream();

                            executionState.CurrentOperation = ExecutorOperation.BeginUploadRequest;
                            Logger.LogInformational(executionState.OperationContext, SR.TraceUpload);
                            MultiBufferMemoryStream multiBufferMemoryStream = executionState.RestCMD.SendStream as MultiBufferMemoryStream;

                            try
                            {
                                if (multiBufferMemoryStream != null && !executionState.RestCMD.SendStreamLength.HasValue)
                                {
                                    multiBufferMemoryStream.FastCopyTo(executionState.ReqStream, executionState.OperationExpiryTime);
                                }
                                else
                                {
                                    // don't calculate md5 here as we should have already set this for auth purposes
                                    executionState.RestCMD.SendStream.WriteToSync(executionState.ReqStream, executionState.RestCMD.SendStreamLength, null /* maxLength */, false, true, executionState, null /* streamCopyState */);
                                }

                                executionState.ReqStream.Flush();
                                executionState.ReqStream.Dispose();
                                executionState.ReqStream = null;
                            }
                            catch (Exception)
                            {
                                executionState.Req.Abort();
                                throw;
                            }
                        }

                        // 6. Get response
                        try
                        {
                            executionState.CurrentOperation = ExecutorOperation.BeginGetResponse;
                            Logger.LogInformational(executionState.OperationContext, SR.TraceGetResponse);
                            executionState.Req.Timeout      = (int)executionState.RemainingTimeout.TotalMilliseconds;
                            executionState.Resp             = (HttpWebResponse)executionState.Req.GetResponse();
                            executionState.CurrentOperation = ExecutorOperation.EndGetResponse;
                        }
                        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
                            {
                                executionState.ExceptionRef = StorageException.TranslateException(ex, executionState.Cmd.CurrentResult);
                            }
                        }

                        // Response
                        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;
                            executionState.Result           = executionState.RestCMD.PreProcessResponse(executionState.RestCMD, executionState.Resp, executionState.ExceptionRef, executionState.OperationContext);

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

                        // 8. (Potentially reads stream from server)
                        executionState.CurrentOperation       = ExecutorOperation.GetResponseStream;
                        executionState.RestCMD.ResponseStream = executionState.Resp.GetResponseStream();

                        if (!executionState.RestCMD.RetrieveResponseStream)
                        {
                            executionState.RestCMD.DestinationStream = Stream.Null;
                        }

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

                            try
                            {
                                executionState.CurrentOperation = ExecutorOperation.BeginDownloadResponse;
                                Logger.LogInformational(executionState.OperationContext, SR.TraceDownload);
                                executionState.RestCMD.ResponseStream.WriteToSync(executionState.RestCMD.DestinationStream, null /* copyLength */, null /* maxLength */, executionState.RestCMD.CalculateMd5ForResponseStream, false, executionState, executionState.RestCMD.StreamCopyState);
                            }
                            finally
                            {
                                executionState.RestCMD.ResponseStream.Dispose();
                                executionState.RestCMD.ResponseStream = null;
                            }
                        }

                        // Step 9 - This will not be called if an exception is raised during stream copying
                        Executor.ProcessEndOfRequest(executionState);

                        Executor.FinishRequestAttempt(executionState);
                        return(executionState.Result);
                    }
                    catch (Exception e)
                    {
                        Logger.LogWarning(executionState.OperationContext, SR.TraceGenericError, e.Message);
                        Executor.FinishRequestAttempt(executionState);

                        StorageException translatedException = StorageException.TranslateException(e, executionState.Cmd.CurrentResult);
                        executionState.ExceptionRef = translatedException;
                        Logger.LogInformational(executionState.OperationContext, SR.TraceRetryCheck, executionState.RetryCount, executionState.Cmd.CurrentResult.HttpStatusCode, translatedException.IsRetryable ? "yes" : "no", translatedException.Message);

                        shouldRetry = false;
                        if (translatedException.IsRetryable && (executionState.RetryPolicy != null))
                        {
                            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;
                            }
                        }
                    }
                    finally
                    {
                        if (executionState.Resp != null)
                        {
                            executionState.Resp.Close();
                            executionState.Resp = null;
                        }
                    }

                    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);
                        throw executionState.ExceptionRef;
                    }
                    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);
                            Thread.Sleep(delay);
                        }

                        Logger.LogInformational(executionState.OperationContext, SR.TraceRetry);
                    }
                }while (shouldRetry);
            }

            // should never get here, either return, or throw;
            throw new NotImplementedException(SR.InternalStorageError);
        }