/* PIP - Platform Independent Primitives Speed and quality in/out diagnostics Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "pidiagnostics.h" /** \class PIDiagnostics * \brief Connection quality diagnostics * \details * \section PIDiagnostics_sec0 Synopsis * This class provide abstract connection quality diagnostics and * counting. You should create instance of %PIDiagnostics and on * packet receive call function \a received(), on packet send call * function \a sended(). %PIDiagnostics calculates correct, wrong * and sended counters, packets per second, bytes per seconds, * immediate and integral receive frequencies and receive/send speeds * in human readable representation. There statistics are calculates * one time per period, by default 1 second. To calculate them you * should start %PIDiagnostics with function \a start() or pass \b true * to constructor. * */ PIDiagnostics::PIDiagnostics(bool start_): PITimer() { PITimer::reset(); reset(); if (start_) start(); } void PIDiagnostics::reset() { lock(); qual = PIDiagnostics::Unknown; speedIn = speedOut = PIString::readableSize(0) + "/s"; ifreq = immediate_freq = integral_freq = 0.f; packets[0] = packets[1] = 0; cur_pckt = rec_once = 0; wrong_count = receive_count = send_count = 0; packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; unlock(); } void PIDiagnostics::received(int size, bool correct) { lock(); packets[correct ? 1 : 0]++; rec_once = 1; if (correct) { float el = elapsed_s(); PITimer::reset(); if (el > 0.f) immediate_freq = ifreq = 1.f / el; else immediate_freq = ifreq = 0.f; receive_count++; packets_in_sec++; bytes_in_sec += size; } else { immediate_freq = ifreq = 0.f; wrong_count++; } unlock(); } void PIDiagnostics::sended(int size) { lock(); send_count++; packets_out_sec++; bytes_out_sec += size; unlock(); } void PIDiagnostics::tick(void * data, int delimiter) { lock(); PIDiagnostics::Quality diag; float fdel = 1. / (interval() / 1000.); immediate_freq = ifreq; ifreq = 0.f; speedIn = PIString::readableSize(bytes_in_sec * fdel) + "/s"; speedOut = PIString::readableSize(bytes_out_sec * fdel) + "/s"; bytes_in_sec = bytes_out_sec = packets_in_sec = packets_out_sec = 0; int arc = packets[0] + packets[1]; float good_percents = 0.f; if (arc > 0) good_percents = (float)packets[1] / arc * 100.f; integral_freq = packets[1] * fdel; if (rec_once == 0) { diag = PIDiagnostics::Unknown; } else { if (good_percents == 0.f) diag = PIDiagnostics::Failure; else if (good_percents <= 20.f) diag = PIDiagnostics::Bad; else if (good_percents > 20.f && good_percents <= 80.f) diag = PIDiagnostics::Average; else diag = PIDiagnostics::Good; if (diag != qual) { qualityChanged(diag, qual); qual = diag; } } packets[0] = packets[1] = 0; unlock(); }