FixAntenna/NetCore/FixEngine/Session/Util/SessionStatusCheckerThread.cs (80 lines of code) (raw):

// Copyright (c) 2021 EPAM Systems // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.Diagnostics; using System.Threading; using Epam.FixAntenna.NetCore.Common.Logging; namespace Epam.FixAntenna.NetCore.FixEngine.Session.Util { /// <summary> /// Checks the session status after specific timeout, if the session state is /// the same disconnect the session with specific reason. /// </summary> internal class SessionStatusCheckerThread/* : WorkerThread*/ { private const int Second = 1000; private static readonly ILog Log = LogFactory.GetLog(typeof(SessionStatusCheckerThread)); private readonly IExtendedFixSession _session; private readonly int _timeout; private readonly SessionState _state; private readonly string _reason; private readonly bool _deliverError; private readonly Thread _thread; //TODO: implement logic private readonly Stopwatch _stopWatch; private readonly object _sync = new object(); /// <summary> /// Creates the <c>SessionStatusCheckerThread</c>. /// </summary> /// <param name="session"> the monitored session </param> /// <param name="timeout"> the time to wait before close the session </param> /// <param name="state"> the initial session state </param> /// <param name="reason"> the closed reason if session will be closed </param> /// <param name="notifyErrorHandler"> if sets to true the session error handler /// will be notify with error level and reason message. </param> public SessionStatusCheckerThread(IExtendedFixSession session, int timeout, SessionState state, string reason, bool notifyErrorHandler = true) { _session = session; _timeout = timeout; _state = state; _stopWatch = new Stopwatch(); _reason = reason; _deliverError = notifyErrorHandler; _thread = new Thread(Run) { Name = "SessionStatusChecker" }; } public void Start() { _stopWatch.Start(); _thread.Start(); } private void Run() { if (Log.IsTraceEnabled) { Log.Trace("Start checker thread for session: " + _session + ". wait for state " + _state + " during " + _timeout); } while (_stopWatch.ElapsedMilliseconds / Second <= _timeout && _session.SessionState == _state) { lock (_sync) { try { Monitor.Wait(_sync, TimeSpan.FromMilliseconds(Second)); } catch (ThreadInterruptedException) { // intentionally blank } } } _stopWatch.Stop(); if (_session.SessionState == _state) { if (Log.IsInfoEnabled) { Log.Info("Session state is still " + _state + ". Session will be disconnected"); } if (_session.SessionState == SessionState.Connected) { _session.Disconnect(null, _reason); } else { //session.markShutdownAsGraceful(); _session.Shutdown(null, false); } if (_deliverError) { _session.ErrorHandler.OnWarn(_reason, new InvalidOperationException(_reason)); } } if (Log.IsTraceEnabled) { Log.Trace("Stop checker thread for session: " + _session); } } } }