public void RecordConnectionFailed(ConnectionFailureType failureType, Exception innerException = null, [CallerMemberName] string origin = null)
        {
            IdentifyFailureType(innerException, ref failureType);

            if (failureType == ConnectionFailureType.InternalFailure)
            {
                OnInternalError(innerException, origin);
            }

            // stop anything new coming in...
            bridge.Trace("Failed: " + failureType);
            bool isCurrent;

            PhysicalBridge.State oldState;
            bridge.OnDisconnected(failureType, this, out isCurrent, out oldState);

            if (isCurrent && Interlocked.CompareExchange(ref failureReported, 1, 0) == 0)
            {
                int now = Environment.TickCount, lastRead = Thread.VolatileRead(ref lastReadTickCount), lastWrite = Thread.VolatileRead(ref lastWriteTickCount),
                    lastBeat       = Thread.VolatileRead(ref lastBeatTickCount);
                int unansweredRead = Thread.VolatileRead(ref firstUnansweredWriteTickCount);

                string message = failureType + " on " + Format.ToString(bridge.ServerEndPoint.EndPoint) + "/" + connectionType
                                 + ", origin: " + origin
                                 + ", input-buffer: " + ioBufferBytes + ", outstanding: " + GetSentAwaitingResponseCount()
                                 + ", last-read: " + unchecked (now - lastRead) / 1000 + "s ago, last-write: " + unchecked (now - lastWrite) / 1000 + "s ago"
                                 + ", unanswered-write: " + unchecked (now - unansweredRead) / 1000 + "s ago"
                                 + ", keep-alive: " + bridge.ServerEndPoint.WriteEverySeconds + "s, pending: "
                                 + bridge.GetPendingCount() + ", state: " + oldState + ", last-heartbeat: " + (lastBeat == 0 ? "never" : (unchecked (now - lastBeat) / 1000 + "s ago"))
                                 + (bridge.IsBeating ? " (mid-beat)" : "") + ", last-mbeat: " + multiplexer.LastHeartbeatSecondsAgo + "s ago, global: "
                                 + ConnectionMultiplexer.LastGlobalHeartbeatSecondsAgo + "s ago";

                var ex = innerException == null
                    ? new RedisConnectionException(failureType, message)
                    : new RedisConnectionException(failureType, message, innerException);

                bridge.OnConnectionFailed(this, failureType, ex);
            }

            // cleanup
            lock (outstanding)
            {
                bridge.Trace(outstanding.Count != 0, "Failing outstanding messages: " + outstanding.Count);
                while (outstanding.Count != 0)
                {
                    var next = outstanding.Dequeue();
                    bridge.Trace("Failing: " + next);
                    next.Fail(failureType, innerException);
                    bridge.CompleteSyncOrAsync(next);
                }
            }

            // burn the socket
            var socketManager = multiplexer.SocketManager;

            if (socketManager != null)
            {
                socketManager.Shutdown(socketToken);
            }
        }
        public void RecordConnectionFailed(ConnectionFailureType failureType, ref SocketManager.ManagerState managerState, Exception innerException = null, [CallerMemberName] string origin = null)
        {
            IdentifyFailureType(innerException, ref failureType);

            managerState = SocketManager.ManagerState.RecordConnectionFailed_OnInternalError;
            if (failureType == ConnectionFailureType.InternalFailure)
            {
                OnInternalError(innerException, origin);
            }

            // stop anything new coming in...
            bridge.Trace("Failed: " + failureType);
            bool isCurrent;

            PhysicalBridge.State oldState;
            int @in = -1, ar = -1;

            managerState = SocketManager.ManagerState.RecordConnectionFailed_OnDisconnected;
            bridge.OnDisconnected(failureType, this, out isCurrent, out oldState);
            if (oldState == PhysicalBridge.State.ConnectedEstablished)
            {
                try
                {
                    @in = GetAvailableInboundBytes(out ar);
                }
                catch { /* best effort only */ }
            }

            if (isCurrent && Interlocked.CompareExchange(ref failureReported, 1, 0) == 0)
            {
                managerState = SocketManager.ManagerState.RecordConnectionFailed_ReportFailure;
                int now = Environment.TickCount, lastRead = Thread.VolatileRead(ref lastReadTickCount), lastWrite = Thread.VolatileRead(ref lastWriteTickCount),
                    lastBeat       = Thread.VolatileRead(ref lastBeatTickCount);
                int unansweredRead = Thread.VolatileRead(ref firstUnansweredWriteTickCount);

                var exMessage = new StringBuilder(failureType + " on " + Format.ToString(bridge.ServerEndPoint.EndPoint) + "/" + connectionType);
                var data      = new List <Tuple <string, string> >
                {
                    Tuple.Create("FailureType", failureType.ToString()),
                    Tuple.Create("EndPoint", Format.ToString(bridge.ServerEndPoint.EndPoint))
                };
                Action <string, string, string> add = (lk, sk, v) =>
                {
                    data.Add(Tuple.Create(lk, v));
                    exMessage.Append(", " + sk + ": " + v);
                };

                add("Origin", "origin", origin);
                add("Input-Buffer", "input-buffer", ioBufferBytes.ToString());
                add("Outstanding-Responses", "outstanding", GetSentAwaitingResponseCount().ToString());
                add("Last-Read", "last-read", unchecked (now - lastRead) / 1000 + "s ago");
                add("Last-Write", "last-write", unchecked (now - lastWrite) / 1000 + "s ago");
                add("Unanswered-Write", "unanswered-write", unchecked (now - unansweredRead) / 1000 + "s ago");
                add("Keep-Alive", "keep-alive", bridge.ServerEndPoint.WriteEverySeconds + "s");
                add("Pending", "pending", bridge.GetPendingCount().ToString());
                add("Previous-Physical-State", "state", oldState.ToString());

                if (@in >= 0)
                {
                    add("Inbound-Bytes", "in", @in.ToString());
                    add("Active-Readers", "ar", ar.ToString());
                }

                add("Last-Heartbeat", "last-heartbeat", (lastBeat == 0 ? "never" : (unchecked (now - lastBeat) / 1000 + "s ago")) + (bridge.IsBeating ? " (mid-beat)" : ""));
                add("Last-Multiplexer-Heartbeat", "last-mbeat", multiplexer.LastHeartbeatSecondsAgo + "s ago");
                add("Last-Global-Heartbeat", "global", ConnectionMultiplexer.LastGlobalHeartbeatSecondsAgo + "s ago");
#if !__MonoCS__
                var mgr = bridge.Multiplexer.SocketManager;
                add("SocketManager-State", "mgr", mgr.State.ToString());
                add("Last-Error", "err", mgr.LastErrorTimeRelative());
#endif

                var ex = innerException == null
                    ? new RedisConnectionException(failureType, exMessage.ToString())
                    : new RedisConnectionException(failureType, exMessage.ToString(), innerException);

                foreach (var kv in data)
                {
                    ex.Data["Redis-" + kv.Item1] = kv.Item2;
                }

                managerState = SocketManager.ManagerState.RecordConnectionFailed_OnConnectionFailed;
                bridge.OnConnectionFailed(this, failureType, ex);
            }

            // cleanup
            managerState = SocketManager.ManagerState.RecordConnectionFailed_FailOutstanding;
            lock (outstanding)
            {
                bridge.Trace(outstanding.Count != 0, "Failing outstanding messages: " + outstanding.Count);
                while (outstanding.Count != 0)
                {
                    var next = outstanding.Dequeue();
                    bridge.Trace("Failing: " + next);
                    next.Fail(failureType, innerException);
                    bridge.CompleteSyncOrAsync(next);
                }
            }

            // burn the socket
            managerState = SocketManager.ManagerState.RecordConnectionFailed_ShutdownSocket;
            var socketManager = multiplexer.SocketManager;
            if (socketManager != null)
            {
                socketManager.Shutdown(socketToken);
            }
        }