Files
pip/libs/main/io_utils/pidiagnostics.h
peri4 1c7fc39b6c version 4.0.0_alpha
in almost all methods removed timeouts in milliseconds, replaced to PISystemTime
PITimer rewrite, remove internal impl, now only thread implementation, API similar to PIThread
PITimer API no longer pass void*
PIPeer, PIConnection improved stability on reinit and exit
PISystemTime new methods
pisd now exit without hanging
2024-07-30 14:18:02 +03:00

167 lines
5.5 KiB
C++

/*! \file pidiagnostics.h
* \ingroup IO
* \~\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 <http://www.gnu.org/licenses/>.
*/
#ifndef PIDIAGNOSTICS_H
#define PIDIAGNOSTICS_H
#include "piqueue.h"
#include "pitimer.h"
class PIP_EXPORT PIDiagnostics: public PITimer {
PIOBJECT_SUBCLASS(PIDiagnostics, PITimer);
friend class PIConnection;
public:
NO_COPY_CLASS(PIDiagnostics);
//! Constructs an empty diagnostics and if "start_" start it
PIDiagnostics(bool start_ = true);
virtual ~PIDiagnostics();
//! Connection quality
enum Quality {
Unknown /** Unknown, no one packet received yet */ = 1,
Failure /** No connection, no one correct packet received for last period */ = 2,
Bad /** Bad connection, correct packets received <= 20% */ = 3,
Average /** Average connection, correct packets received > 20% and <= 80% */ = 4,
Good /** Good connection, correct packets received > 80% */ = 5
};
//! Information about current diagnostics state
struct PIP_EXPORT State {
State();
float immediate_freq = 0.f;
float integral_freq = 0.f;
ullong received_packets_per_sec = 0ull;
ullong received_packets = 0ull;
ullong received_packets_wrong = 0ull;
ullong received_bytes_per_sec = 0ull;
ullong received_bytes = 0ull;
ullong received_bytes_wrong = 0ull;
ullong sended_packets_per_sec = 0ull;
ullong sended_packets = 0ull;
ullong sended_bytes_per_sec = 0ull;
ullong sended_bytes = 0ull;
PIString receive_speed;
PIString send_speed;
PIDiagnostics::Quality quality = PIDiagnostics::Unknown;
};
//! Returns current state
PIDiagnostics::State state() const;
//! Returns period of full disconnect in seconds and period of averaging frequency
PISystemTime disconnectTimeout() const { return disconn_; }
//! Returns period of full disconnect in seconds and period of averaging frequency
void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") {
setDisconnectTimeout(PISystemTime::fromSeconds(s));
}
//! Returns period of full disconnect and period of averaging frequency
void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); }
//! Returns connection quality
PIDiagnostics::Quality quality() const;
//! Returns receive speed in format "n {B|kB|MB|GB|TB}/s"
PIString receiveSpeed() const;
//! Returns send speed in format "n {B|kB|MB|GB|TB}/s"
PIString sendSpeed() const;
EVENT_HANDLER0(void, start);
EVENT_HANDLER1(void, start, double, msecs);
EVENT_HANDLER0(void, reset);
EVENT_HANDLER1(void, received, int, size) { received(size, true); }
EVENT_HANDLER2(void, received, int, size, bool, correct);
EVENT_HANDLER1(void, sended, int, size);
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \handlers
//! \{
//! \fn void start(double msecs = 1000.)
//! \brief Start diagnostics evaluations with period "msecs" milliseconds
//! \fn void reset()
//! \brief Reset diagnostics counters
//! \fn void received(int size, bool correct = true)
//! \brief Notify diagnostics about "correct" corected received packet
//! \fn void sended(int size)
//! \brief Notify diagnostics about sended packet
//! \}
//! \events
//! \{
//! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \brief Raise on change receive quality from "old_quality" to "new_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<Entry> & hist, int & cnt);
void propertyChanged(const char *) override;
void changeDisconnectTimeout(PISystemTime disct);
PIQueue<Entry> 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