Back to index

nordugrid-arc-nox  1.1.0~rc6
info_types.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <iostream>
00006 #include <limits.h>
00007 
00008 #include <arc/StringConv.h>
00009 #include "../misc/canonical_dir.h"
00010 #include "../misc/escaped.h"
00011 #include "info_types.h"
00012 
00013 #if defined __GNUC__ && __GNUC__ >= 3
00014 
00015 #include <limits>
00016 #define istream_readline(__f,__s,__n) {      \
00017    __f.get(__s,__n,__f.widen('\n'));         \
00018    if(__f.fail()) __f.clear();               \
00019    __f.ignore(std::numeric_limits<std::streamsize>::max(), __f.widen('\n')); \
00020 }
00021 
00022 #else
00023 
00024 #define istream_readline(__f,__s,__n) {      \
00025    __f.get(__s,__n,'\n');         \
00026    if(__f.fail()) __f.clear();               \
00027    __f.ignore(INT_MAX,'\n'); \
00028 }
00029 
00030 #endif
00031 
00032 static Arc::Logger& logger = Arc::Logger::getRootLogger();
00033 
00034 void output_escaped_string(std::ostream &o,const std::string &str) {
00035   std::string::size_type n,nn;
00036   for(nn=0;;) {
00037 //    if((n=str.find(' ',nn)) == std::string::npos) break;
00038     if((n=str.find_first_of(" \\",nn)) == std::string::npos) break;
00039     o.write(str.data()+nn,n-nn);
00040     o.put('\\');
00041     o.put(*(str.data()+n));
00042     nn=n+1;
00043   };
00044   o.write(str.data()+nn,str.length()-nn);
00045 }
00046 
00047 std::ostream &operator<< (std::ostream &o,const FileData &fd) {
00048   output_escaped_string(o,fd.pfn);
00049   o.put(' ');
00050   output_escaped_string(o,fd.lfn);
00051   return o;
00052 }
00053 
00054 std::istream &operator>> (std::istream &i,FileData &fd) {
00055   char buf[1024];
00056   istream_readline(i,buf,sizeof(buf));
00057   fd.pfn.resize(0); fd.lfn.resize(0);
00058   int n=input_escaped_string(buf,fd.pfn);
00059   input_escaped_string(buf+n,fd.lfn);
00060   if((fd.pfn.length() == 0) && (fd.lfn.length() == 0)) return i; /* empty st */
00061   if(canonical_dir(fd.pfn) != 0) {
00062     logger.msg(Arc::ERROR,"Wrong directory in %s",buf);
00063     fd.pfn.resize(0); fd.lfn.resize(0);
00064   };
00065   return i;
00066 }
00067 
00068 FileData::FileData(void) {
00069 }
00070 
00071 FileData::FileData(const char *pfn_s,const char *lfn_s) {
00072   if(pfn_s) { pfn=pfn_s; } else { pfn.resize(0); };
00073   if(lfn_s) { lfn=lfn_s; } else { lfn.resize(0); };
00074 }
00075 
00076 FileData& FileData::operator= (const char *str) {
00077   pfn.resize(0); lfn.resize(0);
00078   int n=input_escaped_string(str,pfn);
00079   input_escaped_string(str+n,lfn);
00080   return *this;
00081 }
00082 
00083 bool FileData::operator== (const FileData& data) {
00084   // pfn may contain leading slash. It must be striped
00085   // before comparison.
00086   const char* pfn_ = pfn.c_str();
00087   if(pfn_[0] == '/') ++pfn_;
00088   const char* dpfn_ = data.pfn.c_str();
00089   if(dpfn_[0] == '/') ++dpfn_;
00090   return (strcmp(pfn_,dpfn_) == 0);
00091   // return (pfn == data.pfn);
00092 }
00093 
00094 bool FileData::operator== (const char *name) {
00095   if(name == NULL) return false;
00096   if(name[0] == '/') ++name;
00097   const char* pfn_ = pfn.c_str();
00098   if(pfn_[0] == '/') ++pfn_;
00099   return (strcmp(pfn_,name) == 0);
00100 }
00101 
00102 bool FileData::has_lfn(void) {
00103   return (lfn.find(':') != std::string::npos);
00104 }
00105 
00106 
00107 static char StateToShortcut(const std::string& state) {
00108   if(state == "ACCEPTED") return 'a'; // not supported
00109   if(state == "PREPARING") return 'b';
00110   if(state == "SUBMIT") return 's'; // not supported
00111   if(state == "INLRMS") return 'q';
00112   if(state == "FINISHING") return 'f';
00113   if(state == "FINISHED") return 'e';
00114   if(state == "DELETED") return 'd';
00115   if(state == "CANCELING") return 'c';
00116   return ' ';
00117 }
00118 
00119 JobLocalDescription& JobLocalDescription::operator=(const Arc::JobDescription& arc_job_desc)
00120 {
00121   action = "request";
00122 
00123   projectnames.clear();
00124   projectnames.push_back(arc_job_desc.Identification.JobVOName);
00125 
00126   jobname = arc_job_desc.Identification.JobName;
00127   downloads = 0;
00128   uploads = 0;
00129   rtes = 0;
00130   outputdata.clear();
00131   inputdata.clear();
00132   rte.clear();
00133   transfershare="_default";
00134 
00135   const std::list<Arc::Software>& sw = arc_job_desc.Resources.RunTimeEnvironment.getSoftwareList();
00136   for (std::list<Arc::Software>::const_iterator itSW = sw.begin(); itSW != sw.end(); ++itSW, ++rtes)
00137     rte.push_back(std::string(*itSW));
00138 
00139   for (std::list<Arc::FileType>::const_iterator file = arc_job_desc.DataStaging.File.begin();
00140        file != arc_job_desc.DataStaging.File.end(); ++file) {
00141     std::string fname = file->Name;
00142     if(fname.empty()) continue; // Can handle only named files
00143     if(fname[0] != '/') fname = "/"+fname; // Just for safety
00144     // Because ARC job description does not keep enough information
00145     // about initial JSDL description we have to make some guesses here.
00146     if(!file->Source.empty()) { // input file
00147       // Only one source per file supported
00148       inputdata.push_back(FileData(fname.c_str(), ""));
00149       if (file->Source.front().URI &&
00150           file->Source.front().URI.Protocol() != "file") {
00151         inputdata.back().lfn = file->Source.front().URI.fullstr();
00152         ++downloads;
00153       }
00154 
00155       if (inputdata.back().has_lfn()) {
00156         Arc::URL u(inputdata.back().lfn);
00157 
00158         if (file->IsExecutable ||
00159             file->Name == arc_job_desc.Application.Executable.Name) {
00160           u.AddOption("exec", "yes");
00161         }
00162         if (u.Option("cache").empty())
00163           u.AddOption("cache", (file->DownloadToCache ? "yes" : "no"));
00164         if (u.Option("threads").empty() && file->Source.front().Threads > 1)
00165           u.AddOption("threads", Arc::tostring(file->Source.front().Threads));
00166         inputdata.back().lfn = u.fullstr();
00167       }
00168     }
00169     if (!file->Target.empty()) { // output file
00170       FileData fdata(fname.c_str(), file->Target.front().URI.fullstr().c_str());
00171       outputdata.push_back(fdata);
00172       ++uploads;
00173 
00174       if (outputdata.back().has_lfn()) {
00175         Arc::URL u(outputdata.back().lfn);
00176         if (u.Option("threads").empty() && file->Target.front().Threads > 1)
00177           u.AddOption("threads", Arc::tostring(file->Source.front().Threads));
00178         outputdata.back().lfn = u.fullstr();
00179       }
00180     }
00181     if (file->KeepData) {
00182       // user downloadable file
00183       FileData fdata(fname.c_str(), NULL);
00184       outputdata.push_back(fdata);
00185     }
00186   }
00187 
00188   // Order of the following calls matters!
00189   arguments.clear();
00190   arguments = arc_job_desc.Application.Executable.Argument;
00191   arguments.push_front(arc_job_desc.Application.Executable.Name);
00192 
00193   stdin_ = arc_job_desc.Application.Input;
00194   stdout_ = arc_job_desc.Application.Output;
00195   stderr_ = arc_job_desc.Application.Error;
00196 
00197   if (arc_job_desc.Resources.DiskSpaceRequirement.DiskSpace > -1)
00198     diskspace = (unsigned long long int)arc_job_desc.Resources.DiskSpaceRequirement.DiskSpace;
00199 
00200   processtime = arc_job_desc.Application.ProcessingStartTime;
00201 
00202   const int lifetimeTemp = (int)arc_job_desc.Resources.SessionLifeTime.GetPeriod();
00203   if (lifetimeTemp > 0) lifetime = lifetimeTemp;
00204 
00205   activityid = arc_job_desc.Identification.ActivityOldId;
00206 
00207   stdlog = arc_job_desc.Application.LogDir;
00208 
00209   jobreport.clear();
00210   for (std::list<Arc::URL>::const_iterator it = arc_job_desc.Application.RemoteLogging.begin();
00211        it != arc_job_desc.Application.RemoteLogging.end(); it++) {
00212     jobreport.push_back(it->str());
00213   }
00214 
00215   {
00216     int n = 0;
00217     for (std::list<Arc::NotificationType>::const_iterator it = arc_job_desc.Application.Notification.begin();
00218          it != arc_job_desc.Application.Notification.end(); it++) {
00219       if (n >= 3) break; // Only 3 instances are allowed.
00220       std::string states;
00221       for (std::list<std::string>::const_iterator s = it->States.begin();
00222            s != it->States.end(); ++s) {
00223         char state = StateToShortcut(*s);
00224         if(state == ' ') continue;
00225         states+=state;
00226       }
00227       if(states.empty()) continue;
00228       if(it->Email.empty()) continue;
00229       if (n != 0) notify += " ";
00230       notify += states + " " + it->Email;
00231       n++;
00232     }
00233   }
00234 
00235   if (!arc_job_desc.Resources.CandidateTarget.empty() &&
00236       !arc_job_desc.Resources.CandidateTarget.front().QueueName.empty())
00237     queue = arc_job_desc.Resources.CandidateTarget.front().QueueName;
00238 
00239   if (!arc_job_desc.Application.CredentialService.empty() &&
00240       arc_job_desc.Application.CredentialService.front())
00241     credentialserver = arc_job_desc.Application.CredentialService.front().str();
00242 
00243   if (arc_job_desc.Application.Rerun > -1)
00244     reruns = arc_job_desc.Application.Rerun;
00245 
00246   return *this;
00247 };
00248 
00249 const char* const JobLocalDescription::transfersharedefault = "_default";
00250 
00251 bool LRMSResult::set(const char* s) {
00252   // 1. Empty string = exit code 0
00253   if(s == NULL) s="";
00254   for(;*s;++s) { if(!isspace(*s)) break; };
00255   if(!*s) { code_=0; description_=""; };
00256   // Try to read first word as number
00257   char* e;
00258   code_=strtol(s,&e,0);
00259   if((!*e) || (isspace(*e))) {
00260     for(;*e;++e) { if(!isspace(*e)) break; };
00261     description_=e;
00262     return true;
00263   };
00264   // If there is no number that means some "uncoded" failure
00265   code_=-1;
00266   description_=s;
00267   return true;
00268 }
00269 
00270 std::istream& operator>>(std::istream& i,LRMSResult &r) {
00271   char buf[1025]; // description must have reasonable size
00272   if(i.eof()) { buf[0]=0; } else { istream_readline(i,buf,sizeof(buf)); };
00273   r=buf;
00274   return i;
00275 }
00276 
00277 std::ostream& operator<<(std::ostream& o,const LRMSResult &r) {
00278   o<<r.code()<<" "<<r.description();
00279   return o;
00280 }
00281