/* 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; }