示例#1
0
        /// <summary>
        /// Gets the retry decision based on the request error
        /// </summary>
        internal static RetryDecisionWithReason GetRetryDecisionWithReason(
            IRequestError error, IExtendedRetryPolicy policy, IStatement statement, Configuration config, int retryCount)
        {
            var ex = error.Exception;

            if (ex is SocketException || ex is OverloadedException || ex is IsBootstrappingException || ex is TruncateException ||
                ex is OperationTimedOutException)
            {
                if (ex is SocketException exception)
                {
                    RequestExecution.Logger.Verbose("Socket error " + exception.SocketErrorCode);
                }

                // For PREPARE requests, retry on next host
                var decision = statement == null && ex is OperationTimedOutException
                    ? RetryDecision.Retry(null, false)
                    : policy.OnRequestError(statement, config, ex, retryCount);

                return(new RetryDecisionWithReason(decision, RequestExecution.GetErrorType(error)));
            }

            if (ex is ReadTimeoutException e)
            {
                return(new RetryDecisionWithReason(
                           policy.OnReadTimeout(
                               statement,
                               e.ConsistencyLevel,
                               e.RequiredAcknowledgements,
                               e.ReceivedAcknowledgements,
                               e.WasDataRetrieved,
                               retryCount),
                           RequestErrorType.ReadTimeOut
                           ));
            }

            if (ex is WriteTimeoutException e1)
            {
                return(new RetryDecisionWithReason(
                           policy.OnWriteTimeout(
                               statement,
                               e1.ConsistencyLevel,
                               e1.WriteType,
                               e1.RequiredAcknowledgements,
                               e1.ReceivedAcknowledgements,
                               retryCount),
                           RequestErrorType.WriteTimeOut
                           ));
            }

            if (ex is UnavailableException e2)
            {
                return(new RetryDecisionWithReason(
                           policy.OnUnavailable(statement, e2.Consistency, e2.RequiredReplicas, e2.AliveReplicas, retryCount),
                           RequestErrorType.Unavailable
                           ));
            }

            // Any other Exception just throw it
            return(new RetryDecisionWithReason(RetryDecision.Rethrow(), RequestExecution.GetErrorType(error)));
        }
示例#2
0
        /// <summary>
        /// Handles the response of a (re)prepare request and retries to execute on the same connection
        /// </summary>
        private void ReprepareResponseHandler(IRequestError error, Response response, Host host)
        {
            try
            {
                if (error?.Exception != null)
                {
                    HandleRequestError(error, host);
                    return;
                }
                RequestExecution.ValidateResult(response);
                var output = ((ResultResponse)response).Output;
                if (!(output is OutputPrepared outputPrepared))
                {
                    _parent.SetCompleted(
                        new DriverInternalError("Expected prepared response, obtained " + output.GetType().FullName));
                    return;
                }

                if (_parent.Statement is BoundStatement boundStatement)
                {
                    // Use the latest result metadata id
                    boundStatement.PreparedStatement.ResultMetadataId = outputPrepared.ResultMetadataId;
                }
                Send(_request, host, HandleResponse);
            }
            catch (Exception exception)
            {
                //There was an issue while sending
                _parent.SetCompleted(exception);
            }
        }
        /// <summary>
        /// Checks if the exception is either a Cassandra response error or a socket exception to retry or failover if necessary.
        /// </summary>
        private void HandleRequestError(IRequestError error, Host host)
        {
            var ex = error.Exception;

            RequestExecution.Logger.Info("RequestHandler received exception {0}", ex.ToString());
            if (ex is PreparedQueryNotFoundException foundException &&
                (_parent.Statement is BoundStatement || _parent.Statement is BatchStatement))
            {
                PrepareAndRetry(foundException.UnknownId, host);
                return;
            }
            if (ex is NoHostAvailableException exception)
            {
                //A NoHostAvailableException when trying to retrieve
                _parent.SetNoMoreHosts(exception, this);
                return;
            }

            _triedHosts[host.Address] = ex;
            if (ex is OperationTimedOutException)
            {
                RequestExecution.Logger.Warning(ex.Message);
                var connection = _connection;
                if (connection == null)
                {
                    RequestExecution.Logger.Error("Connection must not be null");
                }
                else
                {
                    // Checks how many timed out operations are in the connection
                    _session.CheckHealth(host, connection);
                }
            }

            var retryInformation = GetRetryDecisionWithReason(
                error, _parent.RetryPolicy, _parent.Statement, _session.Cluster.Configuration, _retryCount);

            switch (retryInformation.Decision.DecisionType)
            {
            case RetryDecision.RetryDecisionType.Rethrow:
                _parent.SetCompleted(ex);
                break;

            case RetryDecision.RetryDecisionType.Ignore:
                // The error was ignored by the RetryPolicy, return an empty rowset
                _parent.SetCompleted(null, FillRowSet(RowSet.Empty(), null));
                break;

            case RetryDecision.RetryDecisionType.Retry:
                //Retry the Request using the new consistency level
                Retry(retryInformation.Decision.RetryConsistencyLevel, retryInformation.Decision.UseCurrentHost, host);
                break;
            }

            _requestObserver.OnRequestError(host, retryInformation.Reason, retryInformation.Decision.DecisionType);
        }
        private void EventHandler(IRequestError error, Response response, long timestamp)
        {
            if (!(response is EventResponse))
            {
                Connection.Logger.Error("Unexpected response type for event: " + response.GetType().Name);
                return;
            }

            CassandraEventResponse?.Invoke(this, ((EventResponse)response).CassandraEventArgs);
        }
示例#5
0
 /// <summary>
 /// Asynchronously marks the provided operations as completed and invoke the callbacks with the exception.
 /// </summary>
 internal static void CallbackMultiple(IEnumerable <OperationState> ops, IRequestError error, long timestamp)
 {
     Task.Factory.StartNew(() =>
     {
         foreach (var state in ops)
         {
             var callback = state.SetCompleted();
             callback(error, null, timestamp);
         }
     }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
 }
示例#6
0
 /// <summary>
 /// Attempts to transition the underlying Task to RanToCompletion or Faulted state.
 /// </summary>
 public static void TrySetRequestError <T>(this TaskCompletionSource <T> tcs, IRequestError error, T result)
 {
     if (error?.Exception != null)
     {
         tcs.TrySetException(error.Exception);
     }
     else
     {
         tcs.TrySetResult(result);
     }
 }
示例#7
0
        /// <summary>
        /// Marks this operation as completed and invokes the callback with the exception using the default task scheduler.
        /// Its safe to call this method multiple times as the underlying callback will be invoked just once.
        /// </summary>
        public void InvokeCallback(IRequestError error, long timestamp)
        {
            var callback = SetCompleted();

            if (callback == Noop)
            {
                return;
            }
            //Invoke the callback in a new thread in the thread pool
            //This way we don't let the user block on a thread used by the Connection
            Task.Factory.StartNew(() => callback(error, null, timestamp), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
        }
示例#8
0
        private static RequestErrorType GetErrorType(IRequestError error)
        {
            if (error.Exception is OperationTimedOutException)
            {
                return(RequestErrorType.ClientTimeout);
            }

            if (error.Unsent)
            {
                return(RequestErrorType.Unsent);
            }

            return(error.IsServerError ? RequestErrorType.Other : RequestErrorType.Aborted);
        }
示例#9
0
 private void HandleResponse(IRequestError error, Response response, Host host)
 {
     if (_parent.HasCompleted())
     {
         //Do nothing else, another execution finished already set the response
         return;
     }
     try
     {
         if (error?.Exception != null)
         {
             HandleRequestError(error, host);
             return;
         }
         HandleRowSetResult(response);
     }
     catch (Exception handlerException)
     {
         _parent.SetCompleted(handlerException);
     }
 }
        public void OnOperationReceive(IRequestError error, Response response, long timestamp)
        {
            if (!_enabledNodeTimerMetrics)
            {
                return;
            }

            try
            {
                var startTimestamp = Volatile.Read(ref _startTimestamp);
                if (startTimestamp == 0)
                {
                    MetricsOperationObserver.Logger.Warning("Start timestamp wasn't recorded, discarding this measurement.");
                    return;
                }

                _operationTimer.Record((timestamp - startTimestamp) * MetricsOperationObserver.Factor);
            }
            catch (Exception ex)
            {
                MetricsOperationObserver.LogError(ex);
            }
        }
示例#11
0
        /// <summary>
        /// Returns an action that capture the parameters closure
        /// </summary>
        private Action <MemoryStream, long> CreateResponseAction(
            ResultMetadata resultMetadata, ISerializer serializer, FrameHeader header, Action <IRequestError, Response, long> callback)
        {
            var compressor = Compressor;

            void DeserializeResponseStream(MemoryStream stream, long timestamp)
            {
                Response      response     = null;
                IRequestError error        = null;
                var           nextPosition = stream.Position + header.BodyLength;

                try
                {
                    Stream plainTextStream = stream;
                    if (header.Flags.HasFlag(HeaderFlags.Compression))
                    {
                        plainTextStream          = compressor.Decompress(new WrappedStream(stream, header.BodyLength));
                        plainTextStream.Position = 0;
                    }
                    response = FrameParser.Parse(new Frame(header, plainTextStream, serializer, resultMetadata));
                }
                catch (Exception caughtException)
                {
                    error = RequestError.CreateClientError(caughtException, false);
                }
                if (response is ErrorResponse errorResponse)
                {
                    error    = RequestError.CreateServerError(errorResponse);
                    response = null;
                }
                //We must advance the position of the stream manually in case it was not correctly parsed
                stream.Position = nextPosition;
                callback(error, response, timestamp);
            }

            return(DeserializeResponseStream);
        }
 public void OnOperationReceive(IRequestError error, Response response, long timestamp)
 {
 }