Esempio n. 1
0
        private WriteResult HandleWriteException(Message message, Exception ex)
        {
            var inner = new RedisConnectionException(ConnectionFailureType.InternalFailure, "Failed to write", ex);

            message.SetExceptionAndComplete(inner, this);
            return(WriteResult.WriteFailure);
        }
Esempio n. 2
0
        internal static Exception NoConnectionAvailable(bool includeDetail, bool includePerformanceCounters, RedisCommand command, Message message, ServerEndPoint server, ReadOnlySpan <ServerEndPoint> serverSnapshot)
        {
            string commandLabel = GetLabel(includeDetail, command, message);

            if (server != null)
            {
                //if we already have the serverEndpoint for connection failure use that
                //otherwise it would output state of all the endpoints
                serverSnapshot = new ServerEndPoint[] { server };
            }

            var innerException = PopulateInnerExceptions(serverSnapshot);

            StringBuilder exceptionmessage         = new StringBuilder("No connection is available to service this operation: ").Append(commandLabel);
            string        innermostExceptionstring = GetInnerMostExceptionMessage(innerException);

            if (!string.IsNullOrEmpty(innermostExceptionstring))
            {
                exceptionmessage.Append("; ").Append(innermostExceptionstring);
            }

            if (includeDetail)
            {
                exceptionmessage.Append("; ").Append(PerfCounterHelper.GetThreadPoolAndCPUSummary(includePerformanceCounters));
            }

            var ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, exceptionmessage.ToString(), innerException, message?.Status ?? CommandStatus.Unknown);

            if (includeDetail)
            {
                AddDetail(ex, message, server, commandLabel);
            }
            return(ex);
        }
Esempio n. 3
0
        internal static Exception ConnectionFailure(bool includeDetail, ConnectionFailureType failureType, string message, ServerEndPoint server)
        {
            var ex = new RedisConnectionException(failureType, message);

            if (includeDetail)
            {
                AddExceptionDetail(ex, null, server, null);
            }
            return(ex);
        }
Esempio n. 4
0
        internal static Exception NoConnectionAvailable(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server)
        {
            string s  = GetLabel(includeDetail, command, message);
            var    ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, "No connection is available to service this operation: " + s);

            if (includeDetail)
            {
                AddDetail(ex, message, server, s);
            }
            return(ex);
        }
Esempio n. 5
0
        internal static Exception NoConnectionAvailable(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server, ServerEndPoint[] serverSnapshot)
        {
            string s = GetLabel(includeDetail, command, message);

            if (server != null)
            {
                //if we already have the serverEndpoint for connection failure use that
                //otherwise it would output state of all the endpoints
                serverSnapshot = new ServerEndPoint[] { server };
            }
            string exceptionmessage = "No connection is available to service this operation: " + s;
            var    ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, exceptionmessage, GetServerSnapshotInnerExceptions(serverSnapshot));

            if (includeDetail)
            {
                AddDetail(ex, message, server, s);
            }
            return(ex);
        }
Esempio n. 6
0
        internal static Exception NoConnectionAvailable(
            ConnectionMultiplexer multiplexer,
            Message message,
            ServerEndPoint server,
            ReadOnlySpan <ServerEndPoint> serverSnapshot = default,
            RedisCommand command = default)
        {
            string commandLabel = GetLabel(multiplexer.IncludeDetailInExceptions, message?.Command ?? command, message);

            if (server != null)
            {
                //if we already have the serverEndpoint for connection failure use that
                //otherwise it would output state of all the endpoints
                serverSnapshot = new ServerEndPoint[] { server };
            }

            var innerException = PopulateInnerExceptions(serverSnapshot == default ? multiplexer.GetServerSnapshot() : serverSnapshot);

            // Try to get a useful error message for the user.
            long   attempts = multiplexer._connectAttemptCount, completions = multiplexer._connectCompletedCount;
            string initialMessage;

            // We only need to customize the connection if we're aborting on connect fail
            // The "never" case would have thrown, if this was true
            if (!multiplexer.RawConfig.AbortOnConnectFail && attempts <= multiplexer.RawConfig.ConnectRetry && completions == 0)
            {
                // Initial attempt, attempted use before an async connection completes
                initialMessage = $"Connection to Redis never succeeded (attempts: {attempts} - connection likely in-progress), unable to service operation: ";
            }
            else if (!multiplexer.RawConfig.AbortOnConnectFail && attempts > multiplexer.RawConfig.ConnectRetry && completions == 0)
            {
                // Attempted use after a full initial retry connect count # of failures
                // This can happen in Azure often, where user disables abort and has the wrong config
                initialMessage = $"Connection to Redis never succeeded (attempts: {attempts} - check your config), unable to service operation: ";
            }
            else
            {
                // Default if we don't have a more useful error message here based on circumstances
                initialMessage = "No connection is active/available to service this operation: ";
            }

            StringBuilder sb = new StringBuilder(initialMessage);

            sb.Append(commandLabel);
            string innermostExceptionstring = GetInnerMostExceptionMessage(innerException);

            if (!string.IsNullOrEmpty(innermostExceptionstring))
            {
                sb.Append("; ").Append(innermostExceptionstring);
            }

            // Add counters and exception data if we have it
            List <Tuple <string, string> > data = null;

            if (multiplexer.IncludeDetailInExceptions)
            {
                data = new List <Tuple <string, string> >();
                AddCommonDetail(data, sb, message, multiplexer, server);
            }
            var ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, sb.ToString(), innerException, message?.Status ?? CommandStatus.Unknown);

            if (multiplexer.IncludeDetailInExceptions)
            {
                CopyDataToException(data, ex);
                sb.Append("; ").Append(PerfCounterHelper.GetThreadPoolAndCPUSummary(multiplexer.IncludePerformanceCountersInExceptions));
                AddExceptionDetail(ex, message, server, commandLabel);
            }
            return(ex);
        }
        /// <summary>
        /// This writes a message to the output stream
        /// </summary>
        /// <param name="physical">The phsyical connection to write to.</param>
        /// <param name="message">The message to be written.</param>
        internal WriteResult WriteMessageTakingWriteLock(PhysicalConnection physical, Message message)
        {
            Trace("Writing: " + message);
            message.SetEnqueued();

            WriteResult result;
            bool        haveLock = false;

            try
            {
                Monitor.TryEnter(SingleWriterLock, TimeoutMilliseconds, ref haveLock);
                if (!haveLock)
                {
                    message.Cancel();
                    Multiplexer?.OnMessageFaulted(message, null);
                    this.CompleteSyncOrAsync(message);
                    return(WriteResult.TimeoutBeforeWrite);
                }

                var existingMessage = Interlocked.CompareExchange(ref _activeMesssage, message, null);
                if (existingMessage != null)
                {
                    Multiplexer?.OnInfoMessage($"reentrant call to WriteMessageTakingWriteLock for {message.CommandAndKey}, {existingMessage.CommandAndKey} is still active");
                    return(WriteResult.NoConnectionAvailable);
                }
                physical.SetWriting();
                var messageIsSent = false;
                if (message is IMultiMessage)
                {
                    SelectDatabaseInsideWriteLock(physical, message); // need to switch database *before* the transaction
                    foreach (var subCommand in ((IMultiMessage)message).GetMessages(physical))
                    {
                        result = WriteMessageToServerInsideWriteLock(physical, subCommand);
                        if (result != WriteResult.Success)
                        {
                            // we screwed up; abort; note that WriteMessageToServer already
                            // killed the underlying connection
                            Trace("Unable to write to server");
                            message.Fail(ConnectionFailureType.ProtocolFailure, null, "failure before write: " + result.ToString());
                            this.CompleteSyncOrAsync(message);
                            return(result);
                        }
                        //The parent message (next) may be returned from GetMessages
                        //and should not be marked as sent again below
                        messageIsSent = messageIsSent || subCommand == message;
                    }
                    if (!messageIsSent)
                    {
                        message.SetRequestSent(); // well, it was attempted, at least...
                    }

                    result = WriteResult.Success;
                }
                else
                {
                    result = WriteMessageToServerInsideWriteLock(physical, message);
                }

                if (result == WriteResult.Success)
                {
                    result = physical.FlushSync();
                }
                physical.SetIdle();
            }
            catch (Exception ex)
            {
                var inner = new RedisConnectionException(ConnectionFailureType.InternalFailure, "Failed to write", ex);
                message.SetExceptionAndComplete(inner, this);
                result = WriteResult.WriteFailure;
            }
            finally
            {
                if (haveLock)
                {
                    Interlocked.CompareExchange(ref _activeMesssage, null, message); // remove if it is us
                    Monitor.Exit(SingleWriterLock);
                }
            }

            return(result);
        }