KaliVeda
Toolkit for HIC analysis
KVBatchSystem.cpp
1 /*
2 $Id: KVBatchSystem.cpp,v 1.12 2008/04/14 08:49:11 franklan Exp $
3 $Revision: 1.12 $
4 $Date: 2008/04/14 08:49:11 $
5 */
6 
7 //Created by KVClassFactory on Thu Apr 13 13:07:59 2006
8 //Author: John Frankland
9 
10 #include "KVBatchSystem.h"
11 #include "KVBase.h"
12 #include "TEnv.h"
13 #include "TPluginManager.h"
14 #include "TSystem.h"
15 #include "KVDataAnalyser.h"
16 #include "KVDataAnalysisTask.h"
17 
18 using namespace std;
19 
21 
22 KVBatchSystem* gBatchSystem = 0;
23 
24 
35 
37  : KVBase(name), fAnalyser(nullptr)
38 {
39  // Constructor with name of batch system. Name will be used to retrieve
40  // resources from configuration file, e.g. batch system title, job submission
41  // command, name of batch script, default job options, runs per job in multijob mode:
42  //
43  // [batch system name].BatchSystem.Title:
44  // [batch system name].BatchSystem.JobSubCmd:
45  // [batch system name].BatchSystem.JobScript:
46  // [batch system name].BatchSystem.DefaultJobOptions:
47 
48  //set title of batch system
49  SetTitle(gEnv->GetValue(Form("%s.BatchSystem.Title", name), ""));
50  //command for job submission
51  fJobSubCmd = gEnv->GetValue(Form("%s.BatchSystem.JobSubCmd", name), "");
52  //check command is valid
53  if (!KVBase::FindExecutable(fJobSubCmd)) {
54  KVError::Warning(this, "KVBatchSystem", "Batch system %s has unknown job submission command: %s",
55  name, fJobSubCmd.Data());
56  }
57  //script for batch job
58  SetJobScript(gEnv->GetValue(Form("%s.BatchSystem.JobScript", name), ""));
59  //set default job options
60  SetDefaultJobOptions(gEnv->GetValue(Form("%s.BatchSystem.DefaultJobOptions", name), ""));
61 }
62 
63 
64 
67 
69 {
70  //Destructor
71  if (gBatchSystem == this)
72  gBatchSystem = 0;
73 }
74 
75 
76 
105 
107 {
108  //Builds and returns static string containing full command line necessary to submit a batch
109  //job. This is constructed as follows:
110  //
111  // [JobSubCmd] [default options] [par1 val1] [par2 val2] ... [JobScript]
112  //
113  //The 'default options' can be set with SetDefaultJobOptions().
114  //
115  //The 'par1,val1' pairs are the named parameters held in the fParList KVParameterList.
116  //For each parameter in the list, the name of the parameter is used for 'par1' and the value
117  //of the parameter is used for 'val1' etc. etc.
118  //e.g. if the job submission command requires an option to be passed with the following
119  //syntax
120  // [JobSubCmd] -Noption
121  //one of the parameters in the list should be called "-N" and its value should be 'option'
122  //
123  //In order to add a simple flag such as
124  // [JobSubCmd] -V
125  //add a parameter called "-V" with value "".
126  //
127  //The special variable #JobName# can be used anywhere and will be replaced by the
128  //jobname returned by GetJobName() at the moment of job submission.
129  //
130  //The special variable #tmpDIR# can be used anywhere and will be replaced by the
131  //full path to the system temporary directory at the moment of job submission.
132  //
133  //The special variable #launchDIR# can be used anywhere and will be replaced by the
134  //full path to the working directory at the moment of job submission.
135 
136  static TString command_line;
137  command_line.Form("%s %s ", fJobSubCmd.Data(), fDefOpt.Data());
138  if (fParList.GetNpar()) {
139  for (int i = 0; i < fParList.GetNpar(); i++) {
140  KVNamedParameter* par = fParList.GetParameter(i);
141  command_line += par->GetName();
142  if (par->GetTString() != "") {
143  command_line += par->GetString();
144  }
145  command_line += " ";
146  }
147  }
148  command_line += fJobScript;
149  //replace #JobName# with name of current job
150  command_line.ReplaceAll("#JobName#", GetJobName());
151  //replace #tmpDIR# with temporary directory path
152  command_line.ReplaceAll("#tmpDIR#", gSystem->TempDirectory());
153  //replace #launchDIR# with working directory (job submission directory) path
154  command_line.ReplaceAll("#launchDIR#", gSystem->WorkingDirectory());
155  return command_line.Data();
156 }
157 
158 
159 
160 
164 
166 {
167  //Clear previously set parameters in order to create a new job submission command
168  //(default options are not affected: use SetDefaultJobOptions to change them)
169 
170  fJobName = "";
171  fParList.Clear();
172  fAnalyser = nullptr;
173 }
174 
175 
176 
177 
180 
182 {
183  //Make this the default batch system
184  gBatchSystem = this;
185 }
186 
187 
188 
189 
196 
198 {
199  //Submits a job to batch system, i.e. executes the string formed by GetJobSubCmdLine,
200  //if all necessary parameters have been given (any missing ones will be asked for).
201  //Parameters specific to a given batch system can be added my modifying the
202  //CheckJobParameters() method for the associated child class.
203 
204  //set environment variables required by KaliVedaAnalysis batch executable
205  gSystem->Setenv("KVBATCHNAME", GetJobName());
206  gSystem->Setenv("KVLAUNCHDIR", gSystem->WorkingDirectory());
207  cout << GetJobSubCmdLine() << endl;
208  if (fAnalyser) {
209  fAnalyser->WriteBatchEnvFile(GetJobName());
210  gSystem->Setenv("KVANALYSER", fAnalyser->GetAnalyserClassNameForBatchJob());
211  }
213 }
214 
215 
216 
217 
222 
224 {
225  //Processes the job requests for the batch system.
226  //In normal mode, this submits one job for the data analyser fAnalyser
227  //In multijobs mode, this submits one job for each run in the runlist associated to fAnalyser
228 
229  if (!CheckJobParameters()) return;
230 
231  SubmitJob();
232 }
233 
234 
235 
236 
242 
244 {
245  // Create batch system object defined as a plugin in .kvrootrc
246  // If no plugin is found, we create a new KVBatchSystem base object which
247  // will be initialised from resources defined in .kvrootrc using its name.
248 
249  //check and load plugin library
250  TPluginHandler* ph = KVBase::LoadPlugin("KVBatchSystem", plugin);
251  if (!ph)
252  return new KVBatchSystem(plugin);
253 
254  //execute constructor/macro for batch system
255  auto bs = ((KVBatchSystem*) ph->ExecPlugin(1, plugin));
256  if(!bs)
257  {
258  // Just because the plugin is defined doesn't mean that it will work!
259  KVError::Error(KVBatchSystem{""},"GetBatchSystem","Batch system plugin %s: class %s not found, system undefined", plugin, ph->GetClass());
260  }
261  return bs;
262 }
263 
264 
265 
266 
272 
274 {
275  // Submit data analysis task described by KVDataAnalyser object to the batch system.
276  //
277  // Note that the default options for this batch system may be changed just before
278  // job submission depending on the current environment, see ChangeDefJobOpt().
279 
280  Info("SubmitTask", "Task submission for analyser class : %s", da->ClassName());
281  SetAnalyser(da);
282  //change job submission options depending on task, environment, etc.
283  ChangeDefJobOpt(da);
284  Run();
285 }
286 
287 
288 
289 
302 
303 void KVBatchSystem::ChangeDefJobOpt(KVDataAnalyser* da)
304 {
305  // PRIVATE method called by SubmitTask() at moment of job submission.
306  // Depending on the current environment, the default job submission options
307  // may be changed by this method.
308  // For example, default options may be changed depending on the analysis
309  // task to be performed. We look for an environment variable of the form:
310  //
311  // [batch system name].BatchSystem.DefaultJobOptions.[analysis task name]
312  //
313  // and if found we use the options defined by it. If not, we use the default
314  // job options defined by
315  // [batch system name].BatchSystem.DefaultJobOptions
316 
317  TString tmp = gEnv->GetValue(Form("%s.BatchSystem.DefaultJobOptions.%s",
318  GetName(), da->GetAnalysisTask()->GetName()), "");
319  if (tmp.Length()) {
320  Info("ChangeDefJobOpt", "Changing default batch options for task %s.", da->GetAnalysisTask()->GetName());
321  Info("ChangeDefJobOpt", "Batch job options for this job are : %s", tmp.Data());
322  SetDefaultJobOptions(tmp.Data());
323  }
324  else {
325  tmp = gEnv->GetValue(Form("%s.BatchSystem.DefaultJobOptions", GetName()), "");
326  SetDefaultJobOptions(tmp.Data());
327  }
328 }
329 
330 
331 
332 
344 
346 {
347  //Returns name of batch job, either during submission of batch jobs or when an analysis
348  //task is running in batch mode (access through gBatchSystem global pointer).
349  //
350  //In multi-job mode, the job name is generated from the base name set by SetJobName()
351  //plus the extension "_Rxxxx-yyyy" with "xxxx" and "yyyy" the number of the first and last runfile
352  //which will be analysed by the current job.
353  //
354  // Depending on the batch system, some sanitization of the jobname may be required
355  // e.g. to remove "illegal" characters from the jobname. This is done by SanitizeJobName()
356  // before the jobname is returned.
357 
358  if (!fAnalyser) {
359  //stand-alone batch submission ?
360  fCurrJobName = fJobName;
361  }
362  else {
363  //replace any special symbols with their current values
364  fCurrJobName = fAnalyser->ExpandAutoBatchName(fJobName.Data());
365  if (MultiJobsMode() && !fAnalyser->BatchMode()) {
366  KVString tmp;
367  if (fCurrJobRunList.GetNValues() > 1)
368  tmp.Form("_R%s-%s", fCurrJobRunList.First().as_string().Data(),
369  fCurrJobRunList.Last().as_string().Data());
370  else
371  tmp.Form("_R%s", fCurrJobRunList.First().as_string().Data());
372  fCurrJobName += tmp;
373  }
374  }
375  SanitizeJobName();
376  return fCurrJobName.Data();
377 }
378 
379 
380 
381 
384 
386 {
387  // Checks the job and ask for the job name if needed
388  KVString jobName = fJobName;
389  while (!jobName.Length()) {
390  cout << "Please enter the job name : ";
391  cout.flush();
392  jobName.ReadToDelim(cin);
393  if (jobName.Length()) {
394  SetJobName(jobName.Data());
395  }
396  }
397  return kTRUE;
398 }
399 
400 
401 
402 
406 
408 {
409  //Store any useful information on batch system in the TEnv
410  //(this method is used by KVDataAnalyser::WriteBatchEnvFile)
411  env->SetValue("BatchSystem.JobName", GetJobName());
412 }
413 
414 
415 
416 
420 
422 {
423  //Read any useful information on batch system from the TEnv
424  //(this method is used by KVDataAnalyser::ReadBatchEnvFile)
425  fJobName = env->GetValue("BatchSystem.JobName", "");
426 }
427 
428 
429 
430 
434 
435 void KVBatchSystem::Print(Option_t* option) const
436 {
437  //if option="log", print infos for batch log file
438  //if option="all", print detailed info on batch system
439  if (!strcmp(option, "log")) {
440  cout << "Job " << GetJobName()
441  << " executed by batch system " << GetName() << endl;
442  }
443  else if (!strcmp(option, "all")) {
444  cout << ClassName() << " : Name = " << GetName() << endl << " Title = " << GetTitle() << endl;
445  cout << " fJobSubCmd = " << fJobSubCmd.Data() << endl;
446  cout << " fJobScript = " << fJobScript.Data() << endl;
447  cout << " fDefOpt = " << fDefOpt.Data() << endl;
448  fParList.Print(); //list of parameters/switches to be passed on job submission command line
449  }
450  else
452 }
453 
454 
455 
462 
464 {
465  // Create and fill list with KVBatchJob objects, one for each job currently
466  // handled by the batch system.
467  //
468  // Needs to be implemented for specific systems in child classes.
469  // This method returns 0x0.
470  return 0x0;
471 }
472 
473 
474 
483 
485 {
486  // Fill the list with all relevant parameters for batch system,
487  // set to their default values.
488  //
489  // Parameters defined here are:
490  // JobName [string]
491  // AutoJobName [bool]
492  // AutoJobNameFormat [string]
493 
494  nl.Clear();
495  nl.SetTitle(GetTitle());
496  nl.SetValue("JobName", "");
497  nl.SetValue("AutoJobName", kTRUE);
498  nl.SetValue("AutoJobNameFormat", "$UserClass");
499 }
500 
501 
502 
505 
507 {
508  // Use the parameters in the list to set all relevant parameters for batch system.
509 
510  if (nl.GetBoolValue("AutoJobName"))
511  SetJobName(nl.GetStringValue("AutoJobNameFormat"));
512  else
513  SetJobName(nl.GetStringValue("JobName"));
514  Info("SetBatchSystemParameters", "JobName = %s", GetJobName());
515 }
516 
517 
518 
519 
527 
529 {
530  //Set the job name. In MultiJobsMode this will be used as the base name for all jobs;
531  //each individual job will have the name 'basejobname_Rxxxx", with xxxx=run number for job.
532  //
533  //The job name can be generated automatically by replacing certain special symbols
534  //in the name given here depending on the characteristics of the job. See
535  //KVDataAnalyser::ExpandAutoBatchName for allowed symbols.
536  fJobName = name;
537 }
538 
539 
bool Bool_t
char Char_t
constexpr Bool_t kTRUE
const char Option_t
R__EXTERN TEnv * gEnv
Option_t Option_t option
char name[80]
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Base class for KaliVeda framework.
Definition: KVBase.h:140
static Bool_t FindExecutable(TString &exec, const Char_t *path="$(PATH)")
Definition: KVBase.cpp:994
void Print(Option_t *option="") const override
Definition: KVBase.cpp:412
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:795
Base class for interface to a batch job management system.
Definition: KVBatchSystem.h:78
virtual void SubmitTask(KVDataAnalyser *da)
void SetAnalyser(KVDataAnalyser *da)
virtual void WriteBatchEnvFile(TEnv *)
void Clear(Option_t *opt="") override
virtual const Char_t * GetJobSubCmdLine()
virtual void SetJobName(const Char_t *name)
virtual void SetDefaultJobOptions(const Char_t *opt)
virtual Bool_t MultiJobsMode() const
void cd()
Make this the default batch system.
virtual void SubmitJob()
KVBatchSystem(const Char_t *name)
virtual const Char_t * GetJobName() const
virtual void Run()
virtual void SanitizeJobName() const
virtual KVList * GetListOfJobs()
static KVBatchSystem * GetBatchSystem(const Char_t *plugin)
virtual void ReadBatchEnvFile(TEnv *)
virtual void SetBatchSystemParameters(const KVNameValueList &)
Use the parameters in the list to set all relevant parameters for batch system.
virtual void SetJobScript(const Char_t *path)
void Print(Option_t *="") const override
virtual ~KVBatchSystem()
Destructor.
virtual void GetBatchSystemParameterList(KVNameValueList &)
virtual Bool_t CheckJobParameters()
Checks the job and ask for the job name if needed.
Manager class which sets up and runs data analysis tasks.
virtual TString ExpandAutoBatchName(const Char_t *format) const
virtual void WriteBatchEnvFile(const TString &, Bool_t sav=kTRUE)
virtual TString GetAnalyserClassNameForBatchJob()
KVDataAnalysisTask * GetAnalysisTask() const
Bool_t BatchMode() const
Extended TList class which owns its objects by default.
Definition: KVList.h:22
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
KVNamedParameter * GetParameter(Int_t idx) const
return the parameter object with index idx
void SetValue(const Char_t *name, value_type value)
Int_t GetNpar() const
return the number of stored parameters
void Clear(Option_t *opt="") override
Bool_t GetBoolValue(const Char_t *name) const
const Char_t * GetStringValue(const Char_t *name) const
void Print(Option_t *opt="") const override
A generic named parameter storing values of different types.
const Char_t * GetString() const
TString GetTString() const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
virtual const char * GetValue(const char *name, const char *dflt) const
virtual void SetValue(const char *name, const char *value, EEnvLevel level=kEnvChange, const char *type=nullptr)
virtual void SetTitle(const char *title="")
const char * GetName() const override
const char * GetTitle() const override
virtual const char * ClassName() const
virtual void Info(const char *method, const char *msgfmt,...) const
const char * GetClass() const
Longptr_t ExecPlugin(int nargs)
Ssiz_t Length() const
std::istream & ReadToDelim(std::istream &str, char delim='\n')
const char * Data() const
void Form(const char *fmt,...)
TString & ReplaceAll(const char *s1, const char *s2)
virtual Int_t Exec(const char *shellcmd)
virtual const char * WorkingDirectory()
virtual void Setenv(const char *name, const char *value)
virtual const char * TempDirectory() const
Int_t GetNValues() const
const run_index_t & Last() const
const run_index_t & First() const
TString as_string() const
Definition: run_index.h:95
void Error(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:116
void Warning(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:125
ClassImp(TPyArg)