/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "xstd/h/sstream.h"
#include "xstd/h/iomanip.h"
#include "base/polyLogCats.h"
#include "base/polyLogTags.h"
#include "probe/ProbeStatMgr.h"
ProbeStatMgr TheProbeStatMgr;
static const int lgProbeStats = lgEndOfSysTags+1; // assume no other objects are used
/* ProbeLinkRec */
ProbeLinkRec::ProbeLinkRec() {
}
ProbeLinkRec::ProbeLinkRec(const NetAddr &aCltHost, const NetAddr &aSrvHost):
theCltHost(aCltHost), theSrvHost(aSrvHost) {
}
void ProbeLinkRec::store(OLog &log) const {
log << theCltHost << theSrvHost;
theStats.store(log);
}
void ProbeLinkRec::load(ILog &log) {
log >> theCltHost >> theSrvHost;
theStats.load(log);
}
void ProbeLinkRec::oneLineReport(ostream &os) const {
//stats().theSockRdSzH.print(os << here, "sock_rd.size.") << endl;
//stats().theSockWrSzH.print(os << here, "sock_wr.size.") << endl;
os
<< ' ' << fmtAddress(cltHost())
<< ' ' << fmtAddress(srvHost())
<< ' ' << setw(7) << bitRate(stats().theSockRdSzH.stats())
<< ' ' << setw(7) << bitRate(stats().theSockWrSzH.stats())
<< ' ' << setw(5) << stats().theConnCnt
<< ' ' << setw(5) << stats().theErrorCnt
;
}
String ProbeLinkRec::fmtAddress(const NetAddr &addr) const {
ostringstream buf1, buf2;
buf1 << addr << ends;
buf2 << setw(21) << buf1.str() << ends;
const String s = buf2.str().c_str();
streamFreeze(buf1, false);
streamFreeze(buf2, false);
return s;
}
// Mbits/sec
double ProbeLinkRec::bitRate(const AggrStat &s) const {
const double dur = stats().duration().secd();
if (dur <= 0)
return -1;
return s.sum()/(1024*1024/8)/dur;
}
static
OLog &operator <<(OLog &log, const ProbeLinkRec *rp) {
Assert(rp);
log << ((int)0);
rp->store(log);
return log;
}
static
ILog &operator >>(ILog &log, ProbeLinkRec *&rp) {
rp = new ProbeLinkRec;
int dummy = 0;
log >> dummy;
rp->load(log);
return log;
}
/* ProbeStatMgr */
ProbeStatMgr::ProbeStatMgr() {
}
ProbeStatMgr::~ProbeStatMgr() {
while (theRecs.count()) delete theRecs.pop();
}
// can be called many times to add entries
void ProbeStatMgr::incConfigure(Array<NetAddr*> &cltHosts, Array<NetAddr*> &srvHosts) {
theRecs.stretch(theRecs.count() + cltHosts.count() * srvHosts.count());
for (int c = 0; c < cltHosts.count(); ++c) {
for (int s = 0; s < srvHosts.count(); ++s) {
if (!find(*cltHosts[c], *srvHosts[s]))
theRecs.append(new ProbeLinkRec(*cltHosts[c], *srvHosts[s]));
}
}
}
void ProbeStatMgr::exportStats(OLog &log) const {
log << bege(lgProbeStats, lgcAll) << theRecs << ende;
}
void ProbeStatMgr::importStats(ILog &log) {
Array<ProbeLinkRec*> recs;
const LogEntryPx prefix = log.begEntry();
Assert(prefix.theTag == lgProbeStats);
log >> recs;
log.endEntry();
for (int i = 0; i < recs.count(); ++i)
importStats(recs[i]);
}
void ProbeStatMgr::importStats(ProbeLinkRec *rec) {
const NetAddr &cltHost = rec->cltHost();
const NetAddr &srvHost = rec->srvHost();
if (ProbeLinkStat *s = find(cltHost, srvHost))
s->syncWith(rec->stats());
else
theRecs.append(rec);
}
ProbeLinkStat *ProbeStatMgr::stats(const NetAddr &cltHost, const NetAddr &srvHost) {
if (ProbeLinkStat *s = find(cltHost, srvHost))
return s;
//clog << here << "traffic on unexpected link: " << cltHost << "<->" << srvHost << endl;
theRecs.append(new ProbeLinkRec(cltHost, srvHost));
return &theRecs.last()->stats();
}
void ProbeStatMgr::report(ostream &os) const {
os << "#link "
<< ' ' << setw(21) << "client_address"
<< ' ' << setw(21) << "server_address"
<< ' ' << setw(7) << "inMbps"
<< ' ' << setw(7) << "outMbps"
<< ' ' << setw(5) << "conn"
<< ' ' << setw(5) << "err"
<< endl;
ProbeLinkRec sum(NetAddr("any", -1), NetAddr("any", -1));
for (int i = 0; i < theRecs.count(); ++i) {
ProbeLinkRec &rec = *theRecs[i];
sum.stats() += rec.stats();
report(os, rec, i+1);
}
os << endl;
report(os, sum);
}
void ProbeStatMgr::report(ostream &os, const ProbeLinkRec &rec, int idx) const {
if (idx > 0)
os << setw(5) << idx << ' ';
else
os << setw(5) << 0 << ' ';
rec.oneLineReport(os);
os << endl;
}
ProbeLinkStat *ProbeStatMgr::find(const NetAddr &cltHost, const NetAddr &srvHost) {
Assert(cltHost && srvHost);
for (int i = 0; i < theRecs.count(); ++i) {
if (theRecs[i]->cltHost() == cltHost && theRecs[i]->srvHost() == srvHost)
return &theRecs[i]->stats();
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1