//! \~\file pidiagnostics.h //! \~\ingroup IO-Utils //! \~\brief //! \~english Connection quality diagnostics //! \~russian Диагностика качества связи /* PIP - Platform Independent Primitives Speed and quality in/out diagnostics Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIDIAGNOSTICS_H #define PIDIAGNOSTICS_H #include "piqueue.h" #include "pitimer.h" //! \~\ingroup IO-Utils //! \brief //! \~english Connection diagnostics for packet frequency, throughput and receive quality //! \~russian Диагностика соединения для частоты пакетов, пропускной способности и качества приема //! \details //! \~english This class provides connection quality diagnostics based on packet reception statistics //! \~russian Класс обеспечивает диагностику качества связи на основе статистики приема пакетов class PIP_EXPORT PIDiagnostics: public PITimer { PIOBJECT_SUBCLASS(PIDiagnostics, PITimer); friend class PIConnection; public: NO_COPY_CLASS(PIDiagnostics); //! \~english Constructs diagnostics and optionally starts periodic evaluation immediately. //! \~russian Создает диагностику и при необходимости сразу запускает периодическую оценку. PIDiagnostics(bool start_ = true); //! \~english Stops diagnostics updates. //! \~russian Останавливает обновление диагностики. virtual ~PIDiagnostics(); //! \~english Receive quality estimated from recent packet history. //! \~russian Качество приема, оцениваемое по недавней истории пакетов. enum Quality { Unknown = 1 /** \~english No receive history yet \~russian История приема еще отсутствует */, Failure = 2 /** \~english No correct packets in the recent window \~russian В недавнем окне нет корректных пакетов */, Bad = 3 /** \~english Correct packets are at most 20 percent \~russian Корректных пакетов не более 20 процентов */, Average = 4 /** \~english Correct packets are above 20 and up to 80 percent \~russian Корректных пакетов больше 20 и до 80 процентов */ , Good = 5 /** \~english Correct packets are above 80 percent \~russian Корректных пакетов больше 80 процентов */ }; //! \~english Snapshot of current counters and derived statistics. //! \~russian Снимок текущих счетчиков и производных статистик. struct PIP_EXPORT State { //! \~english Constructs zeroed state with formatted speed strings. //! \~russian Создает обнуленное состояние с отформатированными строками скоростей. State(); //! \~english Latest receive frequency for the current timer interval. //! \~russian Последняя частота приема для текущего интервала таймера. float immediate_freq = 0.f; //! \~english Averaged receive frequency over the disconnect window. //! \~russian Усредненная частота приема по окну отключения. float integral_freq = 0.f; //! \~english Number of correct received packets per second. //! \~russian Число корректно принятых пакетов в секунду. ullong received_packets_per_sec = 0ull; //! \~english Total number of correct received packets. //! \~russian Общее число корректно принятых пакетов. ullong received_packets = 0ull; //! \~english Total number of incorrect received packets. //! \~russian Общее число некорректно принятых пакетов. ullong received_packets_wrong = 0ull; //! \~english Number of received bytes per second. //! \~russian Число принятых байтов в секунду. ullong received_bytes_per_sec = 0ull; //! \~english Total number of correctly received bytes. //! \~russian Общее число корректно принятых байтов. ullong received_bytes = 0ull; //! \~english Total number of bytes from incorrect packets. //! \~russian Общее число байтов из некорректных пакетов. ullong received_bytes_wrong = 0ull; //! \~english Number of sent packets per second. //! \~russian Число отправленных пакетов в секунду. ullong sended_packets_per_sec = 0ull; //! \~english Total number of sent packets. //! \~russian Общее число отправленных пакетов. ullong sended_packets = 0ull; //! \~english Number of sent bytes per second. //! \~russian Число отправленных байтов в секунду. ullong sended_bytes_per_sec = 0ull; //! \~english Total number of sent bytes. //! \~russian Общее число отправленных байтов. ullong sended_bytes = 0ull; //! \~english Human-readable receive speed string. //! \~russian Строка скорости приема в человекочитаемом виде. PIString receive_speed; //! \~english Human-readable send speed string. //! \~russian Строка скорости отправки в человекочитаемом виде. PIString send_speed; //! \~english Current receive quality category. //! \~russian Текущая категория качества приема. PIDiagnostics::Quality quality = PIDiagnostics::Unknown; }; //! \~english Returns a thread-safe snapshot of current diagnostics state. //! \~russian Возвращает потокобезопасный снимок текущего состояния диагностики. PIDiagnostics::State state() const; //! \~english Returns the disconnect timeout and averaging window. //! \~russian Возвращает таймаут отключения и окно усреднения. PISystemTime disconnectTimeout() const { return disconn_; } //! \~english Sets the disconnect timeout in seconds. //! \~russian Устанавливает таймаут отключения в секундах. void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") { setDisconnectTimeout(PISystemTime::fromSeconds(s)); } //! \~english Sets the disconnect timeout and averaging window. //! \~russian Устанавливает таймаут отключения и окно усреднения. void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); } //! \~english Returns current receive quality. //! \~russian Возвращает текущее качество приема. PIDiagnostics::Quality quality() const; //! \~english Returns formatted receive throughput string. //! \~russian Возвращает строку отформатированной скорости приема. PIString receiveSpeed() const; //! \~english Returns formatted send throughput string. //! \~russian Возвращает строку отформатированной скорости отправки. PIString sendSpeed() const; //! \handlers //! \{ //! \fn void start() //! \~english Starts periodic diagnostics evaluation with the default interval. //! \~russian Запускает периодическую оценку диагностики с интервалом по умолчанию. EVENT_HANDLER0(void, start); //! \fn void start(PISystemTime interval) //! \~english Starts periodic diagnostics evaluation with interval "interval". //! \~russian Запускает периодическую оценку диагностики с интервалом "interval". EVENT_HANDLER1(void, start, PISystemTime, interval); //! \fn void reset() //! \~english Resets counters, rolling history and derived statistics. //! \~russian Сбрасывает счетчики, скользящую историю и производные статистики. EVENT_HANDLER0(void, reset); //! \fn void received(int size, bool correct = true) //! \~english Notifies diagnostics about one received packet of size "size". //! \~russian Уведомляет диагностику об одном принятом пакете размером "size". EVENT_HANDLER1(void, received, int, size) { received(size, true); } EVENT_HANDLER2(void, received, int, size, bool, correct); //! \fn void sended(int size) //! \~english Notifies diagnostics about one sent packet of size "size". //! \~russian Уведомляет диагностику об одном отправленном пакете размером "size". EVENT_HANDLER1(void, sended, int, size); //! \} //! \events //! \{ //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \~english Emitted when receive quality changes from "old_quality" to "new_quality". //! \~russian Генерируется при изменении качества приема с "old_quality" на "new_quality". EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); //! \} private: struct PIP_EXPORT Entry { ullong bytes_ok = 0; ullong bytes_fail = 0; uint cnt_ok = 0; uint cnt_fail = 0; bool empty = true; }; friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); void tick(int) override; Entry calcHistory(PIQueue & hist, int & cnt); void propertyChanged(const char *) override; void changeDisconnectTimeout(PISystemTime disct); PIQueue history_rec, history_send; PISystemTime disconn_; State cur_state; mutable PIMutex mutex_state; }; inline bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) { return f.bytes_ok == s.bytes_ok && f.bytes_fail == s.bytes_fail && f.cnt_ok == s.cnt_ok && f.cnt_fail == s.cnt_fail && f.empty == s.empty; } inline bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) { return !(f == s); } inline bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) { return f.bytes_ok < s.bytes_ok; } #endif // PIDIAGNOSTICS_H