Stats.h
Go to the documentation of this file.
00001 /*------------------------------------------------------------------------
00002  *---------------------           WMPSNIFFER          --------------------
00003  *------------------------------------------------------------------------
00004  *                                                         V7.0B  11/05/10
00005  *
00006  *
00007  *  File: Stats.h
00008  *  Authors: Danilo Tardioli
00009  *  ----------------------------------------------------------------------
00010  *  Copyright (C) 2000-2012, Universidad de Zaragoza, SPAIN
00011  *
00012  *  Contact Addresses: Danilo Tardioli                   dantard@unizar.es
00013  *
00014  *  RT-WMP is free software; you can  redistribute it and/or  modify it
00015  *  under the terms of the GNU General Public License  as published by the
00016  *  Free Software Foundation;  either  version 2, or (at  your option) any
00017  *  later version.
00018  *
00019  *  RT-WMP  is distributed  in the  hope  that  it will be   useful, but
00020  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
00021  *  MERCHANTABILITY  or  FITNESS FOR A  PARTICULAR PURPOSE.    See the GNU
00022  *  General Public License for more details.
00023  *
00024  *  You should have received  a  copy of  the  GNU General Public  License
00025  *  distributed with RT-WMP;  see file COPYING.   If not,  write to the
00026  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
00027  *  02111-1307, USA.
00028  *
00029  *  As a  special exception, if you  link this  unit  with other  files to
00030  *  produce an   executable,   this unit  does  not  by  itself cause  the
00031  *  resulting executable to be covered by the  GNU General Public License.
00032  *  This exception does  not however invalidate  any other reasons why the
00033  *  executable file might be covered by the GNU Public License.
00034  *
00035  *----------------------------------------------------------------------*/
00036 
00037 
00038 #ifndef STATS_H1_
00039 #define STATS_H1_
00040 #include <stdlib.h>
00041 #include <string>
00042 #include <sstream>
00043 #include <queue>
00044 #include <limits>
00045 #include "wmp_config.h"
00046 
00047 #include "core/include/frames.h"
00048 #include "core/interface/Msg.h"
00049 #include <string.h>
00050 #include "misc.h"
00051 
00052 template<class T>
00053 std::string toString(T val, int precision = -1) {
00054         std::ostringstream oss;
00055         oss << std::fixed;
00056         if (precision != -1) {
00057                 oss.precision(precision);
00058         }
00059         oss << val;
00060         return oss.str();
00061 }
00062 ;
00063 
00064 template<class T>
00065 class CStats {
00066 
00067 protected:
00068         int id;
00069         bool id_valid;
00070         std::string name, unit;
00071         T val, sum;
00072         bool valid;
00073 public:
00074         T bookmark, aux1, aux2, partial, total;
00075         long long llaux;
00076         struct stat_t {
00077                 T value;
00078                 int pos;
00079         };
00080 
00081         virtual void init(){
00082                 valid=id_valid=false;
00083                 sum=id=val=aux1=aux2=bookmark=llaux=partial=total=0;
00084         }
00085 
00086         CStats() {
00087                 init();
00088                 this->name="xxx";
00089                 this->unit="yyy";
00090         }
00091         CStats(std::string & name) {
00092                 this->name = name;
00093                 init();
00094         }
00095 
00096         std::string & getName() {
00097                 return name;
00098         }
00099 
00100         void set(T val) {
00101                 this->val = val;
00102         }
00103 
00104         T get() {
00105                 return this->val;
00106         }
00107         bool isValid() {
00108                 return valid;
00109         }
00110 
00111         virtual bool new_value(){
00112                 partial++;
00113                 return true;
00114         }
00115 
00116         virtual bool new_touch(){
00117                 total++;
00118                 return true;
00119         }
00120 
00121         double getPercentage(){
00122                 if (total!=0){
00123                         return (100.0*(double) partial / (double) total);
00124                 }else{
00125                         return 0;
00126                 }
00127         }
00128 
00129         std::string & getUnit() {
00130                 return unit;
00131         }
00132 };
00133 
00134 template<class T>
00135 class PlainCStats: public CStats<T> {
00136 typedef typename CStats<T>::stat_t stat_t;
00137 public:
00138         virtual void init(){
00139                 CStats<T>::init();
00140         }
00141         PlainCStats() : CStats<T>() {
00142                 init();
00143         }
00144         PlainCStats(std::string name,std::string unit):CStats<T>(name) {
00145                 this->unit = unit;
00146                 init();
00147         }
00148 
00149         void new_value(T value) {
00150                 CStats<T>::new_value();
00151                 this->valid = true;
00152                 this->sum+=value;
00153         }
00154         T getSum() {
00155                 return this->sum;
00156         }
00157 
00158 };
00159 
00160 template<class T>
00161 class MaxMinCStats: public CStats<T> {
00162 typedef typename CStats<T>::stat_t stat_t;
00163 protected:
00164         double mean;
00165         stat_t max, min;
00166         int idx;
00167         std::vector<T> v;
00168         std::vector<T> vpos;
00169 public :
00170         virtual void init() {
00171                         CStats<T>::init();
00172                         max.value = std::numeric_limits<T>::min();
00173                         min.value = std::numeric_limits<T>::max();
00174                         max.pos = -1;
00175                         min.pos = -1;
00176                         idx = 0;
00177                         mean = 0;
00178                         v.clear();
00179                         vpos.clear();
00180         }
00181 
00182         void reset(){
00183                 max.value = std::numeric_limits<T>::min();
00184                 min.value = std::numeric_limits<T>::max();
00185                 max.pos = -1;
00186                 min.pos = -1;
00187                 idx = 0;
00188                 mean = 0;
00189         }
00190 
00191         MaxMinCStats():CStats<T>() {
00192                 init();
00193         }
00194         MaxMinCStats(std::string name, std::string unit):CStats<T>(name) {
00195                 this->unit = unit;
00196                 init();
00197         }
00198         void new_value(T value, int pos) {
00199                 v.push_back(value);
00200                 vpos.push_back(pos);
00201                 this->valid = true;
00202                 if (value > max.value) {
00203                         max.value=value;
00204                         max.pos = pos;
00205                 }
00206                 if (value < min.value) {
00207                         min.value = value;
00208                         min.pos = pos;
00209                 }
00210                 idx++;
00211                 this->sum += value;
00212         }
00213         int getCount() {
00214                 return idx;
00215         }
00216 
00217         T get(int i){
00218                 return v.at(i);
00219         }
00220         T getPos(int i){
00221                 return vpos.at(i);
00222         }
00223         stat_t getMax() {
00224                 return max;
00225         }
00226         T getMaxVal(){
00227                 return max.value;
00228         }
00229 
00230         T getMinVal(){
00231                 return min.value;
00232         }
00233 
00234         T getInterval() {
00235                 return (max.value - min.value);
00236         }
00237         stat_t getMin() {
00238                 return min;
00239         }
00240         virtual double getMean() {
00241                 if (idx!=0){
00242                         return (double) this->sum / (double) idx;
00243                 } else{
00244                         return 0;
00245                 }
00246         }
00247 };
00248 
00249 template<class T>
00250 class IntervalCStats: public MaxMinCStats<T> {
00251 typedef typename CStats<T>::stat_t stat_t;
00252         stat_t best_max;
00253         stat_t best_min;
00254         int best_count;
00255 public:
00256         virtual void init(){
00257                 MaxMinCStats<T>::init();
00258                 best_count=0;
00259         }
00260 
00261         IntervalCStats():MaxMinCStats<T>() {
00262                 init();
00263         }
00264         IntervalCStats(std::string name, std::string unit):MaxMinCStats<T>(name, unit) {
00265                 init();
00266         }
00267         void reset() {
00268                 done();
00269                 MaxMinCStats<T>::reset();
00270         }
00271         void done(){
00272                 if (this->idx > best_count) {
00273                         best_max = this->max;
00274                         best_min = this->min;
00275                         best_count = this->idx;
00276                 }
00277         }
00278 
00279         stat_t getIntervalMax() {
00280                 return best_max;
00281         }
00282         stat_t getIntervalMin() {
00283                 return best_min;
00284         }
00285         int getIntervalCount() {
00286                 return best_count;
00287         }
00288 };
00289 
00290 template<class T, class P>
00291 class ThingOverTimeCStats: public MaxMinCStats<T> {
00292 typedef typename CStats<T>::stat_t stat_t;
00293         P things;
00294 public:
00295         virtual void init(){
00296                 MaxMinCStats<T>::init();
00297                 things = 0;
00298         }
00299         ThingOverTimeCStats():MaxMinCStats<T>() {
00300                 this->init();
00301         }
00302         ThingOverTimeCStats(std::string name, std::string unit):MaxMinCStats<T>(name, unit) {
00303                 this->init();
00304         }
00305         void new_thing(T size) {
00306                 this->things+=size;
00307         }
00308         void new_time(T time) {
00309                 this->new_value(time,0);
00310         }
00311         double getToT() {
00312                 if ((this->max.value - this->min.value) != 0){
00313                         return (double)(((double) things) / ((double) (this->max.value - this->min.value)));
00314                 } else{
00315                         return 0;
00316                 }
00317         }
00318         virtual double getMean() {
00319                 return getToT();
00320         }
00321 };
00322 
00323 #include <vector>
00324 
00325 template<class T>
00326 class ListCStats: public CStats<T> {
00327 typedef typename CStats<T>::stat_t stat_t;
00328 protected:
00329         std::vector<stat_t> v;
00330         std::string child_name;
00331 public:
00332         virtual void init(){
00333                 CStats<T>::init();
00334                 v.clear();
00335         }
00336         ListCStats(std::string name, std::string child_name) : CStats<T>(name) {
00337                 this->child_name = child_name;
00338                 init();
00339         }
00340         ListCStats() : CStats<T>() {
00341                 init();
00342         }
00343         void new_value(T value, int pos) {
00344                 CStats<T>::new_value();
00345                 this->valid = true;
00346                 stat_t elem;
00347                 elem.value=value;
00348                 elem.pos=pos;
00349                 v.push_back(elem);
00350         }
00351 
00352         virtual int getCount() {
00353                 return v.size();
00354         }
00355 
00356         virtual stat_t getElem(int idx) {
00357                 stat_t elem = v.at(idx);
00358                 return elem;
00359         }
00360 
00361         std::string & getChildName() {
00362                 return child_name;
00363         }
00364 
00365 };
00366 template<class T>
00367 class DoubleListCStats: public ListCStats<T> {
00368 typedef typename CStats<T>::stat_t stat_t;
00369 
00370 public:
00371         DoubleListCStats(std::string name, std::string child_name) : ListCStats<T>(name,child_name) {
00372         }
00373         DoubleListCStats() : ListCStats<T>() {
00374         }
00375 
00376         void new_value(T value1, int pos1, T value2, int pos2) {
00377                 ListCStats<T>::new_value(value1,pos1);
00378                 ListCStats<T>::new_value(value2,pos2);
00379         }
00380         void getElem(int pos, stat_t & v1, stat_t & v2) {
00381                 v1 = ListCStats<T>::getElem(pos*2);
00382                 v2 = ListCStats<T>::getElem(pos*2+1);
00383         }
00384         virtual int getCount() {
00385                 return ListCStats<T>::getCount()/2;
00386         }
00387         stat_t getElem(int idx) {
00388                 stat_t elem = ListCStats<T>::getElem(idx*2);
00389                 return elem;
00390         }
00391 };
00392 
00393 template<class Q>
00394 class MultiCStats {
00395 protected:
00396         std::string name, child_name;
00397         std::vector<Q> v2;
00398 public:
00399         MultiCStats(std::string name, std::string child_name, int nfields) {
00400                 this->child_name = child_name;
00401                 this->name = name;
00402                 v2.resize(nfields);
00403         }
00404         Q & operator[](int id) {
00405                 return v2.at(id);
00406         }
00407 
00408         Q & get(int id) {
00409                 return v2.at(id);
00410         }
00411         std::string & getChildName() {
00412                 return child_name;
00413         }
00414         std::string & getName() {
00415                 return name;
00416         }
00417 };
00418 
00419 #include <map>
00420 
00421 class StatsFlow {
00422         struct Interval {
00423                 int begin;
00424                 int end;
00425                 int dest;
00426                 int rescheduled;
00427                 int prio;
00428                 int age;
00429                 long long timeBegin, timeEnd, timeLoopBegin;
00430                 wmpFrame p;
00431                 struct {
00432                         unsigned short first;
00433                         int firstPos;
00434                         unsigned short last;
00435                         int lastPos;
00436                 } LoopId;
00437         };
00438         std::map<unsigned int, Interval> messages;
00439         std::map<unsigned int, Interval> bc_messages;
00440         std::map<int, MaxMinCStats<long long> * > prio;
00441         std::map<int, MaxMinCStats<long long> * >::iterator prioIt;
00442         MaxMinCStats<long long> mdd;
00443         MaxMinCStats<long long> papMdd;
00444         MaxMinCStats<long long> interAuth;
00445         MaxMinCStats<long long> ctt;
00446         MaxMinCStats<long long> cta;
00447         MaxMinCStats<long long> ctm;
00448 
00449 
00450         ListCStats<long long> interAuthList;
00451         ListCStats<long long> nrd;
00452         ThingOverTimeCStats<long long, long long> bw;
00453         PlainCStats<int> nmsg;
00454         DoubleListCStats<int> preempted;
00455         ListCStats<int> rescheduled;
00456         ListCStats<int> orphan;
00457         DoubleListCStats<int> o3;
00458         ThingOverTimeCStats<long long, long long> avail;
00459 
00460 
00461 
00462 
00463         bool initied, isqos, global_flow, pernode;
00464         int id, from, to, src, dst , begin_id, loop_id, flow_id;
00465 
00466         struct {
00467                 int Pos, NTPos, MKey, msg_id_pos;
00468                 long long NTTime, Time;
00469                 unsigned int msg_id;
00470                 wmpFrame Frame;
00471         } prev;
00472 
00473 public:
00474         virtual void init(){
00475                 messages.clear();
00476                 mdd.init();
00477 
00478                 ctt.init();
00479                 cta.init();
00480                 ctm.init();
00481 
00482                 interAuth.init();
00483                 interAuthList.init();
00484                 nrd.init();
00485                 bw.init();
00486                 nmsg.init();
00487                 preempted.init();
00488                 rescheduled.init();
00489                 papMdd.init();
00490                 avail.init();
00491                 initied=false;
00492                 begin_id=0;
00493                 loop_id=0;
00494                 memset(&prev,0,sizeof(prev));
00495 
00496                 prev.NTTime = 0;
00497                 prev.NTPos = 0;
00498         }
00499 
00500         StatsFlow(int flow_id, int from, int to, bool qos, long long time_begin = 0) :
00501                         mdd("Message Delivery Delay", "us"), papMdd("Message Delivery Delay + PAP", "us"), nrd(
00502                                         "Message Not Reaching Destination", "us"), bw("Bandwidth",
00503                                         "Kbps"), nmsg("Messages", ""), preempted("Preempted","Msg Univocal Id"), rescheduled("Rescheduled","Id"),orphan("Orphan","Id"),
00504                                         o3("Out Of Order","Id"), avail("Available time per second","ms"), ctt("Tokens","us"), cta("Auths","us"), ctm("Messages","us"){
00505                 this->src=from;
00506                 this->dst=to;
00507                 this->global_flow = (dst == -1);
00508                 this->pernode = (dst == -2);
00509                 this->isqos=qos;
00510                 this->flow_id = flow_id;
00511                 init();
00512                 bw.new_time(0);
00513         }
00514         int get_src(){
00515                 return src;
00516         }
00517 
00518         int get_count(){
00519                 return messages.size();
00520         }
00521 
00522         int get_dst(){
00523                 return dst;
00524         }
00525         bool is_qos(){
00526                 return isqos;
00527         }
00528         void new_frame(wmpFrame * p, long long time, int pos){
00529 
00530                 if (!initied){
00531                         begin_id = pos;
00532                         prev.Pos = pos;
00533                         prev.Time = time;
00534                         initied = true;
00535                 }
00536 
00537                 bw.new_time(time);
00538                 avail.new_time(time);
00539                 if (p->hdr.type == TOKEN){
00540                         if (p->tkn.beginner == p->hdr.from){
00541                                 prev.NTTime = prev.Time;
00542                                 prev.NTPos = prev.Pos;
00543                                 loop_id = p->hdr.loop_id;
00544                         }
00545                 }
00546 
00547                 if (p->hdr.type == MESSAGE && mBitsIsSet(p->msg.type, 4)){
00548                         new_message(p, time, pos);
00549                 }
00550 
00551                 prev.Pos = pos;
00552                 prev.Time = time;
00553                 prev.Frame = *p;
00554         }
00555 
00556         int begin(){
00557                 return this->begin_id;
00558         }
00559 
00560         void new_message(wmpFrame * p, long long time, int pos) {
00561                 int flow_id = p->hdr.to * 100 + p->msg.src + 1;
00562 
00563                 bool is_first_msg_jump = false;
00564                 bool is_reaching_me = false;
00565 
00566                 if (global_flow){
00567                         is_first_msg_jump = (p->msg.src == p->hdr.from);
00568                         is_reaching_me = (p->msg.dest & 1 << p->hdr.to);
00569                         bool im_interested = is_reaching_me || is_first_msg_jump;
00570                         if (!im_interested){
00571                                 return;
00572                         }
00573                 }else if (pernode){
00574                         bool im_interested = this->src == p->msg.src ;
00575                         if (!im_interested){
00576                                 return;
00577                         }
00578                         is_first_msg_jump = (p->msg.src == p->hdr.from);
00579                         is_reaching_me = (p->msg.dest & 1 << p->hdr.to);
00580                 }else{
00581                         /* source es el source de mi flujo, yo estoy dentro de los destinos */
00582                         bool im_interested = this->src == p->msg.src && (p->msg.dest & (1<<dst));
00583                         if (!im_interested){
00584                                 return;
00585                         }
00586                         is_first_msg_jump = (p->msg.src == p->hdr.from);
00587                         is_reaching_me = (p->hdr.to == dst);
00588                 }
00589 
00590                 unsigned int mkey = p->msg.msg_hash*100000 + 1000*abs(p->msg.part_id) + 100*p->msg.port;
00591 
00592                 if (messages.find(mkey) == messages.end()){
00593                         messages[mkey].begin = 0;
00594                         messages[mkey].end = 0;
00595                         messages[mkey].prio = p->msg.priority;
00596                         messages[mkey].age = p->msg.age;
00597                         nmsg.new_value(1);
00598                 }
00599 
00600                 if (is_first_msg_jump) {
00601 
00602                         messages[mkey].begin = pos;
00603                         messages[mkey].timeBegin = prev.Time;
00604                         messages[mkey].dest = p->msg.dest;
00605 
00606                         messages[mkey].rescheduled = mBitsIsSet(p->msg.type,2);
00607 
00608                         messages[mkey].LoopId.first = p->hdr.loop_id;
00609                         messages[mkey].LoopId.firstPos = pos;
00610 
00611                         if (p->hdr.loop_id == loop_id){
00612                                 messages[mkey].timeLoopBegin = prev.NTTime;
00613                         }else{
00614                                 messages[mkey].timeLoopBegin = 0;
00615                         }
00616                 }
00617 
00618                 if (is_reaching_me) {
00619 
00620                         messages[mkey].end = pos;
00621                         messages[mkey].timeEnd = time;
00622                         messages[mkey].LoopId.last = p->hdr.loop_id;
00623                         messages[mkey].LoopId.lastPos = pos;
00624 
00625                         /* Message correctly delivered */
00626                         bw.new_thing(1000 * 8 * p ->msg.len);
00627                         bw.new_time(time);
00628                         prev.msg_id = p->msg.msg_hash;
00629                         prev.msg_id_pos = pos;
00630                 }
00631                 prev.Pos = pos;
00632                 prev.Time = time;
00633                 prev.Frame = *p;
00634                 prev.MKey = mkey;
00635 
00636         }
00637 
00638         void process() {
00639                 std::map<unsigned int, Interval>::iterator it;
00640                 for (it = messages.begin(); it != messages.end(); ++it) {
00641                         Interval be = it->second;
00642 
00643                         nrd.new_touch();
00644                         rescheduled.new_touch();
00645                         orphan.new_touch();
00646                         preempted.new_touch();
00647                         o3.new_touch();
00648 
00649                         if (be.rescheduled) {
00650                                 rescheduled.new_value(be.begin, be.end);
00651                         }
00652 
00653                         if (be.begin != 0) {
00654                                 if (be.end != 0) {
00655                                         if ((be.timeEnd - be.timeBegin)>=0){
00656                                                 mdd.new_value(be.timeEnd - be.timeBegin, be.begin);
00657                                         }
00658                                         if (be.LoopId.first != be.LoopId.last){
00659                                                 preempted.new_value(it->first,be.LoopId.firstPos,it->first,be.LoopId.lastPos);
00660                                         }
00661                                         if (be.timeLoopBegin != 0) {
00662                                                 if ((be.timeEnd - be.timeLoopBegin)>0){
00663                                                         papMdd.new_value(be.timeEnd - be.timeLoopBegin, be.end);
00664                                                         if (prio.find(be.prio)==prio.end()){
00665                                                                 prio[be.prio] = new MaxMinCStats<long long>("Priority "+toString(be.prio),"us");
00666                                                         }
00667                                                         prio[be.prio]->new_value(be.timeEnd - be.timeLoopBegin, be.begin);
00668 
00669                                                         /* saves also e-to-e + age */
00670                                                         int prioWithAge = be.prio + 1000;
00671                                                         if (prio.find(prioWithAge)==prio.end()){
00672                                                                 prio[prioWithAge] = new MaxMinCStats<long long>("Priority " + toString(be.prio) + " (total)", "ms");
00673                                                         }
00674                                                         prio[prioWithAge]->new_value(be.age + (be.timeEnd/1000 - be.timeLoopBegin/1000) , be.begin);
00675 
00676                                                         /* saves also ages alone */
00677                                                         prioWithAge = be.prio + 2000;
00678                                                         if (prio.find(prioWithAge)==prio.end()){
00679                                                                 prio[prioWithAge] = new MaxMinCStats<long long>("Priority " + toString(be.prio) + " (age)", "ms");
00680                                                         }
00681                                                         prio[prioWithAge]->new_value(be.age, be.begin);
00682                                                 }
00683                                         }
00684                                 } else {
00685                                         orphan.new_value(be.begin, be.begin);
00686                                         nrd.new_value(be.begin, be.begin);
00687                                 }
00688                         }
00689                 }
00690         }
00691         MaxMinCStats<long long> & getMdd(){
00692                 return mdd;
00693         }
00694         void getBegin(){
00695                 prioIt=prio.begin();
00696         }
00697         bool hasMore(){
00698                 bool ret=(prioIt!=prio.end());
00699                 return ret;
00700         }
00701         int getId(){
00702                  return prioIt->first;
00703         }
00704         MaxMinCStats<long long> & getNextPrioLoop(){
00705                 MaxMinCStats<long long> * ret = prioIt->second;
00706                 prioIt++;
00707                 return *ret;
00708         }
00709         MaxMinCStats<long long> & getCTT(){
00710                 return ctt;
00711         }
00712 
00713         MaxMinCStats<long long> & getCTA(){
00714                 return cta;
00715         }
00716 
00717         MaxMinCStats<long long> & getCTM(){
00718                 return ctm;
00719         }
00720 
00721         MaxMinCStats<long long> & getPapMdd(){
00722                 return papMdd;
00723         }
00724 
00725         ListCStats<long long> & getNrd(){
00726                 return nrd;
00727         }
00728         ListCStats<int> & getRescheduled(){
00729                         return rescheduled;
00730         }
00731         DoubleListCStats<int> & getPreempted(){
00732                         return preempted;
00733         }
00734 
00735         DoubleListCStats<int> & getO3(){
00736                         return o3;
00737         }
00738 
00739         ListCStats<int> & getOrphan(){
00740                 return orphan;
00741         }
00742 
00743         PlainCStats<int> & getNMsg(){
00744                 return nmsg;
00745         }
00746         ThingOverTimeCStats<long long, long long> & getBw(){
00747                 return bw;
00748         };
00749         ThingOverTimeCStats<long long, long long> & getAvail(){
00750                 return avail;
00751         };
00752 
00753         void new_time(long long time) {
00754                 bw.new_time(time);
00755         }
00756         void reset() {
00757                 messages.clear();
00758         }
00759 };
00760 
00761 #endif /* STATS_H_ */


ros_rt_wmp_sniffer
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Fri Jan 3 2014 12:08:32