Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes
ARex::ARexJob Class Reference

This class represents convenience interface to manage jobs handled by Grid Manager. More...

#include <job.h>

Collaboration diagram for ARex::ARexJob:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 ARexJob (const std::string &id, ARexGMConfig &config, Arc::Logger &logger, bool fast_auth_check=false)
 Create instance which is an interface to existing job.
 ARexJob (Arc::XMLNode jsdl, ARexGMConfig &config, const std::string &credentials, const std::string &clientid, Arc::Logger &logger, Arc::XMLNode migration=Arc::XMLNode())
 Create new job with provided JSDL description.
 operator bool (void)
bool operator! (void)
std::string Failure (void)
 Returns textual description of failure of last operation.
 operator ARexJobFailure (void)
std::string ID (void)
 Return ID assigned to job.
bool GetDescription (Arc::XMLNode &jsdl)
 Fills provided jsdl with job description.
bool Cancel (void)
 Cancel processing/execution of job.
bool Clean (void)
 Remove job from local pool.
bool Resume (void)
 Resume execution of job after error.
std::string State (void)
 Returns current state of job.
std::string State (bool &job_pending)
 Returns current state of job and sets job_pending to true if job is pending due to external limits.
bool Failed (void)
 Returns true if job has failed.
std::string SessionDir (void)
 Returns path to session directory.
std::string LogDir (void)
 Returns name of virtual log directory.
int CreateFile (const std::string &filename)
 Creates file in job's session directory and returns handler.
int OpenFile (const std::string &filename, bool for_read, bool for_write)
 Opens file in job's session directory and returns handler.
std::string GetFilePath (const std::string &filename)
int OpenLogFile (const std::string &name)
 Opens log file in control directory.
std::string GetLogFilePath (const std::string &name)
Glib::Dir * OpenDir (const std::string &dirname)
 Opens directory inside session directory.
std::list< std::string > LogFiles (void)
 Returns list of existing log files.
bool UpdateCredentials (const std::string &credentials)
 Updates job credentials.
bool ChooseSessionDir (const std::string &jobid, std::string &sessiondir)
 Select a session dir to use for this job.

Static Public Member Functions

static int TotalJobs (ARexGMConfig &config, Arc::Logger &logger)
 Return number of jobs associated with this configuration.
static std::list< std::string > Jobs (ARexGMConfig &config, Arc::Logger &logger)
 Returns list of user's jobs.

Private Member Functions

bool is_allowed (bool fast=false)
 Returns true if job exists and authorization was checked without errors.
bool make_job_id (void)
bool delete_job_id (void)
bool update_credentials (const std::string &credentials)

Private Attributes

std::string id_
std::string failure_
ARexJobFailure failure_type_
bool allowed_to_see_
bool allowed_to_maintain_
Arc::Loggerlogger_
ARexGMConfigconfig_
JobLocalDescription job_

Detailed Description

This class represents convenience interface to manage jobs handled by Grid Manager.

It works mostly through corresponding classes and functions of Grid Manager.

Definition at line 59 of file job.h.


Constructor & Destructor Documentation

ARexJob::ARexJob ( const std::string &  id,
ARexGMConfig config,
Arc::Logger logger,
bool  fast_auth_check = false 
)

Create instance which is an interface to existing job.

Definition at line 280 of file job.cpp.

                                                                                               :id_(id),logger_(logger),config_(config) {
  if(id_.empty()) return;
  if(!config_) { id_.clear(); return; };
  // Reading essential information about job
  if(!job_local_read_file(id_,*config_.User(),job_)) { id_.clear(); return; };
  // Checking if user is allowed to do anything with that job
  if(!is_allowed(fast_auth_check)) { id_.clear(); return; };
  if(!(allowed_to_see_ || allowed_to_maintain_)) { id_.clear(); return; };
}

Here is the call graph for this function:

ARexJob::ARexJob ( Arc::XMLNode  jsdl,
ARexGMConfig config,
const std::string &  credentials,
const std::string &  clientid,
Arc::Logger logger,
Arc::XMLNode  migration = Arc::XMLNode() 
)

Create new job with provided JSDL description.

Definition at line 290 of file job.cpp.

                                                                                                                                                    :id_(""),logger_(logger),config_(config) {
  if(!config_) return;
  // New job is created here
  // First get and acquire new id
  if(!make_job_id()) return;
  // Turn JSDL into text
  std::string job_desc_str;
  // Make full XML doc out of subtree
  {
    Arc::XMLNode jsdldoc;
    jsdl.New(jsdldoc);
    jsdldoc.GetDoc(job_desc_str);
  };
  // Store description
  std::string fname = config_.User()->ControlDir() + "/job." + id_ + ".description";
  if(!job_description_write_file(fname,job_desc_str)) {
    delete_job_id();
    failure_="Failed to store job RSL description";
    failure_type_=ARexJobInternalError;
    return;
  };
  // Analyze JSDL (checking, substituting, etc)
  std::string acl("");
  if((failure_type_=setfail(parse_job_req(fname.c_str(),job_,&acl))) != ARexJobNoError) {
    if(failure_.empty()) {
      failure_="Failed to parse job/action description";
      failure_type_=ARexJobInternalError;
    };
    delete_job_id();
    return;
  };
  // Check for proper LRMS name in request. If there is no LRMS name
  // in user configuration that means service is opaque frontend and
  // accepts any LRMS in request.
  if((!job_.lrms.empty()) && (!config_.User()->DefaultLRMS().empty())) {
    if(job_.lrms != config_.User()->DefaultLRMS()) {
      failure_="Requested LRMS is not supported by this service";
      failure_type_=ARexJobInternalError;
      //failure_type_=ARexJobDescriptionLogicalError;
      delete_job_id();
      return;
    };
  };
  if(job_.lrms.empty()) job_.lrms=config_.User()->DefaultLRMS();
  // Check for proper queue in request.
  if(job_.queue.empty()) job_.queue=config_.User()->DefaultQueue();
  if(job_.queue.empty()) {
    failure_="Request has no queue defined";
    failure_type_=ARexJobDescriptionMissingError;
    delete_job_id();
    return;
  };
  if(config_.Queues().size() > 0) { // If no queues configured - service takes any
    for(std::list<std::string>::const_iterator q = config_.Queues().begin();;++q) {
      if(q == config_.Queues().end()) {
        failure_="Requested queue "+job_.queue+" does not match any of available queues";
        //failure_type_=ARexJobDescriptionLogicalError;
        failure_type_=ARexJobInternalError;
        delete_job_id();
        return;
      };
      if(*q == job_.queue) break;
    };
  };
  // Start local file 
  /* !!!!! some parameters are unchecked here - rerun,diskspace !!!!! */
  job_.jobid=id_;
  job_.starttime=Arc::Time();
  job_.DN=config_.GridName();
  job_.clientname=clientid;
  job_.migrateactivityid=(std::string)migration["ActivityIdentifier"];
  job_.forcemigration=(migration["ForceMigration"]=="true");
  // BES ActivityIdentifier is global job ID
  Arc::NS ns_;
  ns_["bes-factory"]="http://schemas.ggf.org/bes/2006/08/bes-factory";
  ns_["a-rex"]="http://www.nordugrid.org/schemas/a-rex";
  Arc::XMLNode node_(ns_,"bes-factory:ActivityIdentifier");
  Arc::WSAEndpointReference identifier(node_);
  identifier.Address(config.Endpoint()); // address of service
  identifier.ReferenceParameters().NewChild("a-rex:JobID")=id_;
  identifier.ReferenceParameters().NewChild("a-rex:JobSessionDir")=config.Endpoint()+"/"+id_;
  std::string globalid;
  ((Arc::XMLNode)identifier).GetDoc(globalid);
  std::string::size_type nlp;
  while ((nlp=globalid.find('\n')) != std::string::npos)
    globalid.replace(nlp,1," "); // squeeze into 1 line
  job_.globalid=globalid;
  // Try to create proxy
  if(!update_credentials(credentials)) {
    failure_="Failed to store credentials";
    failure_type_=ARexJobInternalError;
    delete_job_id();
    return;
  };
  // Choose session directory
  std::string sessiondir;
  if (!ChooseSessionDir(id_, sessiondir)) {
    delete_job_id();
    failure_="Failed to find valid session directory";
    failure_type_=ARexJobInternalError;
    return;
  };
  config_.User()->SetSessionRoot(sessiondir);
  // Write local file
  JobDescription job(id_,config_.User()->SessionRoot()+"/"+id_,JOB_STATE_ACCEPTED);
  job.set_local(&job_); // need this for write_grami
  if(!job_local_write_file(job,*config_.User(),job_)) {
    delete_job_id();
    failure_="Failed to create job description";
    failure_type_=ARexJobInternalError;
    return;
  };
  // Write grami file
  Arc::JobDescription desc;
  desc.AddHint("SOURCEDIALECT","GRIDMANAGER");
  desc.Parse(job_desc_str);
  if(!write_grami(desc,job,*config_.User(),NULL)) {
    delete_job_id();
    failure_="Failed to create grami file";
    failure_type_=ARexJobInternalError;
    return;
  };
  // Write ACL file
  if(!acl.empty()) {
    if(!job_acl_write_file(id_,*config.User(),acl)) {
      delete_job_id();
      failure_="Failed to process/store job ACL";
      failure_type_=ARexJobInternalError;
      return;
    };
  };
  // Call authentication/authorization plugin/exec
  {
    // talk to external plugin to ask if we can proceed
    std::list<ContinuationPlugins::result_t> results;
    config_.Plugins().run(job,*config_.User(),results);
    std::list<ContinuationPlugins::result_t>::iterator result = results.begin();
    while(result != results.end()) {
      // analyze results
      if(result->action == ContinuationPlugins::act_fail) {
        delete_job_id();
        failure_="Job is not allowed by external plugin: "+result->response;
        failure_type_=ARexJobInternalError;
        return;
      } else if(result->action == ContinuationPlugins::act_log) {
        // Scream but go ahead
        logger_.msg(Arc::WARNING, "Failed to run external plugin: %s", result->response);
      } else if(result->action == ContinuationPlugins::act_pass) {
        // Just continue
        if(result->response.length()) {
          logger_.msg(Arc::INFO, "Plugin response: %s", result->response);
        };
      } else {
        delete_job_id();
        failure_="Failed to pass external plugin: "+result->response;
        failure_type_=ARexJobInternalError;
        return;
      };
      ++result;
    };
  };
/*@
  // Make access to filesystem on behalf of local user
  if(cred_plugin && (*cred_plugin)) {
    job_subst_t subst_arg;
    subst_arg.user=user;
    subst_arg.job=&job_id;
    subst_arg.reason="new";
    // run external plugin to acquire non-unix local credentials
    if(!cred_plugin->run(job_subst,&subst_arg)) {
      olog << "Failed to run plugin" << std::endl;
      delete_job_id();
      failure_type_=ARexJobInternalError;
      error_description="Failed to obtain external credentials";
      return 1;
    };
    if(cred_plugin->result() != 0) {
      olog << "Plugin failed: " << cred_plugin->result() << std::endl;
      delete_job_id();
      error_description="Failed to obtain external credentials";
      failure_type_=ARexJobInternalError;
      return 1;
    };
  };
*/
  // Create session directory
  if(!job_session_create(job,*config_.User())) {
    delete_job_id();
    failure_="Failed to create session directory";
    failure_type_=ARexJobInternalError;
    return;
  };
  // Create status file (do it last so GM picks job up here)
  if(!job_state_write_file(job,*config_.User(),JOB_STATE_ACCEPTED)) {
    delete_job_id();
    failure_="Failed registering job in grid-manager";
    failure_type_=ARexJobInternalError;
    return;
  };
  SignalFIFO(*config_.User());
  return;
}

Here is the call graph for this function:


Member Function Documentation

bool ARexJob::Cancel ( void  )

Cancel processing/execution of job.

Definition at line 503 of file job.cpp.

                         {
  if(id_.empty()) return false;
  JobDescription job_desc(id_,"");
  if(!job_cancel_mark_put(job_desc,*config_.User())) return false;
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool ARexJob::ChooseSessionDir ( const std::string &  jobid,
std::string &  sessiondir 
)

Select a session dir to use for this job.

Definition at line 781 of file job.cpp.

                                                                            {
  if (config_.SessionRootsNonDraining().size() == 0) {
    // no active session dirs available
    logger_.msg(Arc::ERROR, "No non-draining session dirs available");
    return false;
  }
  // choose randomly from non-draining session dirs
  sessiondir = config_.SessionRootsNonDraining().at(rand() % config_.SessionRootsNonDraining().size());
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool ARexJob::Clean ( void  )

Remove job from local pool.

Definition at line 510 of file job.cpp.

                        {
  if(id_.empty()) return false;
  JobDescription job_desc(id_,"");
  if(!job_clean_mark_put(job_desc,*config_.User())) return false;
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ARexJob::CreateFile ( const std::string &  filename)

Creates file in job's session directory and returns handler.

Definition at line 692 of file job.cpp.

                                                 {
  if(id_.empty()) return -1;
  std::string fname = filename;
  if((!normalize_filename(fname)) || (fname.empty())) {
    failure_="File name is not acceptable";
    failure_type_=ARexJobInternalError;
    return -1;
  };
  int lname = fname.length();
  fname = config_.User()->SessionRoot(id_)+"/"+id_+"/"+fname;
  // First try to create/open file
  int h = Arc::FileOpen(fname.c_str(),O_WRONLY | O_CREAT,config_.User()->get_uid(),config_.User()->get_gid(),S_IRUSR | S_IWUSR);
  if(h != -1) return h;
  if(errno != ENOENT) return -1;
  // If open reports missing directory - try to create all sudirectories
  std::string::size_type n = fname.length()-lname;
  for(;;) {
    n=fname.find('/',n);
    if(n == std::string::npos) break;
    std::string dname = fname.substr(0,n);
    ++n;
    if(Arc::DirCreate(dname.c_str(),config_.User()->get_uid(),config_.User()->get_gid(),S_IRUSR | S_IWUSR | S_IXUSR)) continue;
    if(errno == EEXIST) continue;
  };
  return Arc::FileOpen(fname.c_str(),O_WRONLY | O_CREAT,config_.User()->get_uid(),config_.User()->get_gid(),S_IRUSR | S_IWUSR);
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool ARexJob::delete_job_id ( void  ) [private]

Definition at line 629 of file job.cpp.

                                {
  if(!config_) return true;
  if(!id_.empty()) {
    job_clean_final(JobDescription(id_,
                config_.User()->SessionRoot(id_)+"/"+id_),*config_.User());
    id_="";
  };
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool ARexJob::Failed ( void  )

Returns true if job has failed.

Definition at line 546 of file job.cpp.

                         {
  if(id_.empty()) return false;
  return job_failed_mark_check(id_,*config_.User());
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string ARex::ARexJob::Failure ( void  ) [inline]

Returns textual description of failure of last operation.

Definition at line 84 of file job.h.

Here is the caller graph for this function:

Fills provided jsdl with job description.

Definition at line 493 of file job.cpp.

                                             {
  if(id_.empty()) return false;
  std::string sdesc;
  if(!job_description_read_file(id_,*config_.User(),sdesc)) return false;
  Arc::XMLNode xdesc(sdesc);
  if(!xdesc) return false;
  jsdl.Replace(xdesc);
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string ARexJob::GetFilePath ( const std::string &  filename)

Definition at line 768 of file job.cpp.

                                                        {
  if(id_.empty()) return "";
  std::string fname = filename;
  if(!normalize_filename(fname)) return "";
  if(fname.empty()) config_.User()->SessionRoot(id_)+"/"+id_;
  return config_.User()->SessionRoot(id_)+"/"+id_+"/"+fname;
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string ARexJob::GetLogFilePath ( const std::string &  name)

Definition at line 776 of file job.cpp.

                                                       {
  if(id_.empty()) return "";
  return config_.User()->ControlDir() + "/job." + id_ + "." + name;
}

Here is the call graph for this function:

std::string ARex::ARexJob::ID ( void  ) [inline]

Return ID assigned to job.

Definition at line 87 of file job.h.

{ return id_; };

Here is the caller graph for this function:

bool ARexJob::is_allowed ( bool  fast = false) [private]

Returns true if job exists and authorization was checked without errors.

Fills information about authorization in this instance.

Definition at line 146 of file job.cpp.

                                  {
  allowed_to_see_=false;
  allowed_to_maintain_=false;
  // Checking user's grid name against owner
  if(config_.GridName() == job_.DN) {
    allowed_to_see_=true;
    allowed_to_maintain_=true;
    return true;
  };
  if(fast) return true;
  // Do fine-grained authorization requested by job's owner
  if(config_.beginAuth() == config_.endAuth()) return true;
  std::string acl;
  if(!job_acl_read_file(id_,*config_.User(),acl)) return true; // safe to ignore
  if(acl.empty()) return true; // No policy defiled - only owner allowed
  // Identify and parse policy
  ArcSec::EvaluatorLoader eval_loader;
  AutoPointer<ArcSec::Policy> policy(eval_loader.getPolicy(ArcSec::Source(acl)));
  if(!policy) {
    logger_.msg(Arc::VERBOSE, "%s: Failed to parse user policy", id_);
    return true;
  };
  AutoPointer<ArcSec::Evaluator> eval(eval_loader.getEvaluator(policy));
  if(!eval) {
    logger_.msg(Arc::VERBOSE, "%s: Failed to load evaluator for user policy ", id_);
    return true;
  };
  std::string policyname = policy->getName();
  if((policyname.length() > 7) && 
     (policyname.substr(policyname.length()-7) == ".policy")) {
    policyname.resize(policyname.length()-7);
  };
  if(policyname == "arc") {
    // Creating request - directly with XML
    // Creating top of request document
    Arc::NS ns;
    ns["ra"]="http://www.nordugrid.org/schemas/request-arc";
    Arc::XMLNode request(ns,"ra:Request");
    // Collect all security attributes
    for(std::list<Arc::MessageAuth*>::iterator a = config_.beginAuth();a!=config_.endAuth();++a) {
      if(*a) (*a)->Export(Arc::SecAttr::ARCAuth,request);
    };
    // Leave only client identities
    for(Arc::XMLNode item = request["RequestItem"];(bool)item;++item) {
      for(Arc::XMLNode a = item["Action"];(bool)a;a=item["Action"]) a.Destroy();
      for(Arc::XMLNode r = item["Resource"];(bool)r;r=item["Resource"]) r.Destroy();
    };
    // Fix namespace
    request.Namespaces(ns);
    // Create A-Rex specific action
    // TODO: make helper classes for such operations
    Arc::XMLNode item = request["ra:RequestItem"];
    if(!item) item=request.NewChild("ra:RequestItem");
    // Possible operations are Modify and Read
    Arc::XMLNode action;
    action=item.NewChild("ra:Action");
    action="Read"; action.NewAttribute("Type")="string";
    action.NewAttribute("AttributeId")=JOB_POLICY_OPERATION_URN;
    action=item.NewChild("ra:Action");
    action="Modify"; action.NewAttribute("Type")="string";
    action.NewAttribute("AttributeId")=JOB_POLICY_OPERATION_URN;
    // Evaluating policy
    ArcSec::Response *resp = eval->evaluate(request,policy);
    // Analyzing response in order to understand which operations are allowed
    if(!resp) return true; // Not authorized
    // Following should be somehow made easier
    ArcSec::ResponseList& rlist = resp->getResponseItems();
    for(int n = 0; n<rlist.size(); ++n) {
      ArcSec::ResponseItem* ritem = rlist[n];
      if(!ritem) continue;
      if(ritem->res != ArcSec::DECISION_PERMIT) continue;
      if(!(ritem->reqtp)) continue;
      for(ArcSec::Action::iterator a = ritem->reqtp->act.begin();a!=ritem->reqtp->act.end();++a) {
        ArcSec::RequestAttribute* attr = *a;
        if(!attr) continue;
        ArcSec::AttributeValue* value = attr->getAttributeValue();
        if(!value) continue;
        std::string action = value->encode();
        if(action == "Read") allowed_to_see_=true;
        if(action == "Modify") allowed_to_maintain_=true;
      };
    };
  } else if(policyname == "gacl") {
    // Creating request - directly with XML
    Arc::NS ns;
    Arc::XMLNode request(ns,"gacl");
    // Collect all security attributes
    for(std::list<Arc::MessageAuth*>::iterator a = config_.beginAuth();a!=config_.endAuth();++a) {
      if(*a) (*a)->Export(Arc::SecAttr::GACL,request);
    };
    // Leave only client identities
    int entries = 0;
    for(Arc::XMLNode entry = request["entry"];(bool)entry;++entry) {
      for(Arc::XMLNode a = entry["allow"];(bool)a;a=entry["allow"]) a.Destroy();
      for(Arc::XMLNode a = entry["deny"];(bool)a;a=entry["deny"]) a.Destroy();
      ++entries;
    };
    if(!entries) request.NewChild("entry");
    // Evaluate every action separately
    for(Arc::XMLNode entry = request["entry"];(bool)entry;++entry) {
      entry.NewChild("allow").NewChild("read");
    };
    ArcSec::Response *resp;
    resp=eval->evaluate(request,policy);
    if(resp) {
      ArcSec::ResponseList& rlist = resp->getResponseItems();
      for(int n = 0; n<rlist.size(); ++n) {
        ArcSec::ResponseItem* ritem = rlist[n];
        if(!ritem) continue;
        if(ritem->res != ArcSec::DECISION_PERMIT) continue;
        allowed_to_see_=true; break;
      };
    };
    for(Arc::XMLNode entry = request["entry"];(bool)entry;++entry) {
      entry["allow"].Destroy();
      entry.NewChild("allow").NewChild("write");
    };
    resp=eval->evaluate(request,policy);
    if(resp) {
      ArcSec::ResponseList& rlist = resp->getResponseItems();
      for(int n = 0; n<rlist.size(); ++n) {
        ArcSec::ResponseItem* ritem = rlist[n];
        if(!ritem) continue;
        if(ritem->res != ArcSec::DECISION_PERMIT) continue;
        allowed_to_maintain_=true; break;
      };
    };
    // TODO: <list/>, <admin/>
  } else {
    logger_.msg(Arc::VERBOSE, "%s: Unknown user policy '%s'", id_, policyname);
  };
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::list< std::string > ARexJob::Jobs ( ARexGMConfig config,
Arc::Logger logger 
) [static]

Returns list of user's jobs.

Fine-grained ACL is ignored.

Definition at line 646 of file job.cpp.

                                                                       {
  std::list<std::string> jlist;
  ContinuationPlugins plugins;
  JobsList jobs(*config.User(),plugins);
  jobs.ScanNewJobs();
  JobsList::iterator i = jobs.begin();
  for(;i!=jobs.end();++i) {
    ARexJob job(i->get_id(),config,logger,true);
    if(job) jlist.push_back(i->get_id());
  };
  return jlist;
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string ARexJob::LogDir ( void  )

Returns name of virtual log directory.

Definition at line 664 of file job.cpp.

                              {
  return job_.stdlog;
}

Here is the caller graph for this function:

std::list< std::string > ARexJob::LogFiles ( void  )

Returns list of existing log files.

Definition at line 752 of file job.cpp.

                                         {
  std::list<std::string> logs;
  if(id_.empty()) return logs;
  std::string dname = config_.User()->ControlDir();
  std::string prefix = "job." + id_ + ".";
  Glib::Dir* dir = Arc::DirOpen(dname.c_str(),config_.User()->get_uid(),config_.User()->get_gid());
  if(!dir) return logs;
  for(;;) {
    std::string name = dir->read_name();
    if(name.empty()) break;
    if(strncmp(prefix.c_str(),name.c_str(),prefix.length()) != 0) continue;
    logs.push_back(name.substr(prefix.length())); 
  };
  return logs;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool ARexJob::make_job_id ( void  ) [private]

Definition at line 599 of file job.cpp.

                              {
  if(!config_) return false;
  int i;
  //@ delete_job_id();
  for(i=0;i<100;i++) {
    id_=Arc::tostring((unsigned int)getpid())+
        Arc::tostring((unsigned int)time(NULL))+
        Arc::tostring(rand(),1);
    std::string fname=config_.User()->ControlDir()+"/job."+id_+".description";
    struct stat st;
    if(stat(fname.c_str(),&st) == 0) continue;
    int h = ::open(fname.c_str(),O_RDWR | O_CREAT | O_EXCL,0600);
    // So far assume control directory is on local fs.
    // TODO: add locks or links for NFS
    int err = errno;
    if(h == -1) {
      if(err == EEXIST) continue;
      logger_.msg(Arc::ERROR, "Failed to create file in %s", config_.User()->ControlDir());
      id_="";
      return false;
    };
    fix_file_owner(fname,*config_.User());
    close(h);
    return true;
  };
  logger_.msg(Arc::ERROR, "Out of tries while allocating new job id in %s", config_.User()->ControlDir());
  id_="";
  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Glib::Dir * ARexJob::OpenDir ( const std::string &  dirname)

Opens directory inside session directory.

Definition at line 735 of file job.cpp.

                                                  {
  if(id_.empty()) return NULL;
  std::string dname = dirname;
  if(!normalize_filename(dname)) return NULL;
  //if(dname.empty()) return NULL;
  dname = config_.User()->SessionRoot(id_)+"/"+id_+"/"+dname;
  Glib::Dir* dir = Arc::DirOpen(dname.c_str(),config_.User()->get_uid(),config_.User()->get_gid());
  return dir;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ARexJob::OpenFile ( const std::string &  filename,
bool  for_read,
bool  for_write 
)

Opens file in job's session directory and returns handler.

Definition at line 719 of file job.cpp.

                                                                            {
  if(id_.empty()) return -1;
  std::string fname = filename;
  if((!normalize_filename(fname)) || (fname.empty())) {
    failure_="File name is not acceptable";
    failure_type_=ARexJobInternalError;
    return -1;
  };
  fname = config_.User()->SessionRoot(id_)+"/"+id_+"/"+fname;
  int flags = 0;
  if(for_read && for_write) { flags=O_RDWR; }
  else if(for_read) { flags=O_RDONLY; }
  else if(for_write) { flags=O_WRONLY; }
  return Arc::FileOpen(fname.c_str(),flags,config_.User()->get_uid(),config_.User()->get_gid(),0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ARexJob::OpenLogFile ( const std::string &  name)

Opens log file in control directory.

Definition at line 745 of file job.cpp.

                                              {
  if(id_.empty()) return -1;
  if(strchr(name.c_str(),'/')) return -1;
  std::string fname = config_.User()->ControlDir() + "/job." + id_ + "." + name;
  return Arc::FileOpen(fname.c_str(),O_RDONLY,0,0,0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

ARex::ARexJob::operator ARexJobFailure ( void  ) [inline]

Definition at line 85 of file job.h.

{ return failure_type_; };
ARex::ARexJob::operator bool ( void  ) [inline]

Definition at line 81 of file job.h.

{ return !id_.empty(); };
bool ARex::ARexJob::operator! ( void  ) [inline]

Definition at line 82 of file job.h.

{ return id_.empty(); };
bool ARexJob::Resume ( void  )

Resume execution of job after error.

Definition at line 517 of file job.cpp.

                         {
  if(id_.empty()) return false;
  if(job_.failedstate.length() == 0) {
    // Job can't be restarted.
    return false;
  };
  if(job_.reruns <= 0) {
    // Job run out of number of allowed retries.
    return false;
  };
  if(!job_restart_mark_put(JobDescription(id_,""),*config_.User())) {
    // Failed to report restart request.
    return false;
  };
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string ARexJob::SessionDir ( void  )

Returns path to session directory.

Definition at line 659 of file job.cpp.

                                  {
  if(id_.empty()) return "";
  return config_.User()->SessionRoot(id_)+"/"+id_;
}

Here is the call graph for this function:

std::string ARexJob::State ( void  )

Returns current state of job.

Definition at line 534 of file job.cpp.

                             {
  bool job_pending;
  return State(job_pending);
}

Here is the caller graph for this function:

std::string ARexJob::State ( bool &  job_pending)

Returns current state of job and sets job_pending to true if job is pending due to external limits.

Definition at line 539 of file job.cpp.

                                          {
  if(id_.empty()) return "";
  job_state_t state = job_state_read_file(id_,*config_.User(),job_pending);
  if(state > JOB_STATE_UNDEFINED) state=JOB_STATE_UNDEFINED;
  return states_all[state].name;
}

Here is the call graph for this function:

int ARexJob::TotalJobs ( ARexGMConfig config,
Arc::Logger logger 
) [static]

Return number of jobs associated with this configuration.

TODO: total for all user configurations.

Definition at line 639 of file job.cpp.

                                                             {
  ContinuationPlugins plugins;
  JobsList jobs(*config.User(),plugins);
  jobs.ScanNewJobs();
  return jobs.size();
}

Here is the call graph for this function:

bool ARexJob::update_credentials ( const std::string &  credentials) [private]

Definition at line 559 of file job.cpp.

                                                             {
  if(credentials.empty()) return true;
  std::string fname=config_.User()->ControlDir()+"/job."+id_+".proxy";
  ::unlink(fname.c_str());
  int h=::open(fname.c_str(),O_WRONLY | O_CREAT | O_EXCL,0600);
  if(h == -1) return false;
  fix_file_owner(fname,*config_.User());
  const char* s = credentials.c_str();
  int ll = credentials.length();
  int l = 0;
  for(;(ll>0) && (l!=-1);s+=l,ll-=l) l=::write(h,s,ll);
  ::close(h);
  if(l==-1) return false;
  job_.expiretime = Arc::Credential(fname,"","","").GetEndTime();
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool ARexJob::UpdateCredentials ( const std::string &  credentials)

Updates job credentials.

Definition at line 551 of file job.cpp.

                                                            {
  if(id_.empty()) return false;
  if(!update_credentials(credentials)) return false;
  JobDescription job(id_,config_.User()->SessionRoot(id_)+"/"+id_,JOB_STATE_ACCEPTED);
  if(!job_local_write_file(job,*config_.User(),job_)) return false;
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 65 of file job.h.

Definition at line 64 of file job.h.

Definition at line 71 of file job.h.

std::string ARex::ARexJob::failure_ [private]

Definition at line 62 of file job.h.

Definition at line 63 of file job.h.

std::string ARex::ARexJob::id_ [private]

Definition at line 61 of file job.h.

Definition at line 72 of file job.h.

Definition at line 66 of file job.h.


The documentation for this class was generated from the following files: