forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
StatsModule.cpp
1 
9 #include "StatsModule.h"
10 
11 namespace forest {
12 
13 
14 StatsModule::StatsModule(int maxStats1, int maxLnk1, int maxQ1,
15  ComtreeTable* ctt1)
16  : maxStats(maxStats1), maxLnk(maxLnk1), maxQ(maxQ1),
17  ctt(ctt1) {
18  stat = new StatItem[maxStats+1];
19  lnkCnts = new LinkCounts[maxLnk+1];
20  qCnts = new QueueCounts[maxQ+1];
21  for (int i = 1; i <= maxLnk; i++) {
22  lnkCnts[i].inByte = lnkCnts[i].outByte = 0;
23  lnkCnts[i].inPkt = lnkCnts[i].outPkt = 0;
24  lnkCnts[i].numPkt = 0;
25  }
26  for (int i = 1; i <= maxQ; i++) {
27  qCnts[i].bytLen = qCnts[i].pktLen = 0;
28  }
29  n = 0;
30  totInByte = 0; totInPkt = 0; totDiscards = 0;
31  rtrInByte = 0; rtrInPkt = 0;
32  leafInByte = 0; leafInPkt = 0;
33  totOutByte = 0; totOutPkt = 0;
34  rtrOutByte = 0; rtrOutPkt = 0; rtrDiscards = 0;
35  leafOutByte = 0; leafOutPkt = 0; leafDiscards = 0;
36 };
37 
38 StatsModule::~StatsModule() { delete [] stat; }
39 
40 // Record statistics at time now.
41 void StatsModule::record(uint64_t now) {
42  unique_lock<mutex> lck(mtx);
43  int i, val, ctx, cLnk, qid;
44 
45  val = -1;
46  if (n == 0) return;
47 
48  // check for the statsSwitch file
49  string fname = "statsSwitch";
50  ifstream sfs; sfs.open(fname.c_str());
51  string statsSwitch;
52  if (sfs.fail()) return;
53  if (!Util::readWord(sfs,statsSwitch) || statsSwitch != "on") {
54  sfs.close(); return;
55  }
56  sfs.close();
57  for (i = 1; i <= n; i++) {
58  StatItem& s = stat[i];
59  switch(s.typ) {
60  case inPkt:
61  if (s.lnk == 0) val = totInPkt;
62  else if (s.lnk == -1) val = rtrInPkt;
63  else if (s.lnk == -2) val = leafInPkt;
64  else val = lnkCnts[s.lnk].inPkt;
65  break;
66  case outPkt:
67  if (s.lnk == 0) val = totOutPkt;
68  else if (s.lnk == -1) val = rtrOutPkt;
69  else if (s.lnk == -2) val = leafOutPkt;
70  else val = lnkCnts[s.lnk].outPkt;
71  break;
72  case inByt:
73  if (s.lnk == 0) val = totInByte;
74  else if (s.lnk == -1) val = rtrInByte;
75  else if (s.lnk == -2) val = leafInByte;
76  else val = lnkCnts[s.lnk].inByte;
77  break;
78  case outByt:
79  if (s.lnk == 0) val = totOutByte;
80  else if (s.lnk == -1) val = rtrOutByte;
81  else if (s.lnk == -2) val = leafOutByte;
82  else val = lnkCnts[s.lnk].outByte;
83  break;
84  case qPkt:
85  if (s.comt == 0) {
86  val = getLinkQlen(s.lnk);
87  break;
88  }
89  ctx = ctt->getComtIndex(s.comt);
90  cLnk = ctt->getClnkNum(s.comt,s.lnk);
91  qid = ctt->getLinkQ(ctx,cLnk);
92  val = getQlen(qid);
93  break;
94  case qByt:
95  if (s.comt == 0) {
96  val = discCnt(s.lnk);
97  break;
98  }
99  ctx = ctt->getComtIndex(s.comt);
100  cLnk = ctt->getClnkNum(s.comt,s.lnk);
101  qid = ctt->getLinkQ(ctx,cLnk);
102  val = qDiscCnt(qid);
103  break;
104  case disc:
105  cLnk = ctt->getClnkNum(s.comt,s.lnk);
106  qid = ctt->getLinkQ(ctx,cLnk);
107  val = getQlen(qid);
108  break;
109  default: break;
110  }
111  fs << val << " ";
112  }
113  fs << double(now)/1000000000 << endl;
114  fs.flush();
115 }
116 
144 bool StatsModule::readStat(istream& in) {
145  // no lock here, caller must acquire lock
146  int lnk, comt;
147  cntrTyp typ; string typStr, fname;
148 
149  Util::skipBlank(in);
150  if (!Util::readWord(in,typStr)) return false;
151 
152  if (typStr == "inPkt") typ = inPkt;
153  else if (typStr == "outPkt") typ = outPkt;
154  else if (typStr == "inByt") typ = inByt;
155  else if (typStr == "outByt") typ = outByt;
156  else if (typStr == "qPkt") typ = qPkt;
157  else if (typStr == "qByt") typ = qByt;
158  else if (typStr == "disc") typ = disc;
159  else return false;
160 
161  switch (typ) {
162  case inPkt: case outPkt: case inByt: case outByt:
163  if (!Util::readInt(in,lnk)) return false;
164  break;
165  case qPkt: case qByt: case disc:
166  if (!Util::readInt(in,lnk) || !Util::readInt(in,comt))
167  return false;
168  break;
169  }
170  Util::nextLine(in);
171 
172  if (n >= maxStats) return false;
173  n++;
174 
175  StatItem& s = stat[n];
176  s.typ = typ;
177  s.lnk = lnk;
178  s.comt = comt;
179 
180  return true;
181 }
182 
183 bool StatsModule::read(istream& in) {
184 // Read statistics items from the input. The first line must contain an
185 // integer, giving the number of items to be read. The input may
186 // include blank lines and comment lines (any text starting with '#').
187 // Each entry must be on a line by itself (possibly with a trailing comment).
188  unique_lock<mutex> lck(mtx);
189  int num;
190  Util::skipBlank(in);
191  if (!Util::readInt(in,num)) return false;
192  Util::nextLine(in);
193  while (num--) {
194  if (readStat(in)) return false;
195  }
196  string fname = "stats";
197  fs.open(fname.c_str(),fstream::app);
198  if (fs.fail()) return false;
199  return true;
200 }
201 
206 string StatsModule::stat2string(int i) const {
207  // no lock here - caller must acquire lock
208  stringstream ss;
209  StatItem& si = stat[i];
210  switch(si.typ) {
211  case inPkt:
212  ss << " inPkt " << setw(2) << si.lnk << endl;
213  break;
214  case outPkt:
215  ss << "outPkt " << setw(2) << si.lnk << endl;
216  break;
217  case inByt:
218  ss << " inByt " << setw(2) << si.lnk << endl;
219  break;
220  case outByt:
221  ss << "outByt " << setw(2) << si.lnk << endl;
222  break;
223  case qPkt:
224  ss << " qPkt " << setw(2) << si.lnk
225  << " " << setw(2) << si.comt << endl;
226  break;
227  case qByt:
228  ss << " qByt " << setw(2) << si.lnk
229  << " " << setw(2) << si.comt << endl;
230  break;
231  case disc:
232  ss << " disc " << setw(2) << si.lnk
233  << " " << setw(2) << si.comt << endl;
234  break;
235  }
236  return ss.str();
237 }
238 
244  unique_lock<mutex> lck(mtx);
245  string s;
246  for (int i = 1; i <= n; i++) s += stat2string(i);
247  return s;
248 }
249 
250 } // ends namespace
251