Back to index

nordugrid-arc-nox  1.1.0~rc6
plugins.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <cstring>
00006 
00007 #include <arc/Run.h>
00008 #include "../jobs/job.h"
00009 #include "../jobs/states.h"
00010 #include "../jobs/users.h"
00011 
00012 #include "plugins.h"
00013 
00014 /*
00015   Substitution:
00016    %I - job id
00017 */
00018 
00019 
00020 ContinuationPlugins::ContinuationPlugins(void) {
00021 }
00022 
00023 ContinuationPlugins::~ContinuationPlugins(void) {
00024 }
00025 
00026 bool ContinuationPlugins::add(job_state_t state,unsigned int timeout,const char* command) {
00027   if((state == JOB_STATE_ACCEPTED) ||
00028      (state == JOB_STATE_PREPARING) ||
00029      (state == JOB_STATE_SUBMITTING) ||
00030      (state == JOB_STATE_FINISHING) ||
00031      (state == JOB_STATE_FINISHED) ||
00032      (state == JOB_STATE_DELETED)) {
00033     command_t cmd;
00034     cmd.cmd=command;
00035     cmd.to=timeout;
00036     cmd.onsuccess=act_pass;
00037     cmd.onfailure=act_fail;
00038     cmd.ontimeout=act_fail;
00039     commands[state].push_back(cmd);
00040   } else { return false; };
00041   return true;
00042 }
00043 
00044 bool ContinuationPlugins::add(const char* state,unsigned int timeout,const char* command) {
00045   job_state_t i = JobDescription::get_state(state);
00046   if(i != JOB_STATE_UNDEFINED) {
00047     return add(i,timeout,command);
00048   };
00049   return false;
00050 }
00051 
00052 static ContinuationPlugins::action_t get_action(const char *s,unsigned int l) {
00053   if((l == 4) && (strncasecmp(s,"fail",4) == 0)) return ContinuationPlugins::act_fail;
00054   if((l == 4) && (strncasecmp(s,"pass",4) == 0)) return ContinuationPlugins::act_pass;
00055   if((l == 3) && (strncasecmp(s,"log",3) == 0)) return ContinuationPlugins::act_log;
00056   return ContinuationPlugins::act_undefined;
00057 }
00058 
00059 #define RES_ONSUCCESS 0
00060 #define RES_ONFAILURE 1
00061 #define RES_ONTIMEOUT 2
00062 #define RES_TIMEOUT 3
00063 #define RES_UNDEFINED -1
00064 static int get_result(const char *s,unsigned int l) {
00065   if((l == 9) && (strncasecmp(s,"onsuccess",9) == 0)) return RES_ONSUCCESS;
00066   if((l == 9) && (strncasecmp(s,"onfailure",9) == 0)) return RES_ONFAILURE;
00067   if((l == 9) && (strncasecmp(s,"ontimeout",9) == 0)) return RES_ONTIMEOUT;
00068   if((l == 7) && (strncasecmp(s,"timeout",7) == 0)) return RES_TIMEOUT;
00069   return RES_UNDEFINED;
00070 }
00071 
00072 bool ContinuationPlugins::add(job_state_t state,const char* options,const char* command) {
00073   if((state == JOB_STATE_ACCEPTED) ||
00074      (state == JOB_STATE_PREPARING) ||
00075      (state == JOB_STATE_SUBMITTING) ||
00076      (state == JOB_STATE_FINISHING) ||
00077      (state == JOB_STATE_FINISHED) ||
00078      (state == JOB_STATE_DELETED)) {
00079   } else { return false; };
00080   // go through options separated by ','
00081   action_t onsuccess = act_pass;
00082   action_t onfailure = act_fail;
00083   action_t ontimeout = act_fail;
00084   unsigned int to = 0;
00085   const char *opt_p = options;
00086   for(;*opt_p;) {
00087     const char *next_opt_p = strchr(opt_p,',');
00088     if(next_opt_p == NULL) next_opt_p=opt_p+strlen(opt_p);
00089     const char *val_p = strchr(opt_p,'=');
00090     unsigned int name_len;
00091     unsigned int val_len;
00092     if((val_p == NULL) || (val_p >= next_opt_p)) {
00093       name_len = next_opt_p-opt_p;
00094       val_p=next_opt_p;
00095       val_len=0;
00096     } else {
00097       name_len = val_p-opt_p;
00098       val_p++;
00099       val_len=next_opt_p-val_p;
00100     };
00101     action_t act = act_undefined;
00102     int res = get_result(opt_p,name_len);
00103     if(res == RES_UNDEFINED) { // can be timeout
00104       if(val_len != 0) return false;
00105       res=RES_TIMEOUT;
00106       val_p=opt_p;
00107       val_len=next_opt_p-val_p;
00108     };
00109     if(res != RES_TIMEOUT) {
00110       act=get_action(val_p,val_len);
00111       if(act == act_undefined) return false;
00112     };
00113     switch(res) {
00114       case RES_ONSUCCESS: onsuccess=act; break;
00115       case RES_ONFAILURE: onfailure=act; break;
00116       case RES_ONTIMEOUT: ontimeout=act; break;
00117       case RES_TIMEOUT: {
00118         if(val_len > 0) {
00119           char* e;
00120           to=strtoul(val_p,&e,0);
00121           if(e != next_opt_p) return false;
00122         } else { to=0; };
00123       }; break;
00124       default: return false;
00125     };
00126     opt_p=next_opt_p; if(!(*opt_p)) break;
00127     opt_p++;
00128   };
00129   command_t cmd;
00130   cmd.cmd=command;
00131   cmd.to=to;
00132   cmd.onsuccess=onsuccess;
00133   cmd.onfailure=onfailure;
00134   cmd.ontimeout=ontimeout;
00135   commands[state].push_back(cmd);
00136   return true;
00137 }
00138 
00139 bool ContinuationPlugins::add(const char* state,const char* options,const char* command) {
00140   job_state_t i = JobDescription::get_state(state);
00141   if(i != JOB_STATE_UNDEFINED) {
00142     return add(i,options,command);
00143   };
00144   return false;
00145 }
00146 
00147 void ContinuationPlugins::run(const JobDescription &job,const JobUser& user,std::list<result_t>& results) {
00148   job_state_t state = job.get_state();
00149   for(std::list<command_t>::iterator command = commands[state].begin();
00150                      command != commands[state].end();++command) {
00151     action_t act = act_pass;
00152     if(command->cmd.length() == 0) {
00153       results.push_back(result_t(act_pass));
00154       continue;
00155     };
00156     std::string cmd = command->cmd;
00157     for(std::string::size_type p = 0;;) {
00158       p=cmd.find('%',p);
00159       if(p==std::string::npos) break;
00160       if(cmd[p+1]=='I') {
00161         cmd.replace(p,2,job.get_id().c_str());
00162         p+=job.get_id().length();
00163       } else if(cmd[p+1]=='S') {
00164         cmd.replace(p,2,job.get_state_name());
00165         p+=strlen(job.get_state_name());
00166       } else {
00167         p+=2;
00168       };
00169     };
00170     if(!user.substitute(cmd)) {
00171       results.push_back(result_t(act_undefined));
00172       continue; // or break ?
00173     };
00174     std::string res_out("");
00175     std::string res_err("");
00176     int to = command->to;
00177     int result = -1;
00178 
00179     Arc::Run re(cmd);
00180     re.AssignStdout(res_out);
00181     re.AssignStderr(res_err);
00182     re.KeepStdin();
00183     std::string response;
00184     if(re.Start()) {
00185       if(!re.Wait(to)) {
00186         response="TIMEOUT";
00187         act=command->ontimeout;
00188       } else {
00189         result=re.Result();
00190         if(result == 0) {
00191           act=command->onsuccess;
00192         } else {
00193           response="FAILED";
00194           act=command->onfailure;
00195         };
00196       };
00197     } else {
00198       response="FAILED to start plugin";
00199       // act=command->onfailure; ?? 
00200       act=act_undefined;
00201     };
00202     if(!res_out.empty()) {
00203       if(!response.empty()) response+=" : ";
00204       response+=res_out;
00205     };
00206     if(!res_err.empty()) {
00207       if(!response.empty()) response+=" : ";
00208       response+=res_err;
00209     };
00210     results.push_back(result_t(act,result,response));
00211     if(act == act_fail) break;
00212   };
00213 }
00214