예제 #1
0
 internal void OnFullyEstablished(PhysicalConnection connection)
 {
     Trace("OnFullyEstablished");
     if (physical == connection && !isDisposed && ChangeState(State.ConnectedEstablishing, State.ConnectedEstablished))
     {
         reportNextFailure = reconfigureNextFailure = true;
         LastException     = null;
         Interlocked.Exchange(ref failConnectCount, 0);
         ServerEndPoint.OnFullyEstablished(connection);
         Multiplexer.RequestWrite(this, true);
         if (ConnectionType == ConnectionType.Interactive)
         {
             ServerEndPoint.CheckInfoReplication();
         }
     }
     else
     {
         try { connection.Dispose(); } catch { }
     }
 }
예제 #2
0
        internal void OnHeartbeat(bool ifConnectedOnly)
        {
            bool runThisTime = false;

            try
            {
                runThisTime = !isDisposed && Interlocked.CompareExchange(ref beating, 1, 0) == 0;
                if (!runThisTime)
                {
                    return;
                }

                uint index          = (uint)Interlocked.Increment(ref profileLogIndex);
                long newSampleCount = Interlocked.Read(ref operationCount);
                Interlocked.Exchange(ref profileLog[index % ProfileLogSamples], newSampleCount);
                Interlocked.Exchange(ref profileLastLog, newSampleCount);
                Trace("OnHeartbeat: " + (State)state);
                switch (state)
                {
                case (int)State.Connecting:
                    int connectTimeMilliseconds = unchecked (Environment.TickCount - VolatileWrapper.Read(ref connectStartTicks));
                    if (connectTimeMilliseconds >= Multiplexer.RawConfig.ConnectTimeout)
                    {
                        LastException = ExceptionFactory.UnableToConnect("ConnectTimeout");
                        Trace("Aborting connect");
                        // abort and reconnect
                        var   snapshot = physical;
                        bool  isCurrent;
                        State oldState;
                        OnDisconnected(ConnectionFailureType.UnableToConnect, snapshot, out isCurrent, out oldState);
                        using (snapshot) { }     // dispose etc
                        TryConnect(null);
                    }
                    if (!ifConnectedOnly)
                    {
                        AbortUnsent();
                    }
                    break;

                case (int)State.ConnectedEstablishing:
                case (int)State.ConnectedEstablished:
                    var tmp = physical;
                    if (tmp != null)
                    {
                        if (state == (int)State.ConnectedEstablished)
                        {
                            tmp.Bridge.ServerEndPoint.ClearUnselectable(UnselectableFlags.DidNotRespond);
                        }
                        tmp.OnHeartbeat();
                        int writeEverySeconds  = ServerEndPoint.WriteEverySeconds,
                            checkConfigSeconds = Multiplexer.RawConfig.ConfigCheckSeconds;

                        if (state == (int)State.ConnectedEstablished && ConnectionType == ConnectionType.Interactive &&
                            checkConfigSeconds > 0 && ServerEndPoint.LastInfoReplicationCheckSecondsAgo >= checkConfigSeconds &&
                            ServerEndPoint.CheckInfoReplication())
                        {
                            // that serves as a keep-alive, if it is accepted
                        }
                        else if (writeEverySeconds > 0 && tmp.LastWriteSecondsAgo >= writeEverySeconds)
                        {
                            Trace("OnHeartbeat - overdue");
                            if (state == (int)State.ConnectedEstablished)
                            {
                                KeepAlive();
                            }
                            else
                            {
                                bool  ignore;
                                State oldState;
                                OnDisconnected(ConnectionFailureType.SocketFailure, tmp, out ignore, out oldState);
                            }
                        }
                        else if (!queue.Any() && tmp.GetSentAwaitingResponseCount() != 0)
                        {
                            // there's a chance this is a dead socket; sending data will shake that
                            // up a bit, so if we have an empty unsent queue and a non-empty sent
                            // queue, test the socket
                            KeepAlive();
                        }
                    }
                    break;

                case (int)State.Disconnected:
                    if (!ifConnectedOnly)
                    {
                        AbortUnsent();
                        Multiplexer.Trace("Resurrecting " + this.ToString());
                        GetConnection(null);
                    }
                    break;

                default:
                    if (!ifConnectedOnly)
                    {
                        AbortUnsent();
                    }
                    break;
                }
            }
            catch (Exception ex)
            {
                OnInternalError(ex);
                Trace("OnHeartbeat error: " + ex.Message);
            }
            finally
            {
                if (runThisTime)
                {
                    Interlocked.Exchange(ref beating, 0);
                }
            }
        }