/* 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/iomanip.h"
#include "xstd/Clock.h"
#include "runtime/Agent.h"
#include "runtime/Connection.h"
#include "runtime/Xaction.h"
#include "runtime/IcpXaction.h"
#include "runtime/PageInfo.h"
#include "base/StatIntvlRec.h"
#include "runtime/StatIntvl.h"
#include "runtime/globals.h"
#include "xstd/gadgets.h"
#include "runtime/polyBcastChannels.h"
#include "base/polyLogCats.h"
int StatIntvl::TheReportCat = lgcAll;
Array<bool> StatIntvl::IsActiveCat(lgcEnd);
void StatIntvl::ActiveCat(int cat) {
Assert(0 <= cat && cat < lgcEnd);
IsActiveCat.put(true, cat);
}
StatIntvl::StatIntvl() {
Assert(TheConnOpenChannel);
theChannels <<
TheAgentBegChannel << TheAgentEndChannel <<
TheConnOpenChannel << TheConnEstChannel << TheConnCloseChannel <<
TheConnSslActiveChannel <<
TheXactBegChannel << TheXactEndChannel <<
TheXactErrChannel << TheXactRetrChannel <<
TheIcpXactBegChannel << TheIcpXactEndChannel << TheIcpXactErrChannel <<
ThePageEndChannel <<
TheWaitBegChannel << TheWaitEndChannel
;
}
void StatIntvl::setDuration(Time start) {
const Time dur = TheClock.time() >= start ? TheClock - start : Time(0,0);
for (int i = 0; i < IsActiveCat.count(); ++i) {
if (IsActiveCat[i])
getRec(i).theDuration = dur;
}
}
void StatIntvl::storeAll(OLog &ol, int tag) const {
for (int i = 0; i < IsActiveCat.count(); ++i) {
if (IsActiveCat[i]) {
ol << bege(tag, i);
getRec(i).store(ol);
ol << ende;
}
}
}
void StatIntvl::noteAgentEvent(BcastChannel *ch, const Agent *a) {
Assert(a);
StatIntvlRec &rec = getRec(a->logCat());
if (ch == TheAgentBegChannel) {
++rec.thePopulusLvl;
} else
if (ch == TheAgentEndChannel) {
--rec.thePopulusLvl;
} else {
Assert(false);
}
checkpoint();
}
void StatIntvl::noteConnEvent(BcastChannel *ch, const Connection *conn) {
Assert(conn);
StatIntvlRec &rec = getRec(conn->logCat());
if (ch == TheConnOpenChannel) {
++rec.theOpenLvl;
// only server-side SSL connections counted here
if (conn->sslActive())
++rec.theSslStat.connLevel();
} else
if (ch == TheConnSslActiveChannel) {
Should(conn->sslActive());
++rec.theSslStat.connLevel();
} else
if (ch == TheConnEstChannel) {
++rec.theEstbLvl;
} else {
Assert(ch == TheConnCloseChannel);
if (!conn->bad()) {
rec.theConnLifeTm.record((TheClock - conn->openTime()).msec());
rec.theConnUseCnt.record(conn->useCnt());
// record greater-than-1 depths only to get pipelining probability later
const int depth = conn->useLevelMax();
if (depth > 1)
rec.theConnPipelineDepth.record(depth);
}
if (conn->ioCnt())
--rec.theEstbLvl;
--rec.theOpenLvl;
if (conn->sslActive())
--rec.theSslStat.connLevel();
}
checkpoint();
}
void StatIntvl::noteXactEvent(BcastChannel *ch, const Xaction *x) {
Assert(x);
StatIntvlRec &rec = getRec(x->logCat());
if (ch == TheXactBegChannel) {
++rec.theXactLvl;
if (x->sslConfigured())
++rec.theSslStat.xactLevel();
} else
if (ch == TheXactEndChannel) {
const ObjId &oid = x->oid();
const Time repTime = x->lifeTime();
const Size repSize = x->repSize().actual();
// stats must be recorded in only one category for totals to work!
if (oid.basic()) {
// XXX: calculate and use "ideal" time here
rec.theIdealHR.record(Time(0,0), repSize, oid.offeredHit());
rec.theRealHR.record(repTime, repSize, oid.hit());
rec.theChbR.record(repTime, repSize, oid.cachable());
if (oid.fill())
rec.theFill.record(repTime, repSize);
} else
if (oid.repToRedir())
rec.theRepToRedir.record(repTime, repSize);
else
if (oid.rediredReq())
rec.theRediredReq.record(repTime, repSize);
else
if (oid.imsAny()) // should we count 304s separately?
rec.theIms.record(repTime, repSize);
else
if (oid.reload())
rec.theReload.record(repTime, repSize);
else
if (oid.head())
rec.theHead.record(repTime, repSize);
else
if (oid.post())
rec.thePost.record(repTime, repSize);
else
if (oid.put())
rec.thePut.record(repTime, repSize);
else
if (oid.aborted())
rec.theAbort.record(repTime, repSize);
else {
Should(false); // all categories should be accounted for
}
rec.theXactCnt++;
--rec.theXactLvl;
if (x->sslConfigured()) {
--rec.theSslStat.xactLevel();
// comparison with pure HTTP misses will not be accurate
// comparison with pure HTTP hits and not-hits will be accurate
rec.theSslStat.doneXacts().record(repTime, repSize,
oid.basic() && oid.hit());
}
} else
if (ch == TheWaitBegChannel) {
++rec.theWaitLvl;
} else
if (ch == TheWaitEndChannel) {
--rec.theWaitLvl;
} else
if (ch == TheXactErrChannel) {
rec.theXactErrCnt++;
if (x && x->started()) {
--rec.theXactLvl;
if (x->sslConfigured()) {
--rec.theSslStat.xactLevel();
rec.theSslStat.recordXactError();
}
}
} else
if (ch == TheXactRetrChannel) {
rec.theXactRetrCnt++;
if (x && x->started()) {
--rec.theXactLvl;
if (x->sslConfigured())
--rec.theSslStat.xactLevel();
}
} else {
Assert(false);
}
checkpoint();
}
void StatIntvl::noteIcpXactEvent(BcastChannel *ch, const IcpXaction *x) {
Assert(x);
StatIntvlRec &rec = getRec(x->logCat());
if (ch == TheIcpXactEndChannel) {
if (x->timedout())
rec.theIcpStat.recordTimeout();
else
rec.theIcpStat.record(x->lifeTime(), x->repSize(), x->hit());
}
checkpoint();
}
void StatIntvl::notePageEvent(BcastChannel *ch, const PageInfo *p) {
Assert(p);
StatIntvlRec &rec = getRec(lgcCltSide);
if (ch == ThePageEndChannel)
rec.thePage.record(p->lifeTime, p->size);
checkpoint();
}
bool StatIntvl::checkpoint() {
return false;
}
syntax highlighted by Code2HTML, v. 0.9.1