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 <Basics.H>
00028 #include <FS.H>
00029 #include <VestaConfig.H>
00030 #include <CacheIntf.H>
00031 #include <CacheConfig.H>
00032 #include <Debug.H>
00033
00034 #include "WeederConfig.H"
00035 #include "WeedArgs.H"
00036 #include "RootTbl.H"
00037 #include "CommonErrors.H"
00038 #include "Weeder.H"
00039
00040 using std::cout;
00041 using std::cerr;
00042 using std::endl;
00043
00044
00045
00046
00047
00048
00049
00050
00051 static const char *Version = "1.4, 09-May-2002";
00052
00053
00054 static void SyntaxError(char *msg) throw ()
00055 {
00056 cerr << "Error: " << msg << "; exiting..." << endl;
00057 cerr << "Syntax: VestaWeed " << endl;
00058 cerr << " [-nodelete | -query] [-models] [-roots] [-keep dur] [-debug level] [file]" << endl;
00059 exit(1);
00060 }
00061
00062 static void ProcessArgs(int argc, char *argv[], WeedArgs &args)
00063 throw ()
00064 {
00065
00066 args.instrFile = (char *)NULL;
00067 args.debug = CacheIntf::None;
00068 args.delStatus = WeedArgs::DoDeletions;
00069 args.globInstrs = false;
00070 args.printRoots = false;
00071 args.keepSecs = 0;
00072
00073
00074 int arg;
00075 bool sawNorQ = false;
00076 bool sawK = false;
00077 for (arg = 1; arg < argc && *argv[arg] == '-'; arg++) {
00078 if (!strcmp(argv[arg], "-d") || !strcmp(argv[arg], "-debug")) {
00079 arg++;
00080 if (arg >= argc) {
00081 SyntaxError("no 'level' specified for '-debug'");
00082 }
00083 if (sscanf(argv[arg], "%d", &(args.debug)) != 1) {
00084 int i;
00085 for (i = 0; i <= CacheIntf::All; i++) {
00086 if (strcasecmp(argv[arg], CacheIntf::DebugName(i)) == 0)
00087 break;
00088 }
00089 args.debug = (CacheIntf::DebugLevel)i;
00090 }
00091 if (args.debug < CacheIntf::None || args.debug > CacheIntf::All) {
00092 SyntaxError("unrecognized debug level");
00093 }
00094 } else if (strcmp(argv[arg], "-n") == 0 ||
00095 strcmp(argv[arg], "-nodelete") == 0) {
00096 if (sawNorQ) {
00097 SyntaxError("-nodelete and -query are mutually exclusive");
00098 }
00099 sawNorQ = true;
00100 args.delStatus = WeedArgs::NoDeletions;
00101 } else if (strcmp(argv[arg], "-q") == 0 ||
00102 strcmp(argv[arg], "-query") == 0) {
00103 if (sawNorQ) {
00104 SyntaxError("-nodelete and -query are mutually exclusive");
00105 }
00106 sawNorQ = true;
00107 args.delStatus = WeedArgs::QueryDeletions;
00108 } else if (strcmp(argv[arg], "-m") == 0 ||
00109 strcmp(argv[arg], "-models") == 0) {
00110 args.globInstrs = true;
00111 } else if (strcmp(argv[arg], "-r") == 0 ||
00112 strcmp(argv[arg], "-roots") == 0) {
00113 args.printRoots = true;
00114 } else if (!strcmp(argv[arg], "-k") || !strcmp(argv[arg], "-keep")) {
00115 arg++;
00116 if (arg >= argc) {
00117 SyntaxError("no duration argument specified for '-keep'");
00118 }
00119 sawK = true;
00120 char *dur = argv[arg];
00121 int last = strlen(dur) - 1;
00122 int units = 60 * 60;
00123 switch (dur[last]) {
00124 case 'd': units = 60 * 60 * 24; break;
00125 case 'h': units = 60 * 60; break;
00126 case 'm': units = 60; break;
00127 default:
00128 if (!isdigit(dur[last])) {
00129 SyntaxError("unrecognized unit specifier for '-keep' arg");
00130 exit(1);
00131 }
00132 }
00133 if (sscanf(argv[arg], "%d", &(args.keepSecs)) != 1) {
00134 SyntaxError("argument following '-keep' is not an integer");
00135 }
00136 if (args.keepSecs < 0) {
00137 SyntaxError("argument following '-keep' cannot be negative");
00138 }
00139 args.keepSecs *= units;
00140 } else {
00141 SyntaxError("unrecognized command-line switch");
00142 }
00143 }
00144 if (arg < argc - 1) {
00145 SyntaxError("too many arguments");
00146 } else if (arg < argc) {
00147 assert(arg == argc - 1);
00148 args.instrFile = argv[arg];
00149 args.noNew = false;
00150 } else {
00151 args.noNew = true;
00152 if (sawK) {
00153 SyntaxError("-keep flag is meaningless with no input filename");
00154 }
00155 if (args.globInstrs) {
00156 SyntaxError("-models flag is meaningless with no input filename");
00157 }
00158 if (args.printRoots) {
00159 SyntaxError("-roots flag is meaningless with no input filename");
00160 }
00161 }
00162
00163
00164 if (args.debug >= CacheIntf::StatusMsgs) {
00165 cout << Debug::Timestamp() << "Command-line:" << endl << " ";
00166 for (int i = 0; i < argc; i++) {
00167 cout << argv[i] << ' ';
00168 }
00169 cout << endl << endl;
00170 }
00171 }
00172
00173 static bool CentralCache() throw ()
00174 {
00175 return (Config_Host == WeedConfig_CacheHost)
00176 && (Config_Port == WeedConfig_CachePort)
00177 && (Config_MDRoot == WeedConfig_CacheMDRoot)
00178 && (Config_MDDir == WeedConfig_CacheMDDir)
00179 && (Config_GraphLogDir == WeedConfig_CacheGLDir);
00180 }
00181
00182 int main(int argc, char *argv[])
00183 {
00184
00185 WeedArgs args;
00186 ProcessArgs(argc, argv, args);
00187
00188
00189 if (!CentralCache()) {
00190 cerr << "Fatal error: weeder must be run against the central cache!";
00191 cerr << " Exiting..." << endl;
00192 exit(1);
00193 }
00194
00195 try {
00196
00197 Weeder weeder(args.debug);
00198
00199
00200 if (args.debug >= CacheIntf::StatusMsgs) {
00201 cout << Debug::Timestamp() << "Weeder started:" << endl;
00202 cout << " Version: " << Version << endl;
00203 cout << " Configuration file: " <<
00204 VestaConfig::get_location() << endl;
00205 cout << " Graph log directory: " << Config_GraphLogPath << endl;
00206 cout << " Keeping all builds less than "
00207 << args.keepSecs / 3600 << " hours old" << endl;
00208 cout << " Debugging level = "
00209 << CacheIntf::DebugName(args.debug) << endl;
00210 cout << endl;
00211 }
00212
00213
00214 bool resumed = weeder.Weed(args);
00215
00216 if (resumed) {
00217
00218 Weeder weeder2(args.debug);
00219 (void) weeder2.Weed(args);
00220 }
00221
00222 }
00223 catch (SRPC::failure &f) {
00224 cerr << "SRPC failure:" << endl;
00225 cerr << " " << f.msg << endl;
00226 cerr << "Exiting..." << endl;
00227 exit(1);
00228 }
00229 catch (FS::DoesNotExist) {
00230 cerr << "Error: file '" << args.instrFile << "' does not exist"<< endl;
00231 cerr << "Exiting..." << endl;
00232 exit(1);
00233 }
00234 catch (FS::EndOfFile) {
00235 cerr << "Error: premature end-of-file; exiting..." << endl;
00236 exit(1);
00237 }
00238 catch (FS::Failure &f) {
00239 cerr << "Error: reading input file:" << endl;
00240 cerr << " " << f << endl;
00241 cerr << "Exiting..." << endl;
00242 exit(1);
00243 }
00244 catch (VestaLog::Error &err) {
00245 cerr << "VestaLog fatal error -- failed reading graph log:" << endl;
00246 cerr << " " << err.msg << endl;
00247 cerr << "Exiting..." << endl;
00248 exit(1);
00249 }
00250 catch (VestaLog::Eof) {
00251 cerr << "VestaLog fatal error: ";
00252 cerr << "unexpected EOF while reading graph log; exiting..." << endl;
00253 exit(1);
00254 }
00255 catch (InputError &err) {
00256 cerr << "Error in input file '" << args.instrFile << "':" << endl;
00257 cerr << err;
00258 cerr << "Exiting..." << endl;
00259 exit(1);
00260 }
00261 catch (SysError &err) {
00262 cerr << err;
00263 cerr << "Exiting..." << endl;
00264 exit(1);
00265 }
00266 catch (ReposError &err) {
00267 cerr << err;
00268 cerr << "Exiting..." << endl;
00269 exit(1);
00270 }
00271 return 0;
00272 }