added basic functions to collect bandwidth info in pqistreamer both ways; added a sorting method in BWGraphSource to create curves from extracted BW info. Still not yet functional

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8600 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2015-07-12 04:04:18 +00:00
parent 090148cea2
commit 9471a91795
23 changed files with 551 additions and 94 deletions

View File

@ -37,6 +37,8 @@
#include "pqi/pqinetwork.h"
class RSTrafficClue ;
/*** Base DataTypes: ****/
#include "serialiser/rsserial.h"
#include "retroshare/rstypes.h"
@ -93,6 +95,8 @@ virtual void getRates(RsBwRates &rates)
}
virtual int gatherOutQueueStatistics(std::vector<uint32_t>& /*per_service_count*/,std::vector<uint32_t>& /*per_priority_count*/) { return 0;}
virtual int gatherStatistics(std::list<RSTrafficClue>& /* outqueue_lst */,std::list<RSTrafficClue>& /* inqueue_lst */) { return 0;}
virtual int getQueueSize(bool /* in */) { return 0;}
virtual float getRate(bool in)
{

View File

@ -407,6 +407,17 @@ int pqihandler::ExtractOutQueueStatistics(OutQueueStatistics& stats)
return 1 ;
}
int pqihandler::ExtractTrafficInfo(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst)
{
in_lst.clear() ;
out_lst.clear() ;
for( std::map<RsPeerId, SearchModule *>::iterator it = mods.begin(); it != mods.end(); ++it)
(it -> second)->pqi->gatherStatistics(out_lst,in_lst) ;
return 1 ;
}
// NEW extern fn to extract rates.
int pqihandler::ExtractRates(std::map<RsPeerId, RsBwRates> &ratemap, RsBwRates &total)
{

View File

@ -79,6 +79,7 @@ class pqihandler: public P3Interface, public pqiPublisher
// TESTING INTERFACE.
int ExtractRates(std::map<RsPeerId, RsBwRates> &ratemap, RsBwRates &totals);
int ExtractOutQueueStatistics(OutQueueStatistics& stats) ;
int ExtractTrafficInfo(std::list<RSTrafficClue> &out_lst, std::list<RSTrafficClue> &in_lst);
protected:
/* check to be overloaded by those that can

View File

@ -601,6 +601,17 @@ int pqiperson::gatherOutQueueStatistics(std::vector<uint32_t>& per_service,s
return 0;
return activepqi -> gatherOutQueueStatistics(per_service,per_priority);
}
int pqiperson::gatherStatistics(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
// get the rate from the active one.
if ((!active) || (activepqi == NULL))
return 0;
return activepqi -> gatherStatistics(out_lst,in_lst);
}
int pqiperson::getQueueSize(bool in)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/

View File

@ -171,6 +171,7 @@ virtual float getRate(bool in);
virtual void setMaxRate(bool in, float val);
virtual void setRateCap(float val_in, float val_out);
virtual int gatherOutQueueStatistics(std::vector<uint32_t>& per_service,std::vector<uint32_t>& per_priority);
virtual int gatherStatistics(std::list<RSTrafficClue>& outqueue_lst,std::list<RSTrafficClue>& inqueue_lst) ;

View File

@ -56,28 +56,28 @@ void pqiQoS::in_rsItem(void *ptr,int priority)
++_nb_items ;
}
int pqiQoS::gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const
{
assert(per_priority_count.size() == 10) ;
assert(per_service_count.size() == 65536) ;
for(uint32_t i=0;i<_item_queues.size();++i)
{
per_priority_count[i] += _item_queues[i].size() ;
for(std::list<void*>::const_iterator it(_item_queues[i]._items.begin());it!=_item_queues[i]._items.end();++it)
{
uint32_t type = 0;
uint32_t offset = 0;
getRawUInt32((uint8_t*)(*it), 4, &offset, &type);
uint16_t service_id = (type >> 8) & 0xffff ;
++per_service_count[service_id] ;
}
}
return 1 ;
}
// int pqiQoS::gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const
// {
// assert(per_priority_count.size() == 10) ;
// assert(per_service_count.size() == 65536) ;
//
// for(uint32_t i=0;i<_item_queues.size();++i)
// {
// per_priority_count[i] += _item_queues[i].size() ;
//
// for(std::list<void*>::const_iterator it(_item_queues[i]._items.begin());it!=_item_queues[i]._items.end();++it)
// {
// uint32_t type = 0;
// uint32_t offset = 0;
// getRawUInt32((uint8_t*)(*it), 4, &offset, &type);
//
// uint16_t service_id = (type >> 8) & 0xffff ;
//
// ++per_service_count[service_id] ;
// }
// }
// return 1 ;
// }
void *pqiQoS::out_rsItem()

View File

@ -95,7 +95,7 @@ class pqiQoS
// get some stats about what's going on. service_packets will contain the number of
// packets per service, and queue_sizes will contain the size of the different priority queues.
int gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const ;
//int gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const ;
void computeTotalItemSize() const ;
int debug_computeTotalItemSize() const ;

View File

@ -43,10 +43,10 @@ int pqiQoSstreamer::getQueueSize(bool in)
}
}
int pqiQoSstreamer::locked_gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const // extracting data.
{
return pqiQoS::gatherStatistics(per_service_count,per_priority_count) ;
}
//int pqiQoSstreamer::locked_gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const // extracting data.
//{
// return pqiQoS::gatherStatistics(per_service_count,per_priority_count) ;
//}
void pqiQoSstreamer::locked_storeInOutputQueue(void *ptr,int priority)
{

View File

@ -41,7 +41,7 @@ class pqiQoSstreamer: public pqithreadstreamer, public pqiQoS
virtual void locked_clear_out_queue() ;
virtual int locked_compute_out_pkt_size() const { return _total_item_size ; }
virtual void *locked_pop_out_data() ;
virtual int locked_gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const; // extracting data.
//virtual int locked_gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const; // extracting data.
virtual int getQueueSize(bool in) ;

View File

@ -318,6 +318,15 @@ int pqistreamer::queue_outpqi_locked(RsItem *pqi,uint32_t& pktsize)
#ifdef DEBUG_PQISTREAMER
std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl;
#endif
/*******************************************************************************************/
// keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1
// is a full statistics chunk that can be used in the GUI
locked_addTrafficClue(pqi,pktsize,mCurrentStatsChunk_Out) ;
/*******************************************************************************************/
if (mRsSerialiser->serialise(pqi, ptr, &pktsize))
{
locked_storeInOutputQueue(ptr,pqi->priority_level()) ;
@ -345,7 +354,7 @@ int pqistreamer::queue_outpqi_locked(RsItem *pqi,uint32_t& pktsize)
return 1; // keep error internal.
}
int pqistreamer::handleincomingitem_locked(RsItem *pqi)
int pqistreamer::handleincomingitem_locked(RsItem *pqi,int len)
{
#ifdef DEBUG_PQISTREAMER
@ -358,9 +367,44 @@ int pqistreamer::handleincomingitem_locked(RsItem *pqi)
pqi -> PeerId(PeerId());
mIncoming.push_back(pqi);
++mIncomingSize ;
/*******************************************************************************************/
// keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1
// is a full statistics chunk that can be used in the GUI
locked_addTrafficClue(pqi,len,mCurrentStatsChunk_In) ;
/*******************************************************************************************/
return 1;
}
void pqistreamer::locked_addTrafficClue(const RsItem *pqi,uint32_t pktsize,std::list<RSTrafficClue>& lst)
{
time_t now = time(NULL) ;
if(now > mStatisticsTimeStamp) // new chunk => get rid of oldest, replace old list by current list, clear current list.
{
mPreviousStatsChunk_Out = mCurrentStatsChunk_Out ;
mPreviousStatsChunk_In = mCurrentStatsChunk_In ;
mCurrentStatsChunk_Out.clear() ;
mCurrentStatsChunk_In.clear() ;
mStatisticsTimeStamp = now ;
}
RSTrafficClue tc ;
tc.TS = now ;
tc.size = pktsize ;
tc.priority = pqi->priority_level() ;
tc.peer_id = pqi->PeerId() ;
tc.count = 1 ;
tc.service_id = pqi->PacketService() ;
tc.service_sub_id = pqi->PacketSubType() ;
lst.push_back(tc) ;
}
time_t pqistreamer::getLastIncomingTS()
{
RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/
@ -742,16 +786,9 @@ continue_packet:
std::cerr << "[" << (void*)pthread_self() << "] " << "deserializing. Size=" << pktlen << std::endl ;
#endif
// if(pktlen == 17306)
// {
// FILE *f = RsDirUtil::rs_fopen("dbug.packet.bin","w");
// fwrite(block,pktlen,1,f) ;
// fclose(f) ;
// exit(-1) ;
// }
RsItem *pkt = mRsSerialiser->deserialise(block, &pktlen);
if ((pkt != NULL) && (0 < handleincomingitem_locked(pkt)))
if ((pkt != NULL) && (0 < handleincomingitem_locked(pkt,pktlen)))
{
#ifdef DEBUG_PQISTREAMER
pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "Successfully Read a Packet!");
@ -988,11 +1025,19 @@ void pqistreamer::free_rpend_locked()
int pqistreamer::gatherOutQueueStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count)
{
#ifdef TO_REMOVE
RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/
return locked_gatherStatistics(per_service_count,per_priority_count);
#endif
}
int pqistreamer::gatherStatistics(std::list<RSTrafficClue>& outqueue_lst,std::list<RSTrafficClue>& inqueue_lst)
{
RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/
return locked_gatherStatistics(outqueue_lst,inqueue_lst);
}
int pqistreamer::getQueueSize(bool in)
{
RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/
@ -1046,9 +1091,9 @@ int pqistreamer::locked_compute_out_pkt_size() const
return total ;
}
int pqistreamer::locked_gatherStatistics(std::vector<uint32_t>&,std::vector<uint32_t>&) const
int pqistreamer::locked_gatherStatistics(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst)
{
std::cerr << "(II) called overloaded function locked_gatherStatistics(). This is probably an error" << std::endl;
// std::cerr << "(II) called overloaded function pqistreamer::locked_gatherStatistics(). " << std::endl;
return 1 ;
}

View File

@ -63,6 +63,7 @@ class pqistreamer: public PQInterface
virtual void getRates(RsBwRates &rates);
virtual int getQueueSize(bool in); // extracting data.
virtual int gatherOutQueueStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count); // extracting data.
virtual int gatherStatistics(std::list<RSTrafficClue>& outqueue_stats,std::list<RSTrafficClue>& inqueue_stats); // extracting data.
protected:
int tick_bio();
@ -78,7 +79,8 @@ class pqistreamer: public PQInterface
virtual void locked_clear_out_queue() ;
virtual int locked_compute_out_pkt_size() const ;
virtual void *locked_pop_out_data() ;
virtual int locked_gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const; // extracting data.
//virtual int locked_gatherStatistics(std::vector<uint32_t>& per_service_count,std::vector<uint32_t>& per_priority_count) const; // extracting data.
virtual int locked_gatherStatistics(std::list<RSTrafficClue>& outqueue_stats,std::list<RSTrafficClue>& inqueue_stats); // extracting data.
protected:
@ -90,7 +92,7 @@ class pqistreamer: public PQInterface
private:
int queue_outpqi_locked(RsItem *i,uint32_t& serialized_size);
int handleincomingitem_locked(RsItem *i);
int handleincomingitem_locked(RsItem *i, int len);
// ticked regularly (manages out queues and sending
// via above interfaces.
@ -146,7 +148,15 @@ class pqistreamer: public PQInterface
time_t mLastIncomingTs;
// traffic statistics
std::list<RSTrafficClue> mPreviousStatsChunk_In ;
std::list<RSTrafficClue> mPreviousStatsChunk_Out ;
std::list<RSTrafficClue> mCurrentStatsChunk_In ;
std::list<RSTrafficClue> mCurrentStatsChunk_Out ;
time_t mStatisticsTimeStamp ;
void locked_addTrafficClue(const RsItem *pqi, uint32_t pktsize, std::list<RSTrafficClue> &lst);
};
#endif //MRK_PQI_STREAMER_HEADER

View File

@ -171,6 +171,21 @@ class RsConfigDataRates
int mQueueOut;
};
class RSTrafficClue
{
public:
time_t TS ;
uint32_t size ;
uint8_t priority ;
uint16_t service_id ;
uint8_t service_sub_id ;
RsPeerId peer_id ;
uint32_t count ;
RSTrafficClue() { TS=0;size=0;service_id=0;service_sub_id=0; count=0; }
RSTrafficClue& operator+=(const RSTrafficClue& tc) { size += tc.size; count += tc.count ; return *this ;}
};
class OutQueueStatistics
{
public:
@ -234,8 +249,8 @@ class RsServerConfig
{
public:
RsServerConfig() { return; }
virtual ~RsServerConfig() { return; }
RsServerConfig() {}
virtual ~RsServerConfig() {}
/* From RsIface::RsConfig */
// Implemented Only this one!
@ -247,6 +262,8 @@ virtual int getConfigNetStatus(RsConfigNetStatus &status) = 0;
virtual int getTotalBandwidthRates(RsConfigDataRates &rates) = 0;
virtual int getAllBandwidthRates(std::map<RsPeerId, RsConfigDataRates> &ratemap) = 0;
virtual int getOutQueueStatistics(OutQueueStatistics& stats) = 0 ;
virtual int getTrafficInfo(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst) = 0 ;
/* From RsInit */
// NOT IMPLEMENTED YET!

View File

@ -220,7 +220,6 @@ static const uint32_t RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE = 0x0008 ;
static const uint32_t RS_GENERIC_ID_GROUTER_ID_TYPE = 0x0009 ;
typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_SSL_ID_TYPE> SSLIdType ;
//typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_GROUTER_ID_TYPE> GRouterKeyIdType ;
typedef t_RsGenericIdType< PGP_KEY_ID_SIZE , true, RS_GENERIC_ID_PGP_ID_TYPE> PGPIdType ;
typedef t_RsGenericIdType< SHA1_SIZE , false, RS_GENERIC_ID_SHA1_ID_TYPE> Sha1CheckSum ;
typedef t_RsGenericIdType< PGP_KEY_FINGERPRINT_SIZE, true, RS_GENERIC_ID_PGP_FINGERPRINT_TYPE> PGPFingerprintType ;

View File

@ -187,14 +187,16 @@ int p3ServerConfig::getConfigStartup(RsConfigStartup &/*params*/)
return 0;
}
#if 0
int p3ServerConfig::getConfigDataRates(RsConfigDataRates &/*params*/)
/***** for RsConfig -> p3BandwidthControl ****/
int p3ServerConfig::getTrafficInfo(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst)
{
if (rsBandwidthControl)
return rsBandwidthControl->ExtractTrafficInfo(out_lst,in_lst);
else
return 0 ;
}
#endif
/***** for RsConfig -> p3BandwidthControl ****/
int p3ServerConfig::getTotalBandwidthRates(RsConfigDataRates &rates)
{

View File

@ -59,6 +59,7 @@ virtual int getConfigStartup(RsConfigStartup &params);
virtual int getTotalBandwidthRates(RsConfigDataRates &rates);
virtual int getAllBandwidthRates(std::map<RsPeerId, RsConfigDataRates> &ratemap);
virtual int getOutQueueStatistics(OutQueueStatistics& stats) ;
virtual int getTrafficInfo(std::list<RSTrafficClue>& out_lst, std::list<RSTrafficClue> &in_lst) ;
/* From RsInit */

View File

@ -285,6 +285,11 @@ int p3BandwidthControl::ExtractOutQueueStatistics(OutQueueStatistics& stats)
return mPg->ExtractOutQueueStatistics(stats) ;
}
int p3BandwidthControl::ExtractTrafficInfo(std::list<RSTrafficClue>& in_stats,std::list<RSTrafficClue>& out_stats)
{
return mPg->ExtractTrafficInfo(out_stats,in_stats) ;
}

View File

@ -95,6 +95,7 @@ class p3BandwidthControl: public p3Service, public pqiServiceMonitor
virtual int ExtractOutQueueStatistics(OutQueueStatistics& stats) ;
virtual int ExtractTrafficInfo(std::list<RSTrafficClue> &in_stats, std::list<RSTrafficClue> &out_stats);
/*!
* Interface stuff.
@ -110,7 +111,6 @@ class p3BandwidthControl: public p3Service, public pqiServiceMonitor
//virtual void saveDone();
//virtual bool loadList(std::list<RsItem*>& load) ;
private:
bool checkAvailableBandwidth();

View File

@ -203,6 +203,7 @@ void RSGraphSource::update()
else
++it ;
}
void RSGraphSource::reset()
{
_points.clear() ;

View File

@ -89,7 +89,7 @@ public:
protected slots:
// Calls the internal source for a new data points; called by the timer. You might want to overload this
// if the collection system needs it. Otherwise, the default method will call getValues()
void update() ;
virtual void update() ;
void updateIfPossible() ;
protected:

View File

@ -0,0 +1,257 @@
#include "BWGraph.h"
void BWGraphSource::update()
{
// std::cerr << "Updating BW graphsource..." << std::endl;
std::list<RSTrafficClue> in_rstcl ;
std::list<RSTrafficClue> out_rstcl ;
TrafficHistoryChunk thc ;
rsConfig->getTrafficInfo(thc.out_rstcl,thc.in_rstcl);
// keep track of them, in case we need to change the sorting
thc.time_stamp = time(NULL) ;
mTrafficHistory.push_back(thc) ;
std::map<std::string,float> vals ;
convertTrafficClueToValues(thc.out_rstcl,vals) ;
qint64 ms = getTime() ;
for(std::map<std::string,float>::iterator it=vals.begin();it!=vals.end();++it)
{
std::list<std::pair<qint64,float> >& lst(_points[it->first]) ;
lst.push_back(std::make_pair(ms,it->second)) ;
for(std::list<std::pair<qint64,float> >::iterator it2=lst.begin();it2!=lst.end();)
if( ms - (*it2).first > _time_limit_msecs)
{
//std::cerr << " removing old value with time " << (*it).first/1000.0f << std::endl;
it2 = lst.erase(it2) ;
}
else
break ;
}
// remove empty lists
for(std::map<std::string,std::list<std::pair<qint64,float> > >::iterator it=_points.begin();it!=_points.end();)
if(it->second.empty())
{
std::map<std::string,std::list<std::pair<qint64,float> > >::iterator tmp(it) ;
++tmp;
_points.erase(it) ;
it=tmp ;
}
else
++it ;
// also clears history
for(std::list<TrafficHistoryChunk>::iterator it = mTrafficHistory.begin();it!=mTrafficHistory.end();++it)
if( ms - 1000*(*it).time_stamp > _time_limit_msecs)
it = mTrafficHistory.erase(it) ;
else
break ;
}
void BWGraphSource::convertTrafficClueToValues(const std::list<RSTrafficClue>& lst,std::map<std::string,float>& vals) const
{
vals.clear() ;
switch(_friend_graph_type)
{
case GRAPH_TYPE_SINGLE:
switch(_service_graph_type)
{
case GRAPH_TYPE_SINGLE: // single friend, single service => one curve per service sub_id
{
std::vector<RSTrafficClue> clue_per_sub_id(256) ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
if(it->peer_id == _current_selected_friend && it->service_id == _current_selected_service)
clue_per_sub_id[it->service_sub_id] += *it ;
for(uint32_t i=0;i<256;++i)
if(clue_per_sub_id[i].count > 0)
vals[QString::number(i,16).toStdString()] = (_current_unit == UNIT_KILOBYTES)?(clue_per_sub_id[i].size/1000.0f):(clue_per_sub_id[i].count) ;
}
break ;
case GRAPH_TYPE_ALL: // single friend, all services => one curve per service id
{
std::map<uint16_t,RSTrafficClue> clue_per_id ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
if(it->peer_id == _current_selected_friend)
clue_per_id[it->service_id] += *it ;
for(std::map<uint16_t,RSTrafficClue>::const_iterator it(clue_per_id.begin());it!=clue_per_id.end();++it)
vals[QString::number(it->first,16).toStdString()] = (_current_unit == UNIT_KILOBYTES)?(it->second.size/1000.0f):(it->second.count) ;
}
break ;
case GRAPH_TYPE_SUM: // single friend, sum services => one curve
{
RSTrafficClue total ;
std::map<uint16_t,RSTrafficClue> clue_per_id ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
if(it->peer_id == _current_selected_friend)
total += *it ;
vals[_current_selected_friend_name] = (_current_unit == UNIT_KILOBYTES)?(total.size/1000.0f):(total.count) ;
}
}
break ;
case GRAPH_TYPE_ALL:
switch(_service_graph_type)
{
case GRAPH_TYPE_SINGLE: // all friends, single service => one curve per friend for that service
{
std::map<RsPeerId,RSTrafficClue> clue_per_peer_id;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
if(it->service_id == _current_selected_service)
clue_per_peer_id[it->peer_id] += *it ;
for(std::map<RsPeerId,RSTrafficClue>::const_iterator it(clue_per_peer_id.begin());it!=clue_per_peer_id.end();++it)
vals[it->first.toStdString()] = (_current_unit == UNIT_KILOBYTES)?(it->second.size/1000.0f):(it->second.count) ;
}
break ;
case GRAPH_TYPE_ALL: std::cerr << "(WW) Impossible situation. Cannot draw graph in mode All/All. Reverting to sum." << std::endl;
case GRAPH_TYPE_SUM: // all friends, sum of services => one curve per friend
{
RSTrafficClue total ;
std::map<RsPeerId,RSTrafficClue> clue_per_peer_id ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
clue_per_peer_id[it->peer_id] += *it;
for(std::map<RsPeerId,RSTrafficClue>::const_iterator it(clue_per_peer_id.begin());it!=clue_per_peer_id.end();++it)
vals[it->first.toStdString()] = (_current_unit == UNIT_KILOBYTES)?(it->second.size/1000.0f):(it->second.count) ;
}
break ;
}
break ;
case GRAPH_TYPE_SUM:
switch(_service_graph_type)
{
case GRAPH_TYPE_SINGLE: // sum of friends, single service => one curve per service sub id summed over all friends
{
std::vector<RSTrafficClue> clue_per_sub_id(256) ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
if(it->service_id == _current_selected_service)
clue_per_sub_id[it->service_sub_id] += *it ;
for(uint32_t i=0;i<256;++i)
if(clue_per_sub_id[i].count > 0)
vals[QString::number(i,16).toStdString()] = (_current_unit == UNIT_KILOBYTES)?(clue_per_sub_id[i].size/1000.0f):(clue_per_sub_id[i].count) ;
}
break ;
case GRAPH_TYPE_ALL: // sum of friends, all services => one curve per service id summed over all friends
{
std::map<uint16_t,RSTrafficClue> clue_per_service ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
clue_per_service[it->service_id] += *it;
for(std::map<uint16_t,RSTrafficClue>::const_iterator it(clue_per_service.begin());it!=clue_per_service.end();++it)
vals[QString::number(it->first,16).toStdString()] = (_current_unit == UNIT_KILOBYTES)?(it->second.size/1000.0f):(it->second.count) ;
}
break ;
case GRAPH_TYPE_SUM: // sum of friends, sum of services => one single curve covering the total bandwidth
{
RSTrafficClue total ;
for(std::list<RSTrafficClue>::const_iterator it(lst.begin());it!=lst.end();++it)
total += *it;
vals[QString("Total").toStdString()] = (_current_unit == UNIT_KILOBYTES)?(total.size/1000.0f):(total.count) ;
}
break ;
}
break ;
}
}
void BWGraphSource::getValues(std::map<std::string,float>& values) const
{
RsConfigDataRates totalRates;
rsConfig->getTotalBandwidthRates(totalRates);
values.insert(std::make_pair(std::string("Bytes in"),1024 * (float)totalRates.mRateIn)) ;
values.insert(std::make_pair(std::string("Bytes out"),1024 * (float)totalRates.mRateOut)) ;
_total_sent += 1024 * totalRates.mRateOut * _update_period_msecs/1000.0f ;
_total_recv += 1024 * totalRates.mRateIn * _update_period_msecs/1000.0f ;
}
QString BWGraphSource::unitName() const { return tr("KB/s"); }
QString BWGraphSource::displayValue(float v) const
{
if(v < 1000)
return QString::number(v,'f',2) + " B/s" ;
else if(v < 1000*1024)
return QString::number(v/1024.0,'f',2) + " KB/s" ;
else
return QString::number(v/(1024.0*1024),'f',2) + " MB/s" ;
}
QString BWGraphSource::legend(int i,float v) const
{
if(i==0)
return RSGraphSource::legend(i,v) + " Total: " + niceNumber(_total_recv) ;
else
return RSGraphSource::legend(i,v) + " Total: " + niceNumber(_total_sent) ;
}
QString BWGraphSource::niceNumber(float v) const
{
if(v < 1000)
return QString::number(v,'f',2) + " B" ;
else if(v < 1000*1024)
return QString::number(v/1024.0,'f',2) + " KB" ;
else if(v < 1000*1024*1024)
return QString::number(v/(1024*1024.0),'f',2) + " MB" ;
else
return QString::number(v/(1024*1024.0*1024),'f',2) + " GB";
}
void BWGraphSource::setSelector(int selector_class,int selector_type,const std::string& selector_client_string)
{
}
BWGraph::BWGraph(QWidget *parent) : RSGraphWidget(parent)
{
_local_source = new BWGraphSource() ;
_local_source->setCollectionTimeLimit(30*60*1000) ; // 30 mins
_local_source->setCollectionTimePeriod(1000) ; // collect every second
_local_source->setDigits(2) ;
_local_source->start() ;
setSource(_local_source) ;
setTimeScale(1.0f) ; // 1 pixels per second of time.
resetFlags(RSGRAPH_FLAGS_LOG_SCALE_Y) ;
resetFlags(RSGRAPH_FLAGS_PAINT_STYLE_PLAIN) ;
setFlags(RSGRAPH_FLAGS_SHOW_LEGEND) ;
}
BWGraphSource *BWGraph::source()
{
return _local_source ;
}

View File

@ -6,25 +6,47 @@
class BWGraphSource: public RSGraphSource
{
public:
struct TrafficHistoryChunk
{
time_t time_stamp;
std::list<RSTrafficClue> out_rstcl ;
std::list<RSTrafficClue> in_rstcl ;
};
enum { SELECTOR_TYPE_FRIEND=0x00, SELECTOR_TYPE_SERVICE=0x01 };
enum { GRAPH_TYPE_SINGLE=0x00, GRAPH_TYPE_ALL=0x01, GRAPH_TYPE_SUM };
enum { GRAPH_TYPE_SINGLE=0x00, GRAPH_TYPE_ALL=0x01, GRAPH_TYPE_SUM=0x02 };
enum { UNIT_KILOBYTES=0x00, UNIT_COUNT=0x01 };
// re-derived from RSGraphSource
virtual void getValues(std::map<std::string,float>& values) const;
virtual QString displayValue(float v) const;
virtual QString legend(int i,float v) const;
virtual void update();
QString unitName() const ;
// own methdods to control what's used to create displayed info
void setSelector(int selector_class,int selector_type,const std::string& selector_client_string = std::string()) ;
protected:
void convertTrafficClueToValues(const std::list<RSTrafficClue> &lst, std::map<std::string, float> &vals) const;
private:
QString niceNumber(float v) const;
mutable float _total_sent ;
mutable float _total_recv ;
int _friend_graph_type ;
int _service_graph_type ;
RsPeerId _current_selected_friend ;
std::string _current_selected_friend_name ;
uint16_t _current_selected_service ;
int _current_unit ;
std::list<TrafficHistoryChunk> mTrafficHistory ;
};
class BWGraph: public RSGraphWidget

View File

@ -0,0 +1,55 @@
#include <QComboBox>
#include "BandwidthStatsWidget.h"
BandwidthStatsWidget::BandwidthStatsWidget(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this) ;
QObject::connect(ui.friend_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateFriendSelection(int))) ;
QObject::connect(ui.updn_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUpDownSelection(int))) ;
QObject::connect(ui.unit_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUnitSelection(int))) ;
QObject::connect(ui.service_CB,SIGNAL(currentIndexChanged(int)),this, SLOT(updateServiceSelection(int))) ;
}
void BandwidthStatsWidget::updateFriendSelection(int n)
{
if(n == 0)
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_FRIEND,BWGraphSource::GRAPH_TYPE_SUM) ;
else if(n == 1)
{
// 1 means all. So make sure the other combo is not set on ALL. If so, switch it to sum.
if(ui.service_CB->currentIndex() == 1)
ui.service_CB->setCurrentIndex(0) ;
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_FRIEND,BWGraphSource::GRAPH_TYPE_ALL) ;
}
else
{
int ci = ui.friend_CB->currentIndex() ;
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_FRIEND,BWGraphSource::GRAPH_TYPE_SINGLE,ui.friend_CB->itemData(ci,Qt::UserRole).toString().toStdString()) ;
}
}
void BandwidthStatsWidget::updateServiceSelection(int n)
{
if(n == 0)
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_SERVICE,BWGraphSource::GRAPH_TYPE_SUM) ;
else if(n == 1)
{
// 1 means all. So make sure the other combo is not set on ALL. If so, switch it to sum.
if(ui.friend_CB->currentIndex() == 1)
ui.friend_CB->setCurrentIndex(0) ;
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_SERVICE,BWGraphSource::GRAPH_TYPE_ALL) ;
}
else
{
int ci = ui.service_CB->currentIndex() ;
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_SERVICE,BWGraphSource::GRAPH_TYPE_SINGLE,ui.service_CB->itemData(ci,Qt::UserRole).toString().toStdString()) ;
}
}

View File

@ -0,0 +1,15 @@
#include "ui_BandwidthStatsWidget.h"
#include "BWGraph.h"
class BandwidthStatsWidget: public QWidget
{
public:
BandwidthStatsWidget(QWidget *parent) ;
protected slots:
void updateFriendSelection(int n);
void updateServiceSelection(int n);
private:
Ui::BwStatsWidget ui;
};