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

PrintCacheVal.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 Thu May 29 15:30:19 PDT 1997 by heydon
00020 
00021 // PrintCacheVal -- Write the values pickled in cache entries to stdout.
00022 
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #if defined(__digital__)
00026 #include <sys/mode.h>
00027 #endif
00028 #include <dirent.h>
00029 #include <Basics.H>
00030 #include <FS.H>
00031 #include <AtomicFile.H>
00032 #include <FP.H>
00033 #include <CacheArgs.H>
00034 #include <CacheConfig.H>
00035 #include <VestaVal.H>
00036 #include <CacheEntry.H>
00037 #include <SPKFile.H>
00038 #include <SMultiPKFileRep.H>
00039 
00040 using std::ostream;
00041 using std::ifstream;
00042 using std::cout;
00043 using std::cerr;
00044 using std::endl;
00045 
00046 void Error(char *msg, char *arg = (char *)NULL) throw ()
00047 {
00048     cout << "Error: " << msg;
00049     if (arg != (char *)NULL) cout << ": `" << arg << "'";
00050     cout << endl;
00051     cout << "SYNTAX: PrintCacheVal [ -n | -N ] [ -ci num ] [ path ]" << endl;
00052     exit(1);
00053 }
00054 
00055 bool OpenFile(const Text fname, /*OUT*/ ifstream &ifs) throw (FS::Failure)
00056 /* Open the file named "fname" for reading. If successful, set "ifs" to a
00057    stream on the file and return true. If the file does not exist, print an
00058    error message and return false. If any other error occurs, throw
00059    "FS::Failure".
00060 */
00061 {
00062     try {
00063         FS::OpenReadOnly(fname, ifs);
00064     }
00065     catch (FS::DoesNotExist) {
00066         cerr << "Error: unable to open '" << fname << "' for reading." << endl;
00067         return false;
00068     }
00069     return true;
00070 }
00071 
00072 static void SearchMPK(ostream &os, const Text &fname, int nSwitch, int ciOnly)
00073   throw (SMultiPKFileRep::BadMPKFile, FS::EndOfFile, FS::Failure)
00074 {
00075     // print the filename if "nSwitch"
00076     if (nSwitch > 0) {
00077         os << "MultiPKFile " << fname << ':';
00078         if (nSwitch > 1) os << endl;
00079     }
00080 
00081     // open the file
00082     ifstream ifs;
00083     if (!OpenFile(fname, /*OUT*/ ifs)) return;
00084 
00085     try {
00086         // read it (including the PKFiles)
00087         SMultiPKFileRep::Header hdr(ifs);
00088         hdr.ReadEntries(ifs);
00089         hdr.ReadPKFiles(ifs);
00090         FS::Close(ifs);
00091 
00092         // walk over the PKFiles in the MultiPKFile
00093         int entryCnt = 0;
00094         for (int i = 0; i < hdr.num; i++) {
00095             SMultiPKFileRep::HeaderEntry *he;
00096             bool inTbl = hdr.pkTbl.Get(*(hdr.pkSeq[i]), he);
00097             assert(inTbl);
00098 
00099             // walk over the entries in the PKFile
00100             SPKFile *pkFile = he->pkfile;
00101             SPKFile::CFPEntryIter it(pkFile->OldEntries());
00102             FP::Tag fp; CE::List *entries;
00103             while (it.Next(/*OUT*/ fp, /*OUT*/ entries)) {
00104                 // walk over the entries in the CFP group
00105                 while (entries != (CE::List *)NULL) {
00106                     CE::T *ent = entries->Head();
00107                     if (ciOnly < 0 || ciOnly == ent->CI()) {
00108                         // act on this entry
00109                         entryCnt++;
00110                         const VestaVal::T *val = ent->Value();
00111                         switch (nSwitch) {
00112                           case 0:
00113                             // print the entry's pickled value to 'os'
00114                             FS::Write(os, (char *)(&(val->len)),
00115                               sizeof(val->len));
00116                             FS::Write(os, val->bytes, val->len);
00117                             break;
00118                           case 1:
00119                             // do nothing
00120                             break;
00121                           case 2:
00122                             // print a summary of the entry to 'os'
00123                             os << "  ci = " << ent->CI()
00124                                << "; value length = " << val->len << endl;
00125                             break;
00126                         }
00127                     }
00128                     entries = entries->Tail();
00129                 }
00130             }
00131         }
00132         if (nSwitch == 1) os << " entries = " << entryCnt << endl;
00133     } catch (...) {
00134         if (nSwitch == 1) os << endl;
00135         FS::Close(ifs);
00136         throw;
00137     }
00138 }
00139 
00140 static void FSStat(const Text &path, /*OUT*/ struct stat *buffer)
00141   throw (FS::Failure, FS::DoesNotExist)
00142 {
00143     if (stat(path.cchars(), buffer) != 0) {
00144         if (errno == ENOENT) throw FS::DoesNotExist();
00145         else throw FS::Failure(Text("stat"), path);
00146     }
00147 }
00148 
00149 static bool IsDotDir(char *arc) throw ()
00150 {
00151     return (!strcmp(arc, ".") || !strcmp(arc, ".."));
00152 }
00153 
00154 static bool IsTempFile(const Text &path) throw ()
00155 /* Return true iff "path" ends in an arc of the form "<hex-digit>+;*". */
00156 {
00157     int slashIx = path.FindCharR('/');
00158     int semiIx = path.FindChar(AtomicFile::reserved_char, slashIx);
00159     if (semiIx <= 0) return false;
00160     for (int i = slashIx + 1; i < semiIx; i++) {
00161         if (!isxdigit(path[i])) return false;
00162     }
00163     return true;
00164 }
00165 
00166 static void SearchPath2(ostream &os, const Text &path, int nSwitch,
00167   int ciOnly, struct stat *statBuff) throw (FS::EndOfFile, FS::Failure)
00168 {
00169     // handle files and directories differently
00170     if (S_ISDIR(statBuff->st_mode)) {
00171         // iterate over children and recurse
00172         DIR *dir;
00173         if ((dir = opendir(path.cchars())) == NULL) {
00174             assert(errno != ENOENT);
00175             throw FS::Failure(Text("opendir"), path);
00176         }
00177         Text pathSlash(path + '/');
00178         struct dirent *sysDirEnt;
00179         while ((sysDirEnt = readdir(dir)) != (struct dirent *)NULL) {
00180             // skip "." and ".."
00181             if (IsDotDir(sysDirEnt->d_name)) continue;
00182 
00183             // skip if this is a temporary file created by VestaAtomicLog
00184             Text fullname(pathSlash + sysDirEnt->d_name);
00185             struct stat buffer;
00186             FSStat(fullname, /*OUT*/ &buffer);
00187             if (S_ISREG(buffer.st_mode) && IsTempFile(fullname)) {
00188                 continue;
00189             }
00190 
00191             // search recursively
00192             SearchPath2(os, fullname, nSwitch, ciOnly, &buffer);
00193         }
00194         if (closedir(dir) < 0) {
00195             throw FS::Failure(Text("closedir"), path);
00196         }
00197     } else {
00198         // read MultiPKFile
00199         assert(S_ISREG(statBuff->st_mode));
00200         try {
00201             SearchMPK(os, path, nSwitch, ciOnly);
00202         } catch (SMultiPKFileRep::BadMPKFile) {
00203             cerr << "Warning: ignoring bad MultiPKFile:" <<endl << path <<endl;
00204         }
00205     }
00206 }
00207 
00208 static void SearchPath(ostream &os, const char *path, int nSwitch, int ciOnly)
00209   throw (FS::EndOfFile, FS::Failure)
00210 {
00211     // make path absolute
00212     Text fullpath(path);
00213     if (path[0] != '/') {
00214         // make path absolute
00215         if (fullpath.Length() > 0) {
00216             fullpath = Config_SCachePath + ('/' + fullpath);
00217         } else {
00218             fullpath = Config_SCachePath;
00219         }
00220     }
00221 
00222     // search recursively
00223     struct stat buffer;
00224     FSStat(fullpath, /*OUT*/ &buffer);
00225     SearchPath2(os, fullpath, nSwitch, ciOnly, &buffer);
00226 }
00227 
00228 int main(int argc, char *argv[])
00229 {
00230     // command-line switch values
00231     int nSwitch = 0;
00232     int ci = -1;
00233 
00234     // process command-line
00235     int arg = 1;
00236     while (arg < argc && *argv[arg] == '-') {
00237         if (strcmp(argv[arg], "-n") == 0) {
00238             nSwitch = 1; arg++;
00239         } else if (strcmp(argv[arg], "-N") == 0) {
00240             nSwitch = 2; arg++;
00241         } else if (CacheArgs::StartsWith(argv[arg], "-ci")) {
00242             arg++;
00243             if (arg < argc-1) {
00244                 int res = sscanf(argv[arg], "%d", &ci);
00245                 if (res != 1 || ci < 0) {
00246                     Error("argument to `-ci' is not a non-negative integer",
00247                           argv[arg]);
00248                 }
00249                 arg++;
00250             } else {
00251                 Error("no argument for `-ci'");
00252             }
00253         } else {
00254             Error("unrecognized switch", argv[arg]);
00255         }
00256     }
00257     if (arg < argc - 1) {
00258         Error("at most one `path' argument allowed", argv[arg]);
00259     }
00260     const char *path = (arg < argc) ? argv[arg] : "";
00261 
00262     // print the pickled values in "path"
00263     try {
00264         SearchPath(cout, path, nSwitch, ci);
00265     }
00266     catch (FS::EndOfFile) {
00267         cerr << "Fatal error: unexpected end-of-file" << endl;
00268         exit(3);
00269     }
00270     catch (FS::Failure &f) {
00271         cerr << f;
00272         exit(4);
00273     }
00274     return 0;
00275 }

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