/* 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/iostream.h" #include "xstd/h/iomanip.h" #include "xstd/Rnd.h" #include "base/ObjId.h" #include "xstd/TblDistr.h" #include "base/RndPermut.h" #include "csm/ContentCfg.h" #include "csm/ContentMgr.h" #include "runtime/LogComment.h" #include "pgl/ContentSym.h" #include "pgl/ServerSym.h" #include "csm/ContentSel.h" #include "xstd/gadgets.h" ContentSel::ContentSel(): theDirAccSel(0) { } ContentSel::~ContentSel() { delete theDirAccSel; } void ContentSel::configure(const ServerSym *cfg) { Array ccfgs; theSrvKind = cfg->kind(); // get "global" content information Array csyms; if (!cfg->contents(csyms, theContProbs) || !csyms.count()) { cerr << cfg->loc() << "no content specs for server " << cfg->kind() << endl; exit(-2); } Assert(csyms.count() == theContProbs.count()); TheContentMgr.get(csyms, theContents); // get direct access info Array dasyms; if (!cfg->directAccess(dasyms, theDaProbs) || !dasyms.count()) { cerr << cfg->loc() << "no direct_access specs for server " << cfg->kind() << endl; exit(-2); } TheContentMgr.get(dasyms, theDirectAccess); // check that all direct access cfgs are unique // and build cprobsViaDa map if (!theDaProbs.count()) computeDaProbs(dasyms); // make selector for direct access content theDirAccSel = TblDistr::FromDistrTable("da-sel", theDaProbs); Assert(theDirAccSel); ContentTypeIdx::configure(theContents); } void ContentSel::computeDaProbs(const Array &dasyms) { Assert(theDirectAccess.count()); Array cprobsViaDa; cprobsViaDa.stretch(theDirectAccess.count()); {for (int d = 0; d < theDirectAccess.count(); ++d) { ContentCfg *da = theDirectAccess[d]; int count = 0; for (int c = 0; c < theContents.count(); ++c) { if (theContents[c]->id() == da->id()) { cprobsViaDa.append(theContProbs[c]); count++; } } if (count != 1) { cerr << dasyms[d]->loc() << "direct_access spec below counted " << count << " times in the global contents specs (must be 1):" << endl << *dasyms[d] << endl; exit(-2); } }} // compute direct access probabilities using known content distribution double daProb = 0; {for (int d = 0; d < theDirectAccess.count(); ++d) daProb += cprobsViaDa[d]; } theDaProbs.stretch(theDirectAccess.count()); {for (int d = 0; d < theDirectAccess.count(); ++d) theDaProbs.append(cprobsViaDa[d]/daProb); // contribution of d } } void ContentSel::reportCfg(ostream &os) const { // calculate expected global content distribution // and average cachability of pages Array expCProbs(theContents.count()); double expCProbsSum = 0; for (int c = 0; c < theContents.count(); ++c) { const ContentCfg *cc = theContents[c]; // compute average number of oids of type c generated per da double contPerDa = 0; for (int d = 0; d < theDirectAccess.count(); ++d) { ContentCfg *da = theDirectAccess[d]; //cerr << here << "da[" << d << "]*" << theDaProbs[d] << '/' << daProb << ": " << da->compContPerCall(cc) << endl; contPerDa += da->compContPerCall(cc) * theDaProbs[d]; } // check that content type is accessible if (contPerDa <= 0) { cerr << ": warning: content `" << cc->kind() << "' is not accessible " << "(i.e., is not in direct_access closure)." << endl; } expCProbs[c] = contPerDa; expCProbsSum += contPerDa; } // finilize calculation of expCProbs // and compute average cachability of pages double chbSum = 0; double sizeSum = 0; // report planned and expected global content distributions os << "\tServer " << theSrvKind << ':' << endl; os << '\t' << setw(15) << "content" << ' ' << setw(10) << "planned%" << ' ' << setw(10) << "likely%" << ' ' << setw(10) << "error%" << ' ' << setw(10) << "mean_sz_bytes" << endl; {for (int c = 0; c < theContents.count(); ++c) { const ContentCfg *cc = theContents[c]; expCProbs[c] /= expCProbsSum; chbSum += expCProbs[c] * cc->theChbRatio; const double size = cc->repSizeMean(); sizeSum += expCProbs[c] * size; os << '\t' << setw(15) << cc->kind() << ' ' << setw(10) << 100*theContProbs[c] << ' ' << setw(10) << 100*expCProbs[c] << ' ' << setw(10) << Percent(expCProbs[c]-theContProbs[c], theContProbs[c]) << ' ' << setw(10) << size << endl; }} os << "\texpected average server-side cachability: " << 100*chbSum << '%' << endl; os << "\texpected average server-side object size: " << sizeSum << "Bytes" << endl; } ContentCfg *ContentSel::getDir(const ObjId &oid) { theDirAccSel->rndGen()->seed(GlbPermut(oid.hash(), rndContentSel)); const int tid = (int)theDirAccSel->trial(); Assert(tid >= 0 && tid < theDirectAccess.count()); return theDirectAccess[tid]; }