00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <time.h>
00029
00030 extern "C" char* _Pctime_r(const time_t *timer, char *buffer);
00031
00032
00033 #include <Basics.H>
00034 #include <SRPC.H>
00035
00036
00037 #include <CacheArgs.H>
00038 #include <CacheState.H>
00039
00040
00041 #include "DebugC.H"
00042
00043 using std::cout;
00044 using std::cerr;
00045 using std::endl;
00046
00047 static void Error(char *msg, char *arg = (char *)NULL) throw ()
00048 {
00049 cerr << "Error: " << msg;
00050 if (arg != (char *)NULL) cerr << ": `" << arg << "'";
00051 cerr << endl;
00052 cerr << "SYNTAX: VCacheMonitor [ -update time ] "
00053 << "[ -ts time ] [ -n num ] [ -rows num ]" << endl;
00054 exit(1);
00055 }
00056
00057 static void PrintHeader() throw ()
00058 {
00059 const int numCols = 15;
00060 cout << endl;
00061 cout << " FREE LOOK ADD NUM NUM NUM ";
00062 cout << " NEW OLD NUM NUM MPK" << endl;
00063 cout << "SIZE RES VARS UP ENT VMPK VPKS ENTS ";
00064 cout << "ENTS PKLS ENTS PKLS HF DEL WEED" << endl;
00065 for (int i = 0; i < numCols; i++) cout << "---- ";
00066 cout << endl;
00067 }
00068
00069 static void PrintVal(unsigned int val) throw ()
00070 {
00071 const unsigned int OneK = 1024;
00072 const unsigned int OneM = OneK * OneK;
00073 const unsigned int OneG = OneM * OneK;
00074 char buff[10];
00075 if (val < OneK) {
00076 sprintf(buff, "%4d", val);
00077 cout << buff;
00078 } else {
00079 char suffix = 'K';
00080 if (val >= OneG)
00081 {
00082 val /= OneM;
00083 suffix = 'G';
00084 }
00085 else if (val >= OneM)
00086 {
00087 val /= OneK;
00088 suffix = 'M';
00089 }
00090
00091 float ratio = ((float)val) / ((float)OneK);
00092 if (ratio < 9.95) {
00093 sprintf(buff, "%3.1f", ratio);
00094 } else {
00095 val = (val + (OneK / 2)) / OneK;
00096 sprintf(buff, "%3d", val);
00097 }
00098 cout << buff << suffix;
00099 }
00100 cout << ' ';
00101 }
00102
00103
00104
00105 static bool firstTime = true;
00106
00107 static void EstablishConnection(const DebugC &cache) throw (SRPC::failure)
00108 {
00109 CacheId id;
00110 cache.GetCacheId( id);
00111 FP::Tag instance_fp;
00112 cache.GetCacheInstance( instance_fp);
00113 if (firstTime) firstTime = false;
00114 else cout << endl;
00115 id.Print(cout, 0);
00116 cout << "Instance FP: " << instance_fp << endl;
00117 cout.flush();
00118 }
00119
00120 static void NewCacheState(const int ts, const DebugC &cache,
00121 CacheState* &oldState, CacheState* &newState,
00122 CacheState* spareState, int &rowsPrinted) throw (SRPC::failure)
00123 {
00124
00125 static time_t nextStamp = -1;
00126
00127
00128 cache.GetCacheState( *newState);
00129
00130
00131 if (oldState != (CacheState *)NULL &&
00132 (newState->cnt.freeVarsCnt < oldState->cnt.freeVarsCnt ||
00133 newState->cnt.lookupCnt < oldState->cnt.lookupCnt ||
00134 newState->cnt.addEntryCnt < oldState->cnt.addEntryCnt)) {
00135 EstablishConnection(cache);
00136 PrintHeader();
00137 spareState = oldState;
00138 oldState = (CacheState *)NULL;
00139 rowsPrinted = 0;
00140 }
00141
00142
00143 if (ts >= 0) {
00144 time_t now = time((time_t *)NULL);
00145 assert(now >= 0);
00146 if (now >= nextStamp) {
00147
00148 if (nextStamp >= 0) {
00149 char buffer[64];
00150 (void) ctime_r(&now, buffer);
00151 buffer[strlen(buffer)-1] = '\0';
00152 cout << "------------------------ " << buffer
00153 << " ------------------------" << endl;
00154 }
00155 nextStamp = now + ts;
00156 }
00157 }
00158
00159
00160 PrintVal(newState->virtualSize);
00161 PrintVal(newState->physicalSize);
00162 if (oldState == (CacheState *)NULL) {
00163 for (int i = 0; i < 3; i++) cout << " N/A ";
00164 } else {
00165 MethodCnts &c2 = newState->cnt, &c1 = oldState->cnt;
00166 PrintVal(c2.freeVarsCnt - c1.freeVarsCnt);
00167 PrintVal(c2.lookupCnt - c1.lookupCnt);
00168 PrintVal(c2.addEntryCnt - c1.addEntryCnt);
00169 }
00170 PrintVal(newState->vmpkCnt);
00171 PrintVal(newState->vpkCnt);
00172 PrintVal(newState->entryCnt);
00173 PrintVal(newState->s.newEntryCnt);
00174 PrintVal(newState->s.newPklSize);
00175 PrintVal(newState->s.oldEntryCnt);
00176 PrintVal(newState->s.oldPklSize);
00177 PrintVal(newState->hitFilterCnt);
00178 PrintVal(newState->delEntryCnt);
00179 PrintVal(newState->mpkWeedCnt);
00180 cout << endl;
00181 rowsPrinted++;
00182
00183 {
00184 CacheState *tmp = oldState;
00185 oldState = newState;
00186 newState = (tmp == (CacheState *)NULL) ? spareState : tmp;
00187 }
00188 }
00189
00190 static void Monitor(int update, int ts, int num, int rows, int check) throw ()
00191 {
00192
00193 DebugC cache(CacheIntf::None, true, update*2);
00194
00195
00196 enum ConnState { Disconnected, Connected };
00197 ConnState connState = Disconnected;
00198
00199
00200 CacheState state1, state2;
00201 CacheState *oldState = (CacheState *)NULL;
00202 CacheState *newState = &state1, *spareState = &state2;
00203
00204
00205 int rowsPrinted = 0;
00206 while (num < 0 || rowsPrinted < num) {
00207 try {
00208 switch (connState) {
00209 case Disconnected:
00210 EstablishConnection(cache);
00211 connState = Connected;
00212 assert(rowsPrinted == 0);
00213
00214 case Connected:
00215 if (rowsPrinted == 0 || (rows > 0 && rowsPrinted % rows == 0))
00216 PrintHeader();
00217 NewCacheState(ts, cache, oldState,
00218 newState, spareState, rowsPrinted);
00219 break;
00220 }
00221 }
00222 catch (SRPC::failure) {
00223 if(check) exit(1);
00224 cout << "Error contacting cache server; retrying..." << endl;
00225 firstTime = false;
00226 connState = Disconnected;
00227 oldState = (CacheState *)NULL;
00228 spareState = (newState == &state1) ? &state2 : &state1;
00229 rowsPrinted = 0;
00230 }
00231
00232
00233 if(check) exit(0);
00234 Basics::thread::pause(update);
00235 }
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 static int ParseTime(char *flag, char *tm) throw ()
00248 {
00249 char errBuff[80];
00250 int len = strlen(tm);
00251 if (len == 0) {
00252 sprintf(errBuff, "argument to `%s' is empty", flag);
00253 Error(errBuff, tm);
00254 }
00255 char lastChar = tm[len - 1];
00256 int multiplier = 1;
00257 switch (lastChar) {
00258 case 'd':
00259 multiplier *= 24;
00260
00261 case 'h':
00262 multiplier *= 60;
00263
00264 case 'm':
00265 multiplier *= 60;
00266
00267 case 's':
00268 tm[len - 1] = '\0';
00269 break;
00270 default:
00271 if (!isdigit(lastChar)) {
00272 sprintf(errBuff, "illegal unit specifier `%c' in `%s' argument",
00273 lastChar, flag);
00274 Error(errBuff, tm);
00275 }
00276 }
00277 int res;
00278 if (sscanf(tm, "%d", &res) != 1) {
00279 sprintf(errBuff, "argument to `%s' not an integer", flag);
00280 Error(errBuff, tm);
00281 }
00282 return multiplier * res;
00283 }
00284
00285 int main(int argc, char *argv[])
00286 {
00287 int update = 10;
00288 int ts = -1;
00289 int num = -1;
00290 int rows = -1;
00291 int arg = 1;
00292 int check = 0;
00293
00294
00295 while (arg < argc && *argv[arg] == '-') {
00296 if (CacheArgs::StartsWith(argv[arg], "-update")) {
00297 if (++arg < argc) {
00298 update = ParseTime("-update", argv[arg++]);
00299 } else {
00300 Error("no argument supplied for `-update'");
00301 }
00302 } else if (CacheArgs::StartsWith(argv[arg], "-ts")) {
00303 if (++arg < argc) {
00304 ts = ParseTime("-ts", argv[arg++]);
00305 } else {
00306 Error("no argument supplied for `-ts'");
00307 }
00308 } else if (strcmp(argv[arg], "-n") == 0) {
00309 if (++arg < argc) {
00310 if (sscanf(argv[arg], "%d", &num) != 1) {
00311 Error("argument to `-n' not an integer", argv[arg]);
00312 }
00313 arg++;
00314 } else {
00315 Error("no argument supplied for `-n'");
00316 }
00317 } else if (CacheArgs::StartsWith(argv[arg], "-rows")) {
00318 if (++arg < argc) {
00319 if (sscanf(argv[arg], "%d", &rows) != 1) {
00320 Error("argument to `-rows' not an integer", argv[arg]);
00321 }
00322 arg++;
00323 } else {
00324 Error("no argument supplied for `-rows'");
00325 }
00326 } else if (CacheArgs::StartsWith(argv[arg], "-check")) {
00327 check = 1;
00328 arg++;
00329 } else {
00330 Error("unrecognized option", argv[arg]);
00331 }
00332 }
00333 if (arg < argc) Error("too many command-line arguments");
00334 Monitor(update, ts, num, rows, check);
00335 return(0);
00336 }