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

VCacheStats.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 // Last modified on Fri Apr 29 00:15:35 EDT 2005 by ken@xorian.net  
00020 //      modified on Sat Feb 12 13:10:03 PST 2000 by mann  
00021 //      modified on Sun Aug 23 12:18:35 PDT 1998 by heydon
00022 
00023 // VCacheStats -- gather and print statistics about the stable cache
00024 
00025 #include <Basics.H>
00026 #include <CacheArgs.H>
00027 #include <CacheConfig.H>
00028 #include "StatError.H"
00029 #include "StatNames.H"
00030 #include "StatCount.H"
00031 #include "StatCollection.H"
00032 #include "StatDirEntry.H"
00033 #include "StatMPKFile.H"
00034 
00035 using std::ostream;
00036 using std::cerr;
00037 using std::cout;
00038 using std::endl;
00039 
00040 void PrintSyntax(const char *msg, const char *arg = NULL) throw ()
00041 {
00042     cerr << "Error: " << msg;
00043     if (arg != NULL) cerr << ": " << arg;
00044     cerr << endl;
00045     cerr << "Syntax: VCacheStats "
00046         << "[ -histo ] [ -min ] [ -max ] [ -v | -V ] [ path ]" << endl;
00047     exit(1);
00048 }
00049 
00050 static void Banner(ostream &os) throw ()
00051 {
00052     os << endl;
00053     for (int i = 0; i < 75; i++) os << '*';
00054     os << endl << endl;
00055 }
00056 
00057 void Process(const char *path, int verbose,
00058              bool histo, bool minName, bool maxName,
00059              /*INOUT*/Stat::Collection &stats) throw ()
00060 {
00061     Text fullpath(path);
00062     if (path[0] != '/') {
00063         // make path absolute
00064         if (fullpath.Length() > 0) {
00065             fullpath = Config_SCachePath + ('/' + fullpath);
00066         } else {
00067             fullpath = Config_SCachePath;
00068         }
00069     }
00070     cout << "STATISTICS FOR:" << endl << "  " << fullpath << endl;
00071 
00072     try {
00073         // search "fullpath"
00074         DirEntry *entry = DirEntry::Open(fullpath);
00075         if (verbose > 0) cout << endl << "SEARCHING:" << endl;
00076         entry->Search(verbose, /*INOUT*/ stats);
00077 
00078         // print fanout stats
00079         cout << endl << "*** FANOUT STATISTICS ***" << endl;
00080         int i;
00081         for (i = stats.fanout.size() - 1; i >= 0; i--) {
00082             cout << endl;
00083             cout << Stat::LevelName(i) << " (level " << i << "):" << endl;
00084             StatCount *sc = stats.fanout.get(i);
00085             sc->Print(cout, /*indent=*/ 2, histo,
00086               minName, maxName, /*mean=*/ (i>0));
00087         }
00088         
00089         // print PKFile and cache entry stats
00090         cout << endl;
00091         cout << "*** MULTIPKFILE, PKFILE, AND CACHE ENTRY STATISTICS ***";
00092         cout << endl;
00093         for (i = 0; i < Stat::NumAttributes; i++) {
00094           // If we didn't gather redundant statistics, don't print
00095           // them.
00096           if(!stats.redundant &&
00097              ((i == Stat::NumRedundantNames) ||
00098               (i == Stat::PcntRedundantNames)))
00099             {
00100               continue;
00101             }
00102 
00103             cout << endl << Stat::AttrName((Stat::Attribute)i) << ":" << endl;
00104             stats.entryStats[i].Print(cout, /*indent=*/ 2,
00105                                       histo, minName, maxName);
00106         }
00107     }
00108     catch (const StatError::UnevenLevels &dirName) {
00109         Banner(cerr);
00110         cerr << "Error: the following directory "
00111              << "contains MPKFiles at different depths:" << endl;
00112         cerr << "  " << dirName << endl;
00113         Banner(cerr);
00114     }
00115     catch (const StatError::BadMPKFile &fname) {
00116         Banner(cerr);
00117         cerr << "Error: found illegal MultiPKFile:" << endl;
00118         cerr << "  " << fname << endl;
00119         Banner(cerr);
00120     }
00121     catch (const StatError::EndOfFile &fname) {
00122         Banner(cerr);
00123         cerr << "Fatal error: premature end-of-file" << endl;
00124         cerr << "  " << fname << endl;
00125         Banner(cerr);
00126     }
00127     catch (const FS::Failure &f) {
00128         Banner(cerr);
00129         cerr << "Error: " << f << endl;
00130         Banner(cerr);
00131     }
00132     catch (FS::DoesNotExist) {
00133         Banner(cerr);
00134         cerr << "Error: file '" << fullpath << "' does not exist" << endl;
00135         Banner(cerr);
00136     }
00137 }
00138 
00139 
00140 static StatCount *parseStatName(Stat::Collection &stats, const char *stat)
00141 {
00142 #define ATTRIB_CASE(name) \
00143 if(strcmp(#name, stat) == 0) return &(stats.entryStats[Stat::name])
00144   
00145   ATTRIB_CASE(MPKFileSize);
00146 
00147   ATTRIB_CASE(PKFileSize);
00148   ATTRIB_CASE(NumNames);
00149   ATTRIB_CASE(NameSize);
00150   ATTRIB_CASE(NumEntries);
00151   ATTRIB_CASE(NumCommonNames);
00152   ATTRIB_CASE(PcntCommonNames);
00153 
00154   ATTRIB_CASE(NumEntryNames);
00155   ATTRIB_CASE(NumUncommonNames);
00156   ATTRIB_CASE(PcntUncommonNames);
00157   ATTRIB_CASE(ValueSize);
00158   ATTRIB_CASE(NumDIs);
00159   ATTRIB_CASE(NumKids);
00160   ATTRIB_CASE(NameMapSize);
00161 
00162   // This one is really uninteresting for reporting or masking:
00163   // ATTRIB_CASE(NameMapNonEmpty);
00164 
00165   ATTRIB_CASE(ValPfxTblSize);
00166   ATTRIB_CASE(NumRedundantNames);
00167   ATTRIB_CASE(PcntRedundantNames);
00168 
00169 #define FANOUT_CASE(name, level) \
00170   if(strcmp(name, stat)) return stats.getFanout(level);
00171 
00172   FANOUT_CASE("PKFileFanout", 2);
00173   FANOUT_CASE("CFPFanout", 1);
00174   
00175   // If we make it down here, this is not a valid attribute name.
00176   PrintSyntax("unrecognized statistic name", stat);
00177 
00178   // (Unreachable, but needed for compilation.)
00179   return 0;
00180 }
00181 
00182 int main(int argc, char *argv[])
00183 {
00184     // process command-line
00185     int verbose = 0;
00186     bool printHisto = false, printMinName = false, printMaxName = false;
00187  
00188     // allocate StatCount structures
00189     Stat::Collection stats;
00190 
00191    int arg;
00192     for (arg = 1; arg < argc && *argv[arg] == '-'; arg++) {
00193         if (CacheArgs::StartsWith(argv[arg], "-histo")) {
00194             printHisto = true;
00195         } else if (CacheArgs::StartsWith(argv[arg], "-min", 3)) {
00196             printMinName = true;
00197         } else if (CacheArgs::StartsWith(argv[arg], "-max", 3)) {
00198             printMaxName = true;
00199         } else if (CacheArgs::StartsWith(argv[arg], "-verbose")) {
00200             verbose = max(verbose, 1);
00201         } else if (CacheArgs::StartsWith(argv[arg], "-Verbose")) {
00202           verbose = max(verbose, 2);
00203         } else if (CacheArgs::StartsWith(argv[arg], "-report")) {
00204           // Next arg: which stat to report about
00205           if(++arg >= argc)
00206             PrintSyntax("-report expects stat name");
00207           StatCount *stat = parseStatName(stats, argv[arg]);
00208           // Next arg: number of functions to report about
00209           if(++arg >= argc)
00210             PrintSyntax("-report expects count");
00211           unsigned int report_count = atoi(argv[arg]);
00212           // Set the report count for this stat
00213           stat->SetReportCount(report_count);
00214         } else if (CacheArgs::StartsWith(argv[arg], "-mask")) {
00215           // Next arg: which stat to report about
00216           if(++arg >= argc)
00217             PrintSyntax("-mask expects stat name");
00218           StatCount *stat = parseStatName(stats, argv[arg]);
00219           // Next arg: regular expression to mask out of the report
00220           // for this statistic.
00221           if(++arg >= argc)
00222             PrintSyntax("-mask expects regular expression");
00223           Basics::RegExp *mask = NEW_CONSTR(Basics::RegExp, (argv[arg]));
00224           // Add this to the report mask for this stat
00225           stat->AddReportMask(mask);
00226         } else if (CacheArgs::StartsWith(argv[arg], "-redundant")) {
00227           // Turn on the expensive redundant dependencies check.
00228           stats.redundant = true;
00229         } else {
00230             PrintSyntax("unrecognized command-line option", argv[arg]);
00231         }
00232     }
00233 
00234     // process argument
00235     const char *path = (arg == argc) ? "" : argv[arg];
00236     Process(path, verbose, printHisto, printMinName, printMaxName, stats);
00237 }

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