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

PrimRunTool.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 /* File: PrimRunTool.C                                         */
00020 /* Last Modified On Mon May 23 23:26:37 EDT 2005 by ken@xorian.net         */
00021 /*      Modified On Wed Apr 27 09:50:29 EDT 2005 by irina.furman@intel.com */
00022 /*      Modified On Fri Jun  1 11:50:42 PDT 2001 by yuanyu     */
00023 /*      Modified On Fri Jul 14 20:44:29 PDT 2000 by mann       */
00024 /*      Modified On Wed Feb 10 16:58:42 PST 1999 by heydon     */
00025 /*      Modified On Fri Mar  1 13:29:44 PST 1996 by levin      */
00026 /*      Modified On Fri Jan 26 14:59:36 PST 1996 by horning    */
00027 
00028 #include <iomanip>
00029 #include <sstream>
00030 #include <Basics.H>
00031 #include <OS.H>
00032 #include <RegExp.H>
00033 #include <VestaConfig.H>
00034 #include <chars_seq.H>
00035 #include <UniqueId.H>
00036 #include <RunToolClient.H>
00037 #include <SourceOrDerived.H>
00038 #include <VDirSurrogate.H>
00039 #include "PrimRunTool.H"
00040 #include "Expr.H"
00041 #include "ToolDirectoryServer.H"
00042 #include "Err.H"
00043 #include "ListT.H"
00044 #include "Signal.H"
00045 #include "RunToolHost.H"
00046 #include "ThreadData.H"
00047 #include "EvalBasics.H"
00048 
00049 using std::ios;
00050 using std::ostream;
00051 using std::ostringstream;
00052 using std::cout;
00053 using std::cin;
00054 using std::cerr;
00055 using std::setw;
00056 using std::setfill;
00057 using std::hex;
00058 using std::dec;
00059 using std::endl;
00060 using std::flush;
00061 
00062 // Names for "fields" of RunTool result binding
00063 static Text codeName("code"),
00064             sigName("signal"),
00065             stowName("stdout_written"),
00066             stewName("stderr_written"),
00067             stdoName("stdout"),
00068             stdeName("stderr"),
00069             rootName("root"),
00070             coreName("dumped_core");
00071 
00072 static DepPath rootPath(Text("."));
00073 
00074 // Size hint for runtool dependency set:
00075 static const int runToolDepSize = 80;
00076 
00077 // Size hint for the number of volatile dirs in a runtool call.
00078 static const int runToolDirNum = 20;
00079 
00080 // Some utility functions
00081 struct OurClosure {
00082   Binding newstuff;
00083   VestaSource *dir;
00084   ListT<NodeInfo> *nodeList;
00085   bool found_core;
00086   Text dir_path;
00087 };
00088 
00089 // A regular expression for matching core files
00090 static Basics::RegExp *core_match_re = 0;
00091 
00092 // The default regular expression to use, if
00093 // [Evaluator]core_dump_regexp is not set.
00094 static const char *core_match_re_default = "core(\\.[0-9][0-9]*)?";
00095 
00096 extern "C"
00097 {
00098   void core_match_init()
00099   {
00100     // If [Evaluator]core_dump_regexp is set, attempt to parse it as a
00101     // regular expression.
00102     if(VestaConfig::is_set("Evaluator", "core_dump_regexp"))
00103       {
00104         try
00105           {
00106             Text pattern =
00107               VestaConfig::get_Text("Evaluator", "core_dump_regexp");
00108             core_match_re = NEW_CONSTR(Basics::RegExp, (pattern));
00109           }
00110         catch(Basics::RegExp::ParseError e)
00111           {
00112             outputMu.lock();
00113             cerr << "Error parsing [Evaluator]core_dump_regexp: "
00114                  << e.msg << endl;
00115             outputMu.unlock();
00116               
00117           }
00118         catch(VestaConfig::failure f)
00119           {
00120             // Shouldn't happen, but if it does we ignore it.
00121           }
00122       }
00123 
00124     // If we still don't have a regular expression, either because
00125     // the config variable wasn't set, or we got a parsing error on
00126     // it, use a default
00127     if(core_match_re == 0)
00128       {
00129         try
00130           {
00131             core_match_re = NEW_CONSTR(Basics::RegExp, (core_match_re_default));
00132           }
00133         catch(Basics::RegExp::ParseError e)
00134           {
00135             outputMu.lock();
00136             cerr << "Error parsing default core dump regular expression: "
00137                  << e.msg << endl;
00138             outputMu.unlock();
00139           }
00140       }
00141   }
00142 }
00143 
00144 // Test a filename to see if it looks like a core file
00145 static bool core_match(Text arc)
00146 {
00147   static pthread_once_t core_match_once = PTHREAD_ONCE_INIT;
00148   pthread_once(&core_match_once, core_match_init);
00149 
00150   if(core_match_re != 0) return core_match_re->match(arc);
00151 
00152   // Something must have gone wrong with initializing the core
00153   // matching regular expression.
00154   return false;
00155 }
00156 
00157 Text ToolCommandLineAsText(const RunToolArgs &args)
00158 {
00159   // list is known to be a list of texts; see ApplyCache
00160   Vals vlist = args.command_line->elems;
00161   Text result;
00162   while (!vlist.Null()) {
00163     if(!result.Empty())
00164       {
00165         result += " ";
00166       }
00167     result += ((TextVC*)(vlist.Pop()))->NDS();
00168   }
00169   return result;
00170 }
00171 
00172 chars_seq *ConvertVals(ListVC *list) {
00173   // list is known to be a list of texts; see ApplyCache
00174   Vals vlist = list->elems;
00175   chars_seq *result = NEW_CONSTR(chars_seq, (5, 100));
00176 
00177   while (!vlist.Null()) {
00178     result->append(((TextVC*)(vlist.Pop()))->NDS().chars());
00179   }
00180   return result;
00181 }
00182 
00183 chars_seq *ConvertEnvVars(BindingVC *b) {
00184   // b is known to be a binding of texts; see BindRunToolArgs.
00185   Context c = b->elems;
00186 
00187   chars_seq *result = NEW_CONSTR(chars_seq, (10, 20));
00188   while (!c.Null()) {
00189     Assoc a = c.Pop();
00190     Text t(a->name + "=");
00191     t += ((TextVC*)a->val)->NDS();
00192     result->append(t);
00193   }    
00194   return result;
00195 }
00196 
00197 // The callback
00198 bool ProcessDirectory(void* cl, VestaSource::typeTag type, Arc arc,
00199                       unsigned int index, Bit32 pseudoInode,
00200                       ShortId filesid, bool master) {
00201   NodeInfo ni = NEW(nodeinfo);
00202 
00203   ni->type  = type;
00204   ni->arc   = Text(arc);
00205   ni->index = index;
00206   ((OurClosure*)cl)->nodeList->Push(ni);
00207   return true;
00208 }
00209 
00210 // Helper function for a workaround for late deletion of ".nfsXXX"
00211 // files that are are used by NFS clients for files deleted while a
00212 // process still has them open.
00213 static inline bool nfs_open_but_deleted_name(Arc arc)
00214 {
00215   // If it doesn't start with ".nfs", it's not an open-but-deleted
00216   // name.
00217   if(strncmp(arc, ".nfs", 4) != 0)
00218     {
00219       return false;
00220     }
00221   // Skip over the ".nfs"
00222   arc += 4;
00223   // Skip characters until we find the end of the string or a
00224   // non-hex-digit.
00225   while(*arc && isxdigit(*arc))
00226     {
00227       arc++;
00228     }
00229   // If we've reached the end of the string (meaning all characters
00230   // after ".nfs" were hex digits), then this is an open-but-deleted
00231   // name.  Otherwise, it's not.
00232   return (*arc == 0);
00233 }
00234 
00235 bool AddToNewStuff(OurClosure *cl, bool look_for_cores, Text label) {
00236   VestaSource *f, *d;
00237   Text name;
00238   TextVC *file;
00239   NodeInfo ni;
00240   OurClosure newcl;
00241   Arc arc;
00242 
00243   while(!cl->nodeList->Null()) {
00244     ni = cl->nodeList->Pop();
00245     arc = ni->arc.chars();
00246     name = Text(arc);
00247     try {
00248       switch (ni->type) {
00249       case VestaSource::mutableFile:
00250       case VestaSource::immutableFile:
00251         {
00252           VestaSource::errorCode res = cl->dir->lookup(arc, f);
00253           // Workaround for late delete-on-close of files deleted
00254           // while open on client.  If one happens to get removed
00255           // between the list call that got us its name and this
00256           // lookup call, just ignore it and move on to the next entry
00257           // in the directory.  (Note that this doesn't prevent such
00258           // files from making it into the result of _run_tool.)
00259           if((res == VestaSource::notFound) &&
00260              nfs_open_but_deleted_name(arc))
00261             {
00262               break;
00263             }
00264           assert(res == VestaSource::ok);
00265           assert(f->type == VestaSource::mutableFile ||
00266                  f->type == VestaSource::immutableFile);
00267           file = NEW_CONSTR(TextVC, (name, f->shortId(), f->fptag));
00268           cl->newstuff = cl->newstuff->AddBindingAssoc(name, file);
00269           if(look_for_cores && core_match(name)) {
00270             char *sid =
00271               SourceOrDerived::shortIdToName(f->shortId(), false);
00272             outputMu.lock();
00273             cerr << label << "Possible core file: "
00274                  << cl->dir_path << name << "\n"
00275                  << label << "at " << sid << endl;
00276             outputMu.unlock();
00277             delete[] sid;
00278             cl->found_core = true;
00279           }
00280           break;
00281         }
00282       case VestaSource::volatileDirectory:
00283       case VestaSource::immutableDirectory:
00284       case VestaSource::volatileROEDirectory:
00285         {
00286           VestaSource::errorCode res = cl->dir->lookup(arc, d);
00287           assert(res == VestaSource::ok);
00288           assert(d->type == VestaSource::volatileDirectory ||
00289                  d->type == VestaSource::immutableDirectory ||
00290                  d->type == VestaSource::volatileROEDirectory);
00291           newcl.newstuff = NEW(BindingVC);
00292           newcl.dir = d;
00293           newcl.nodeList = NEW(ListT<NodeInfo>);
00294           newcl.found_core = false;
00295           newcl.dir_path = cl->dir_path + name + "/";
00296           res = d->list(0, ProcessDirectory, &newcl, NULL, true);
00297           assert(res == VestaSource::ok);
00298           bool new_stuff_added = AddToNewStuff(&newcl, look_for_cores, label);
00299           assert(new_stuff_added);
00300           cl->newstuff = cl->newstuff->AddBindingAssoc(name, newcl.newstuff);
00301           cl->found_core = newcl.found_core || cl->found_core;
00302           break;
00303         }
00304       case VestaSource::deleted:
00305         // Might have existed in original binding, or could have been
00306         // created and deleted by tool.
00307         cl->newstuff = cl->newstuff->AddBindingAssoc(name, valFalse);
00308         break;
00309       default:  // impossible
00310         outputMu.lock();        
00311         Error(Text("AddToNewStuff failed, bad type: ") +
00312               IntToText(ni->type) + ".\n");
00313         outputMu.unlock();      
00314         return false;
00315       }
00316     } catch (SRPC::failure f) {
00317       outputMu.lock();      
00318       Error(Text("AddToNewStuff failed (") + IntToText(f.r) +
00319             "): " + f.msg + ".\n");
00320       outputMu.unlock();      
00321       return false;
00322     }
00323   }
00324   return true;
00325 }
00326 
00327 // Format the volatile directory name into a Text
00328 Text volatileDirName(const LongId &fsroot)
00329 {
00330   unsigned int index;
00331   (void) fsroot.getParent(&index);
00332   char arc[(sizeof(index) * 2) + 1];
00333   sprintf(arc, "%08x", index);
00334   return VestaConfig::get_Text("Run_Tool", "VolatileRootName") + "/" + arc;
00335 }
00336 
00337 // Run the tool!
00338 Val RunTool(const RunToolArgs &args, VestaSource*& rootForTool) {
00339   // Returns a Binding; fields documented below.
00340 
00341   rootForTool = NULL;
00342   LongId fsroot;
00343   ostream *report_out, *report_err, *value_out, *value_err;
00344   SourceOrDerived out_sd, err_sd;
00345   ShortId out_sid = NullShortId, err_sid = NullShortId;
00346   bool stdout_cache, stderr_cache, status_cache, signal_cache;
00347   Text stdin_name;
00348 
00349   create_tool_directory_server();
00350 
00351   // command_line:
00352   chars_seq *argv = ConvertVals(args.command_line);
00353 
00354   // stdin_data:
00355   if (args.stdin_data->Length() != 0) {
00356     ShortId id = args.stdin_data->Sid();
00357     SourceOrDerived sd;
00358     sd.open(id);
00359     stdin_name = VestaConfig::get_Text("Repository", "metadata_root") +
00360       sd.shortIdToName(id);
00361     sd.close();
00362   }
00363 
00364   // ./root: already type-checked by BindRunToolArgs
00365   Binding root = (BindingVC*)args.dot->LookupNoDpnd("root");
00366 
00367   // Initialize dirInfos of this runtool call, and put it into the 
00368   // table runToolCalls.
00369   DirInfo *rootDir = NEW(DirInfo);
00370   rootDir->b = root;
00371   rootDir->path = rootPath;
00372   rootDir->isRoot = true;
00373   rootDir->child_lookup = false;
00374   rootDir->coarseDep = false;
00375   Word rootHandle = GetNewHandle();
00376   DirInfos *dirInfos = NEW(DirInfos);
00377   dirInfos->dirInfoTbl = NEW_CONSTR(DirInfoTbl, (runToolDirNum));
00378   dirInfos->dirInfoTbl->Put(WordKey(rootHandle), rootDir);
00379   dirInfos->dep = NEW_CONSTR(DPaths, (runToolDepSize));
00380   runToolCalls.Put(WordKey(rootHandle>>20), dirInfos);
00381 
00382   // stdout_treatment:
00383   Text stdout_treatment((args.stdout_treatment)->NDS());
00384   stdout_cache = true;
00385   report_out = NULL;
00386   value_out = NULL;
00387   if (stdout_treatment == "value" ||
00388       stdout_treatment == "report_value") {
00389     try {
00390       out_sid = CreateDerived();
00391       out_sd.open(out_sid, ios::out);
00392       value_out = &out_sd;
00393     } catch (SRPC::failure f) {
00394       outputMu.lock();  
00395       Error(Text("RunTool: Cannot create fstream for standard output; ")
00396             + f.msg + ".\n");
00397       outputMu.unlock();        
00398       return NEW(ErrorVC);
00399     } catch (SourceOrDerived::Fatal f) {
00400       outputMu.lock();  
00401       Error(Text("RunTool: Cannot create fstream for standard output; ")
00402             + f.msg + ".\n");
00403       outputMu.unlock();        
00404       return NEW(ErrorVC);
00405     }
00406     if (out_sd.bad()) {
00407       outputMu.lock();  
00408       Error(Text("RunTool: Cannot create fstream for standard output; errno = "
00409                  + IntToText(errno)));
00410       outputMu.unlock();
00411       return NEW(ErrorVC);
00412     }
00413   }
00414   if (stdout_treatment == "report_nocache" ||
00415       stdout_treatment == "report" ||
00416       stdout_treatment == "report_value") {
00417     stdout_cache = stdout_treatment != "report_nocache";
00418     report_out = &cout;
00419   }
00420 
00421   // stderr_treatment:
00422   Text stderr_treatment((args.stderr_treatment)->NDS());
00423   stderr_cache = true;
00424   report_err = NULL;
00425   value_err = NULL;
00426   if (stderr_treatment == "value" ||
00427       stderr_treatment == "report_value") {
00428     try {
00429       err_sid = CreateDerived();
00430       err_sd.open(err_sid, ios::out);
00431       value_err = &err_sd;
00432     } catch (SRPC::failure f) {
00433       outputMu.lock();  
00434       Error(Text("RunTool: Cannot create fstream for standard err; ")
00435             + f.msg + ".\n");
00436       outputMu.unlock();        
00437       return NEW(ErrorVC);
00438     } catch (SourceOrDerived::Fatal f) {
00439       outputMu.lock();  
00440       Error(Text("RunTool: Cannot create fstream for standard err; ")
00441             + f.msg + ".\n");
00442       outputMu.unlock();        
00443       return NEW(ErrorVC);
00444     }
00445     if (err_sd.bad()) {
00446       outputMu.lock();  
00447       Error(Text("RunTool: Cannot create fstream for standard err; errno = "
00448                  + IntToText(errno)));
00449       outputMu.unlock();
00450       return NEW(ErrorVC);
00451     }
00452   }
00453   if (stderr_treatment == "report_nocache" ||
00454       stderr_treatment == "report" ||
00455       stderr_treatment == "report_value") {
00456     stderr_cache = stderr_treatment != "report_nocache";
00457     report_err = &cerr;
00458   }
00459   
00460   // status_treatment:
00461   Text status_treatment((args.status_treatment)->NDS());
00462   if (status_treatment == "report_nocache")
00463     status_cache = false;
00464   else {
00465     assert(status_treatment == "report");
00466     status_cache = true;
00467   }
00468 
00469   // signal_treatment:
00470   Text signal_treatment((args.signal_treatment)->NDS());
00471   if (signal_treatment == "report_nocache")
00472     signal_cache = false;
00473   else {
00474     assert(signal_treatment == "report");
00475     signal_cache = true;
00476   }
00477 
00478   // wd_name:
00479   const Text wd((args.wd_name)->NDS());
00480 
00481   // ./envVars:   type-checked by BindRunToolArgs
00482   BindingVC *envVars = (BindingVC*)args.dot->Lookup("envVars");
00483   chars_seq *ev = ConvertEnvVars(envVars);
00484 
00485   // create the volatile directory:
00486   try {
00487     VestaSource::errorCode err =
00488       VDirSurrogate::createVolatileDirectory(SRPC::this_host().chars(),
00489                                              toolDirServerIntfName.chars(),
00490                                              rootHandle, rootForTool, 0,
00491                                              !args.existing_writable->b);
00492     if (err != VestaSource::ok) {
00493       outputMu.lock();      
00494       Error(Text("RunTool: createVolatileDirectory failed (") +
00495             VestaSource::errorCodeString(err) + ".\n");
00496       outputMu.unlock();      
00497       return NEW(ErrorVC);
00498     }
00499   } catch (SRPC::failure f) {
00500     outputMu.lock();    
00501     Error(Text("RunTool: createVolatileDirectory failed (")
00502           + IntToText(f.r) + "): " + f.msg + ".\n");
00503     outputMu.unlock();    
00504     return NEW(ErrorVC);
00505   }
00506   fsroot = rootForTool->longid;
00507 
00508   // host:
00509   void* handle;
00510   const Text host(RunToolHost(args.platform, args.loc, /*OUT*/handle));
00511   const Text label = ThreadLabel();
00512 
00513   // print the command-line:
00514   outputMu.lock();
00515   cout << label << host << ": ";
00516   for (int arg = 0; arg < argv->length(); arg++) {
00517     cout << (*argv)[arg] << " ";
00518   }
00519   cout << endl;
00520   if(getenv("DEBUG_TOOL_DIR_SERVER"))
00521     {
00522       // Print out the root handle for the tool directory server, the
00523       // LongId of the root, and the name of the root within the
00524       // volatile root.
00525       char handle_buff[17];
00526       sprintf(handle_buff, "%016" FORMAT_LENGTH_INT_64 "x", rootHandle);
00527       cout << label << "[tool dir server root handle = "
00528            << handle_buff << "]" << endl
00529            << label << "[root LongId = ";
00530       for(unsigned int i = 0, len = fsroot.length(); i < len; i++)
00531         {
00532           cout << setw(2) << setfill('0') << hex
00533                << (int) (fsroot.value.byte[i] & 0xff);
00534         }
00535       cout << setfill(' ') << dec << "]" << endl
00536            << label << "[root directory name = ";
00537       cout << volatileDirName(fsroot) << "]" << endl;
00538     }
00539   if(pauseBeforeTool) {
00540           cout << label << "Running in " << volatileDirName(fsroot) << "/"
00541                 << wd << endl;
00542           cout << label << "Using the following environment variables:"
00543                 << endl;
00544           for(int i = 0; i < ev->length(); i++) {
00545                   cout << label << "\t" << (*ev)[i] << endl;
00546           }
00547           char enter;
00548           cout << label << "Press Enter to continue...";
00549           cout << flush;
00550           cin.get(enter);
00551           cout << label << "Continuing." << endl;
00552   }
00553   outputMu.unlock();  
00554 
00555   // Call the RunTool!
00556   RunTool::Tool_result r;
00557   try {
00558     r = RunTool::do_it(
00559       host,       // const Text &host
00560       argv,       // chars_seq *argv
00561       fsroot,     // LongId &fsroot
00562       wd,         // const Text &wd = DEFAULT_TOOL_WD
00563       ev,         // chars_seq *ev = NULL
00564       report_out,
00565       value_out,
00566       report_err,
00567       value_err,
00568       &outputMu,
00569       label,
00570       stdin_name  // const Text &stdin_name = ""
00571     );
00572     //  struct Tool_result {
00573     //    int status;
00574     //    int sigval;
00575     //    bool stdout_written;
00576     //    bool stderr_written;
00577     //  };
00578     if (out_sid != NullShortId) { FS::Close(out_sd); }
00579     if (err_sid != NullShortId) { FS::Close(err_sd); }
00580   } catch (SRPC::failure f) {
00581     outputMu.lock();    
00582     Error("invoking _run_tool: " + f.msg + "\n");
00583     outputMu.unlock();    
00584     if (out_sid != NullShortId) out_sd.close();
00585     if (err_sid != NullShortId) err_sd.close();
00586     RunToolDone(handle);
00587     throw(Evaluator::failure(Text("_run_tool failure"), false));
00588   } catch (FS::Failure f) {
00589     // Failed because of filesystem error
00590     outputMu.lock();
00591     ostringstream l_err_msg;
00592     l_err_msg << "writing standard output/error file:" << endl
00593               << f;
00594     Error(l_err_msg.str());
00595     outputMu.unlock();
00596     RunToolDone(handle);
00597     throw(Evaluator::failure(Text("_run_tool failure"), false));
00598   }
00599   if(pauseAfterTool || (pauseAfterToolSignal && r.sigval) ||
00600         (pauseAfterToolError && r.status)) {
00601           outputMu.lock();
00602           cout << label << "Ran in " << volatileDirName(fsroot) << "/" << wd
00603                << endl;
00604           cout << label << "Used the following environment variables:" << endl;
00605           for(int i = 0; i < ev->length(); i++) {
00606                   cout << label << "\t" << (*ev)[i] << endl;
00607           }
00608           cout << label << "Exited with status " << r.status << ", signal "
00609                 << r.sigval << endl;
00610           char enter;
00611           cout << label << "Press Enter to continue...";
00612           cout << flush;
00613           cin.get(enter);
00614           cout << label << "Continuing." << endl;
00615           outputMu.unlock();
00616   }
00617   RunToolDone(handle);
00618 
00619   OurClosure cl;
00620   cl.newstuff = NEW(BindingVC);
00621   cl.dir = rootForTool;
00622   cl.nodeList = NEW(ListT<NodeInfo>);
00623   cl.found_core = false;
00624   cl.dir_path = "/";
00625 
00626   try {
00627     VestaSource::errorCode ok;
00628     ok = rootForTool->list(0, ProcessDirectory, &cl, NULL, true);
00629     if (ok != VestaSource::ok)
00630       throw (SRPC::failure(ok, "problem listing volatile directory"));
00631     ok = rootForTool->makeFilesImmutable(args.fp_content->num);
00632     if (ok != VestaSource::ok)
00633       throw (SRPC::failure(ok,
00634         "problem with making files immutable for volatile directory"));
00635     bool new_stuff_added = AddToNewStuff(&cl, r.dumped_core, label);
00636     assert(new_stuff_added);
00637   } catch (SRPC::failure f) {
00638     outputMu.lock();    
00639     Error(Text("RunTool error (") + IntToText(f.r) + "): " + f.msg + ".\n");
00640     outputMu.unlock();    
00641     return NEW(ErrorVC);
00642   }
00643   if (r.dumped_core && !cl.found_core) {
00644           outputMu.lock();
00645           cerr << label << "Warning: tool dumped core but couldn't find the file." << endl;
00646           outputMu.unlock();
00647   }
00648 
00649   if (r.sigval && !signal_cache) {
00650     if (stopOnError) {
00651       outputMu.lock();      
00652       Error(Text("RunTool error: tool terminated with signal ") +
00653             IntToText(r.sigval) + "(" + getSigMsg(r.sigval) + ").\n");
00654       outputMu.unlock();      
00655       throw(Evaluator::failure(Text("exiting"), false));
00656     }
00657   }
00658   else if (r.status && !status_cache) {
00659     if (stopOnError) {
00660       outputMu.lock();      
00661       Error(Text("RunTool error: tool terminated with non-zero status (") +
00662             IntToText(r.status) + ").\n");
00663       outputMu.unlock();      
00664       throw(Evaluator::failure(Text("exiting"), false));
00665     }
00666   }
00667 
00668   // Collect the result:
00669   Context assocs;
00670   assocs.Push(NEW_CONSTR(AssocVC, (rootName, cl.newstuff)));
00671   if (stderr_treatment == "value" || stderr_treatment == "report_value") {
00672     assocs.Push(NEW_CONSTR(AssocVC, (stdeName, 
00673       NEW_CONSTR(TextVC, (Text("stderr"), err_sid, args.fp_content->num)))));
00674   }
00675   if (stdout_treatment == "value" || stdout_treatment == "report_value") {
00676     assocs.Push(NEW_CONSTR(AssocVC, (stdoName,
00677       NEW_CONSTR(TextVC, (Text("stdout"), out_sid, args.fp_content->num)))));
00678   }
00679   assocs.Push(NEW_CONSTR(AssocVC, 
00680                          (stewName, NEW_CONSTR(BooleanVC, (r.stderr_written)))));
00681   assocs.Push(NEW_CONSTR(AssocVC, 
00682                          (stowName, NEW_CONSTR(BooleanVC, (r.stdout_written)))));
00683   assocs.Push(NEW_CONSTR(AssocVC, 
00684                          (sigName, NEW_CONSTR(IntegerVC, (r.sigval)))));
00685   assocs.Push(NEW_CONSTR(AssocVC, 
00686                          (codeName, NEW_CONSTR(IntegerVC, (r.status)))));
00687   assocs.Push(NEW_CONSTR(AssocVC, 
00688                          (coreName, NEW_CONSTR(BooleanVC, (r.dumped_core)))));
00689 
00690   Val result = NEW_CONSTR(BindingVC, (assocs));
00691 
00692   // Set the cacheit bit:
00693   result->cacheit = ((!r.sigval || signal_cache) &&
00694                      (!r.status || status_cache) &&
00695                      (!r.stdout_written || stdout_cache) &&
00696                      (!r.stderr_written || stderr_cache) &&
00697                      (!(pauseAfterToolSignal && r.sigval)) &&
00698                      (!(pauseAfterToolError && r.status)) &&
00699                      (!pauseBeforeTool) &&
00700                      (!pauseAfterTool) &&
00701                      // It would be very strange for a process to dump
00702                      // core w/o getting a signal.  If that happens,
00703                      // we trat it like a signal for caching purposes.
00704                      (!r.dumped_core || signal_cache));
00705 
00706   // remove information about this volatile directory.  (Note: there's
00707   // a minor race condition here as a ToolDirectoryServer thread could
00708   // already have a pointer to dirInfos and be using it past the point
00709   // we delete it from the table.)
00710   runToolCalls.Delete(rootHandle>>20, dirInfos);
00711 
00712   // For any directory which was looked up itself but for which none
00713   // of its children were looked up, add a type dependency on the
00714   // directory being a binding.
00715   DirInfoIter it(dirInfos->dirInfoTbl);
00716   WordKey unused;
00717   DirInfo *dirInfo;
00718   while(it.Next(unused, dirInfo))
00719     if(!dirInfo->child_lookup)
00720       dirInfos->dep->Add(&(dirInfo->path), valTBinding, TypePK);
00721 
00722   // Set the dependency:
00723   result->dps = dirInfos->dep;
00724 
00725   // return result
00726   return result;
00727 }
00728 
00729 void DeleteRootForTool(VestaSource* rootForTool) {
00730   bool err = VDirSurrogate::deleteVolatileDirectory(rootForTool);
00731   if (err != VestaSource::ok)
00732     throw (SRPC::failure(err, "problem deleting volatile directory for runtool"));
00733 }
00734 
00735 void CreateRootForDeriveds() {
00736   create_tool_directory_server();
00737   VestaSource::errorCode err =
00738     VDirSurrogate::createVolatileDirectory(SRPC::this_host().chars(),
00739                                            toolDirServerIntfName.chars(),
00740                                            GetNewHandle(), rootForDeriveds);
00741   if (err != VestaSource::ok) {
00742     throw (SRPC::failure(err, "problem creating volatile directory"));
00743   }
00744 }
00745 
00746 void DeleteRootForDeriveds() {
00747   VestaSource::errorCode err = VDirSurrogate::deleteVolatileDirectory(rootForDeriveds);
00748   if (err != VestaSource::ok) {
00749     throw (SRPC::failure(err, "problem deleting volatile directory"));
00750   }
00751 }
00752 
00753 ShortId CreateDerived() {
00754   VestaSource* newvs;
00755   static Basics::mutex cdmu;
00756   static int cdcnt = 0;
00757   char arc[32];
00758   cdmu.lock();
00759   sprintf(arc, "%d", cdcnt++);
00760   cdmu.unlock();
00761   VestaSource::errorCode err =
00762     rootForDeriveds->insertMutableFile(arc, NullShortId, true,
00763                                        NULL,VestaSource::replaceDiff, &newvs);
00764   if (err != VestaSource::ok) {
00765     throw (SRPC::failure(err, "problem creating derived."));
00766   }
00767   ShortId sid = newvs->shortId();
00768   delete newvs;
00769   newvs = NULL; // help out the garbage collector
00770   if (sid == NullShortId) {
00771     outputMu.lock();    
00772     Error(Text("Failed to create derived"));
00773     outputMu.unlock();    
00774     throw(Evaluator::failure(Text("exiting"), false));
00775   }
00776   return sid;
00777 }
00778 
00779 void PrimRunToolInit() {
00780   rootPath.Extend(Text("root"));
00781   RunToolHostInit();
00782 }

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