Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

VCacheMonitor.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Created on Sat May 31 16:47:46 PDT 1997 by heydon
00020 // Last modified on Mon May 23 22:09:59 EDT 2005 by ken@xorian.net  
00021 //      modified on Mon Jun  9 15:55:35 EDT 2003 by scott@scooter.cx
00022 //      modified on Sat Feb 12 12:02:53 PST 2000 by mann  
00023 //      modified on Sun Aug 22 16:10:44 PDT 1999 by heydon
00024 
00025 // VCacheMonitor -- a program to monitor the Vesta-2 cache server state
00026 
00027 #include <stdio.h>
00028 #include <time.h>
00029 // necessary to make up for broken header file
00030 extern "C" char* _Pctime_r(const time_t *timer, char *buffer);
00031 
00032 // basics
00033 #include <Basics.H>
00034 #include <SRPC.H>
00035 
00036 // cache-common
00037 #include <CacheArgs.H>
00038 #include <CacheState.H>
00039 
00040 // local includes
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) { // assures won't round up to 10.0
00093         sprintf(buff, "%3.1f", ratio);
00094       } else {
00095         val = (val + (OneK / 2)) / OneK; // round
00096         sprintf(buff, "%3d", val);
00097       }
00098       cout << buff << suffix;
00099     }
00100     cout << ' ';
00101 }
00102 
00103 /* We want to print a blank line before printing the cache Id information
00104    except for the very first time "EstablishConnection" is called. */
00105 static bool firstTime = true;
00106 
00107 static void EstablishConnection(const DebugC &cache) throw (SRPC::failure)
00108 {
00109     CacheId id;
00110     cache.GetCacheId(/*OUT*/ id);
00111     FP::Tag instance_fp;
00112     cache.GetCacheInstance(/*OUT*/ instance_fp);
00113     if (firstTime) firstTime = false;
00114     else cout << endl;
00115     id.Print(cout, /*indent=*/ 0);
00116     cout << "Instance FP:   " << instance_fp << endl;
00117     cout.flush();
00118 }
00119 
00120 static void NewCacheState(const int ts, const DebugC &cache,
00121   /*INOUT*/ CacheState* &oldState, /*INOUT*/ CacheState* &newState,
00122   CacheState* spareState, /*INOUT*/ int &rowsPrinted) throw (SRPC::failure)
00123 {
00124     // time at which to print next time stamp
00125     static time_t nextStamp = -1;
00126 
00127     // get new state
00128     cache.GetCacheState(/*OUT*/ *newState);
00129 
00130     // test if cache has been restarted since last sample
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     // see if it is time to print a timestamp
00143     if (ts >= 0) {
00144         time_t now = time((time_t *)NULL);
00145         assert(now >= 0);
00146         if (now >= nextStamp) {
00147             // don't print a timestamp the first time
00148             if (nextStamp >= 0) {
00149                 char buffer[64];
00150                 (void) ctime_r(&now, buffer);
00151                 buffer[strlen(buffer)-1] = '\0'; // suppress '\n'
00152                 cout << "------------------------ " << buffer
00153                      << " ------------------------" << endl;
00154             }
00155             nextStamp = now + ts;
00156         }
00157     }
00158 
00159     // print row values
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     {   // swap "oldState" and "newState"
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     // establish connection to cache
00193     DebugC cache(CacheIntf::None, true, update*2);
00194 
00195     // connection status
00196     enum ConnState { Disconnected, Connected };
00197     ConnState connState = Disconnected;
00198 
00199     // cache state
00200     CacheState state1, state2;
00201     CacheState *oldState = (CacheState *)NULL;
00202     CacheState *newState = &state1, *spareState = &state2;
00203 
00204     // loop until enough rows have been printed
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                 // fall through immediately!
00214               case Connected:
00215                 if (rowsPrinted == 0 || (rows > 0 && rowsPrinted % rows == 0))
00216                     PrintHeader();
00217                 NewCacheState(ts, cache, /*INOUT*/ oldState, 
00218                   /*INOUT*/ newState, spareState, /*INOUT*/ 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         // pause for "update" seconds
00233         if(check) exit(0);
00234         Basics::thread::pause(update);
00235     }
00236 }
00237 
00238 /* Return the number of seconds denoted by "tm". Except for an optional
00239    suffix character, "tm" must be a non-negative integer value. If
00240    present, the suffix character specifies a time unit as follows:
00241 
00242      s  seconds (default)
00243      m  minutes
00244      h  hours
00245      d  days
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         // fall through
00261       case 'h':
00262         multiplier *= 60;
00263         // fall through
00264       case 'm':
00265         multiplier *= 60;
00266         // fall through
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; // default: update every 10 seconds
00288     int ts = -1;     // default: do not print any timestamps
00289     int num = -1;    // default: update indefinitely
00290     int rows = -1;   // default: only write header lines once
00291     int arg = 1;
00292     int check = 0;
00293 
00294     // process command-line
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 }

Generated on Mon May 8 00:48:31 2006 for Vesta by  doxygen 1.4.2