]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/analysis2/trains/TrainSetup.C
Cleaned up error handling when missing corrections. Previously
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / trains / TrainSetup.C
CommitLineData
56199f2b 1/**
bd6f5206 2 * @defgroup pwglf_forward_trains Trains
56199f2b 3 *
e01b1d30 4 * Train specifications
5 *
bd6f5206 6 * @ingroup pwglf_forward
56199f2b 7 */
1d86b7ca 8/**
9 * @file TrainSetup.C
10 * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
11 * @date Wed Mar 23 12:12:00 2011
12 *
13 * @brief
14 *
bd6f5206 15 * @ingroup pwglf_forward_trains
1d86b7ca 16 *
17 */
18
19#ifndef __CINT__
20#include <fstream>
21#include <iostream>
07ff2416 22#include <cstdlib>
1d86b7ca 23
24#include <TAlienCollection.h>
25#include <TArrayI.h>
26#include <TChain.h>
27#include <TDatime.h>
28#include <TEnv.h>
29#include <TFile.h>
30#include <TGrid.h>
31#include <TList.h>
32#include <TObjString.h>
33#include <TProof.h>
34#include <TString.h>
35#include <TSystem.h>
36#include <TSystemDirectory.h>
37#include <TSystemFile.h>
38#include <TROOT.h>
39
40#include <AliAODHandler.h>
41#include <AliAODInputHandler.h>
42#include <AliAnalysisDataContainer.h>
43#include <AliAnalysisManager.h>
44#include <AliAnalysisAlien.h>
45#include <AliESDInputHandler.h>
46#include <AliMCEventHandler.h>
47#include <AliVEventHandler.h>
48#include <AliPhysicsSelection.h>
49#include <AliCentralitySelectionTask.h>
50#else
51class TArrayI;
52class TChain;
53class AliAnalysisManager;
2a276c75 54class TDatime;
e01b1d30 55class TString;
56class TSystemDirectory;
1d86b7ca 57#endif
58
e01b1d30 59
60
1d86b7ca 61//====================================================================
62/**
63 * Generic set-up of an analysis train using the grid-handler (AliEn plugin).
1d86b7ca 64 *
e01b1d30 65 * See also @ref train_setup_doc
66 *
bd6f5206 67 * @ingroup pwglf_forward_trains
1d86b7ca 68 *
69 */
70struct TrainSetup
71{
e01b1d30 72 // Forward declaration
73 class Runner;
1d86b7ca 74 /**
75 * Data type to process
76 */
77 enum EType {
78 /** Event Summary Data */
79 kESD,
80 /** Analysis Object Data */
e01b1d30 81 kAOD,
82 /** User defined */
83 kUser
1d86b7ca 84 };
85 /**
86 * How to run the analysis
87 *
88 */
89 enum EMode {
90 /** Locally */
91 kLocal = 1,
92 /** In PROOF(-Lite) cluster */
93 kProof,
94 /** On the Grid */
95 kGrid
96 };
97 /**
98 * What stage of the analysis to run
99 *
100 */
101 enum EOper {
102 /** Testing. Local processing, a single copied from Grid */
103 kTest,
104 /** Off-line */
105 kOffline,
106 /** Submit to queue */
107 kSubmit,
108 /** Merge and terminate */
109 kTerminate,
110 /** Full run */
e01b1d30 111 kFull,
112 /** Only intialize */
113 kInitialize
1d86b7ca 114 };
115
f53fb4f6 116
117 //__________________________________________________________________
118 virtual ~TrainSetup() {}
119
1d86b7ca 120 //__________________________________________________________________
121 /**
122 * Constructor
123 *
124 * @param name Name of analysis (free-form)
e01b1d30 125 */
126 TrainSetup(const char* name)
1d86b7ca 127 : fName(name),
2a276c75 128 fEscapedName(name),
1d86b7ca 129 fRootVersion("v5-28-00a"),
130 fAliRootVersion("v4-21-18-AN"),
131 fAliEnAPIVersion("V1.1x"),
132 fProofServer("alicecaf.cern.ch"),
133 fDataDir("/alice/data/2010/LHC10c"),
e01b1d30 134 fDataPattern("*"),
1d86b7ca 135 fDataSet("/COMMON/COMMON/LHC09a4_run8100X#/esdTree"),
136 fXML(""),
2a276c75 137 fNReplica(4),
2a276c75 138 fAllowOverwrite(kFALSE),
139 fUseGDB(kFALSE),
140 fMaxSplit(50),
1d86b7ca 141 fRunNumbers(0),
142 fListOfPARs(),
143 fListOfSources(),
144 fListOfLibraries(),
145 fListOfExtras(),
e01b1d30 146 fDatime(1995, 0, 0, 0, 0, 0),
147 fExecType(kUser),
148 fExecMode(kLocal),
149 fExecOper(kFull),
150 fUsePar(false),
151 fMC(false),
152 fPerRunMerge(false),
153 fVerbose(0)
2a276c75 154 {
2a276c75 155 fEscapedName = EscapeName(fName, fDatime);
1d86b7ca 156 }
1d86b7ca 157 //__________________________________________________________________
158 /**
e01b1d30 159 * @{
160 * @name Software environment
161 */
162 /**
163 * Set ROOT version to use
1d86b7ca 164 *
e01b1d30 165 * @param v Version string of ROOT
166 */
167 void SetROOTVersion(const char* v) { fRootVersion = v; }
168 /**
169 * Set AliROOT version to use
1d86b7ca 170 *
e01b1d30 171 * @param v Version string of AliROOT
1d86b7ca 172 */
e01b1d30 173 void SetAliROOTVersion(const char* v) { fAliRootVersion = v; }
1d86b7ca 174 /**
e01b1d30 175 * Set the AliEn API version to use
1d86b7ca 176 *
e01b1d30 177 * @param v AliEn API version
178 */
179 void SetAliEnAPIVersion(const char* v) { fAliEnAPIVersion = v; }
180 /**
181 * Wether to use par files through-out. Mandetory and enforced in
182 * case of a PROOF job,
1d86b7ca 183 *
e01b1d30 184 * @param usePar If true, use PAR files - even for base libraries
1d86b7ca 185 */
e01b1d30 186 void SetUsePar(Bool_t usePar) { fUsePar = usePar; }
187 /* @} */
188
1d86b7ca 189 //__________________________________________________________________
190 /**
e01b1d30 191 * @{
192 * @name Input data
193 */
194 /**
195 * Set the GRID/Local data dir
1d86b7ca 196 *
e01b1d30 197 * @param d Directory with data
198 */
199 void SetDataDir(const char* d) { fDataDir = d; }
200 /**
201 * Set the glob pattern to search input files in - Grid only
1d86b7ca 202 *
e01b1d30 203 * @param pattern Glob pattern
1d86b7ca 204 */
e01b1d30 205 void SetDataPattern(const char* pattern) { fDataPattern = pattern; }
206 /**
207 * Set the PROOF data set
208 *
209 * @param d PROOF registered data set
210 */
211 void SetDataSet(const char* d) { fDataSet = d; }
212 /**
213 * Set the XML file to use
214 *
215 * @param x XML file
216 */
217 void SetXML(const char* x) { fXML = x; }
218 /**
219 * Wether to assume the input comes from MC. If this is set to
220 * true, and the CreateMCHandler member function isn't overloaded to
221 * return null, then the files @c galice.root, @c Kinematics.root,
222 * and @c TrackRefs.root must be present for each input file (@c
223 * AliESDs.root or @c AliAOD.root)
224 *
225 * @param isMC If true, assume MC input
226 */
227 void SetMC(Bool_t isMC) { fMC = isMC; }
228 /* @} */
1d86b7ca 229
230 //__________________________________________________________________
231 /**
e01b1d30 232 * @{
233 * @name Grid storage and splitting
234 */
235 /**
236 * Set how many replicas of the output we want
1d86b7ca 237 *
e01b1d30 238 * @param n Number of replicas requested
1d86b7ca 239 */
e01b1d30 240 void SetNReplica(Int_t n) { fNReplica = n; }
241 /**
242 * Set the maximum number of files per sub-job.
243 *
244 * @param max Maximum number of files per sub-job
245 */
246 void SetMaxSplit(UShort_t max=50) { fMaxSplit = max; }
247 /* @} */
248
1d86b7ca 249 //__________________________________________________________________
250 /**
e01b1d30 251 * @{
252 * @name Name and local working directory
253 */
254 /**
255 * Set whether to allow overwritting existing files/directories
1d86b7ca 256 *
e01b1d30 257 * @param allow If true, allow overwritting files/directories
258 */
259 void SetAllowOverwrite(Bool_t allow) { fAllowOverwrite = allow; }
260 /**
261 * Set the date and time
1d86b7ca 262 *
e01b1d30 263 * @param year Year (>1994)
264 * @param month Month
265 * @param day Day
266 * @param hour Hour
267 * @param minutes Minute
1d86b7ca 268 */
e01b1d30 269 void SetDateTime(UShort_t year, UShort_t month, UShort_t day,
270 UShort_t hour, UShort_t minutes)
1d86b7ca 271 {
e01b1d30 272 fDatime.Set((year<1995?1995:year), month, day, hour, minutes, 0);
273 fEscapedName = EscapeName(fName, fDatime);
1d86b7ca 274 }
1d86b7ca 275 /**
e01b1d30 276 * Set the date and time from a string.
1d86b7ca 277 *
e01b1d30 278 * @param date Formatted like YYYY/MM/DD HH:MM:SS
1d86b7ca 279 */
e01b1d30 280 void SetDateTime(const TString& date)
281 {
282 if (date.IsNull())
283 fDatime.Set(1985,0,0,0,0,0);
284 else if (date.EqualTo("now", TString::kIgnoreCase))
285 fDatime.Set();
286 else
287 fDatime.Set(date);
288 fEscapedName = EscapeName(fName, fDatime);
289 }
1d86b7ca 290 /**
e01b1d30 291 * Return the escaped name
1d86b7ca 292 *
e01b1d30 293 * @return Escaped name
1d86b7ca 294 */
e01b1d30 295 const TString& EscapedName() const
296 {
297 return fEscapedName;
298 }
299 /* @} */
2a276c75 300 //__________________________________________________________________
301 /**
e01b1d30 302 * @{
303 * @name Execution parameters
2a276c75 304 */
1d86b7ca 305 /**
306 * Set the PROOF server URL
307 *
308 * @param s PROOF server URL
309 */
310 void SetProofServer(const char* s) { fProofServer = s; }
1d86b7ca 311 /**
e01b1d30 312 * Set the type of analysis
1d86b7ca 313 *
e01b1d30 314 * @param type AOD or ESD
1d86b7ca 315 */
e01b1d30 316 void SetType(EType type) { fExecType = type; }
1d86b7ca 317 /**
e01b1d30 318 * Set the type of analysis
1d86b7ca 319 *
e01b1d30 320 * @param type AOD or ESD
1d86b7ca 321 */
e01b1d30 322 void SetType(const char* type) { SetType(ParseType(type)); }
1d86b7ca 323 /**
e01b1d30 324 * Set the execution mode of analysis
1d86b7ca 325 *
e01b1d30 326 * @param mode LOCAL, PROOF, GRID
1d86b7ca 327 */
e01b1d30 328 void SetMode(EMode mode) { fExecMode = mode; }
1d86b7ca 329 /**
e01b1d30 330 * Set the execution mode of analysis
1d86b7ca 331 *
e01b1d30 332 * @param mode LOCAL, PROOF, GRID
1d86b7ca 333 */
e01b1d30 334 void SetMode(const char* mode) { SetMode(ParseMode(mode)); }
1d86b7ca 335 /**
e01b1d30 336 * Set the execution operation of analysis
1d86b7ca 337 *
e01b1d30 338 * @param oper FULL, TERMINATE, INIT
1d86b7ca 339 */
e01b1d30 340 void SetOperation(EOper oper) { fExecOper = oper; }
1d86b7ca 341 /**
e01b1d30 342 * Set the execution operation of analysis
1d86b7ca 343 *
e01b1d30 344 * @param oper FULL, TERMINATE, INIT
1d86b7ca 345 */
e01b1d30 346 void SetOperation(const char* oper) { SetOperation(ParseOperation(oper)); }
871a9ac1 347 /**
348 * Use GDB to wrap PROOF slaves
349 *
350 * @param use Whether to use GDB or not
351 */
352 void SetUseGDB(Bool_t use=kTRUE) { fUseGDB = use; }
e01b1d30 353 /* @} */
354
871a9ac1 355 //__________________________________________________________________
2a276c75 356 /**
e01b1d30 357 * @{
358 * @name Stuff to upload
359 */
1d86b7ca 360 /**
361 * Add a source file to be copied and byte compiled on slaves
362 *
363 * @param src Sources
364 * @param addToExtra If false, do not copy
365 */
366 void AddSource(const char* src, bool addToExtra=true)
367 {
368 fListOfSources.Add(new TObjString(src));
369 if (addToExtra) AddExtraFile(src); // Source code isn't copied!
370 }
1d86b7ca 371 /**
372 * Add binary data to be uploaded to slaves
373 *
374 * @param lib Name of binary file
375 */
376 void AddLibrary(const char* lib) { fListOfLibraries.Add(new TObjString(lib));}
e01b1d30 377 /**
378 * Add an extra file to be uploaded to slave
379 *
380 * @param file Extra file to be uploaded
381 */
382 void AddExtraFile(const char* file)
383 {
384 if (!file || file[0] == '\0') return;
385 fListOfExtras.Add(new TObjString(file));
386 }
387 /* @} */
388
1d86b7ca 389 //__________________________________________________________________
e01b1d30 390 /**
391 * @{
392 * @name Run numbers
393 */
1d86b7ca 394 /**
395 * Add a run to be analysed
396 *
397 * @param run Run number
398 */
399 void AddRun(Int_t run)
400 {
401 Int_t i = fRunNumbers.fN; fRunNumbers.Set(i+1); fRunNumbers[i] = run;
402 }
1d86b7ca 403 /**
404 * Read run numbers from a file
405 *
406 * @param filename File name
407 */
408 void ReadRunNumbers(const char* filename)
409 {
410 std::ifstream file(filename);
411 if (!file)
412 Fatal("ReadRunNumbers", "Cannot read from %s", filename);
413
414 while (!file.eof()) {
415 Int_t run;
416 file >> run;
417 AddRun(run);
418 Char_t c;
419 file >> c;
420 if (file.bad()) break;
421 }
422 file.close();
423 }
1d86b7ca 424 /**
e01b1d30 425 * Set the runs to read from a string. The parts should be
426 * delimited by a character in the string @a delim. If a non-number
427 * part is seen, it is assumed to be the name of a file containing
428 * run numbers.
1d86b7ca 429 *
e01b1d30 430 * @param runs String of runs
431 * @param delim Delimiters
1d86b7ca 432 */
e01b1d30 433 void SetRuns(const TString& runs, const char* delim=":, \t")
1d86b7ca 434 {
e01b1d30 435 TIter next(runs.Tokenize(delim));
436 TObjString* os = 0;
437 while ((os = static_cast<TObjString*>(next()))) {
438 TString s(os->String());
439 if (s.IsNull()) continue;
440 if (!s.IsDigit()) ReadRunNumbers(s);
441 else AddRun(s.Atoi());
442 }
1d86b7ca 443 }
1d86b7ca 444 /**
e01b1d30 445 * Whether final merge should be done over all runs (argument true),
446 * or for each run individually.
1d86b7ca 447 *
e01b1d30 448 * @param perRun If true, do final merge over all runs
1d86b7ca 449 */
e01b1d30 450 void SetPerRunMerge(Bool_t perRun) { fPerRunMerge = perRun; }
451 /* @} */
1d86b7ca 452 //__________________________________________________________________
e01b1d30 453 /**
454 * @{
455 * @name Execution
456 */
d23503ee 457 /**
e01b1d30 458 * Initialize the job
f53fb4f6 459 *
460 * @return true on success, false otherwise
461 */
e01b1d30 462 Bool_t Init()
4bcdcbc1 463 {
e01b1d30 464 if (fExecMode == kProof) fUsePar = true;
465
466 // Info("Init", "Connecting in mode=%d", mode);
467 if (!Connect()) return false;
4bcdcbc1 468
f53fb4f6 469 // --- Get current directory and set-up sub-directory ------------
4bcdcbc1 470 TString cwd = gSystem->WorkingDirectory();
e01b1d30 471 if (!SetupWorkingDirectory()) return false;
472
f53fb4f6 473 // --- Load the common libraries ---------------------------------
e01b1d30 474 if (!LoadCommonLibraries()) return false;
4bcdcbc1 475
476 // --- Create analysis manager -----------------------------------
477 AliAnalysisManager *mgr = new AliAnalysisManager(fName,"Analysis Train");
478
479 // In test mode, collect system information on every event
480 // if (oper == kTest) mgr->SetNSysInfo(1);
e01b1d30 481 if (fVerbose > 0) mgr->SetDebugLevel(fVerbose);
482 if (fExecMode == kLocal) mgr->SetUseProgressBar(kTRUE, 100);
4bcdcbc1 483
484 // --- ESD input handler ------------------------------------------
e01b1d30 485 AliVEventHandler* inputHandler = CreateInputHandler(fExecType);
4bcdcbc1 486 if (inputHandler) mgr->SetInputEventHandler(inputHandler);
487
488 // --- Monte-Carlo ------------------------------------------------
e01b1d30 489 AliVEventHandler* mcHandler = CreateMCHandler(fExecType,fMC);
4bcdcbc1 490 if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
491
492 // --- AOD output handler -----------------------------------------
e01b1d30 493 AliVEventHandler* outputHandler = CreateOutputHandler(fExecType);
4bcdcbc1 494 if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
495
496 // --- Include analysis macro path in search path ----------------
497 gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
498 cwd.Data(), gROOT->GetMacroPath()));
499
500 // --- Physics selction - only for ESD ---------------------------
e01b1d30 501 if (fExecType == kESD) CreatePhysicsSelection(fMC, mgr);
4bcdcbc1 502
503 // --- Create centrality task ------------------------------------
e01b1d30 504 CreateCentralitySelection(fMC, mgr);
4bcdcbc1 505
506 // --- Create tasks ----------------------------------------------
e01b1d30 507 CreateTasks(fExecMode, fUsePar, mgr);
4bcdcbc1 508
509 // --- Create Grid handler ----------------------------------------
510 // _must_ be done after all tasks has been added
e01b1d30 511 AliAnalysisAlien* gridHandler = CreateGridHandler();
4bcdcbc1 512 if (gridHandler) mgr->SetGridHandler(gridHandler);
6ff251d8 513
514 // --- Set debug level on defined tasks --------------------------
515 if (fVerbose > 0) {
516 TIter next(mgr->GetTasks());
517 AliAnalysisTask* sub = 0;
518 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
519 AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
520 if (!se) continue;
521 se->SetDebugLevel(fVerbose);
522 }
523 }
4bcdcbc1 524
525 // --- Print setup -----------------------------------------------
526 Print();
527 // if (mode == kProof) {
528 // Info("Run", "Exported environment variables to PROOF slaves:");
529 // TProof::GetEnvVars()->ls();
530 // Info("Run", "Environment variables for this session:");
531 // gSystem->Exec("printenv");
532 // }
533
534 // --- Initialise the train --------------------------------------
535 if (!mgr->InitAnalysis()) {
536 gSystem->ChangeDirectory(cwd.Data());
537 Error("Run","Failed to initialise train");
538 return false;
539 }
540
541 // --- Show status -----------------------------------------------
542 mgr->PrintStatus();
543
544 return true;
545 }
e01b1d30 546 //------------------------------------------------------------------
f53fb4f6 547 /**
e01b1d30 548 * Run the analysis.
f53fb4f6 549 *
e01b1d30 550 * @param nEvents Number of events to analyse
551 * @param r Possible runner object
552 * @param asShell Passed to SaveSetup
553 */
554 virtual void Run(Int_t nEvents, Runner* r=0, Bool_t asShell=false)
4bcdcbc1 555 {
e01b1d30 556 // Info("Exec", "Doing exec with type=%d, mode=%d, oper=%d, events=%d "
557 // "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar);
558
559 TString cwd = gSystem->WorkingDirectory();
560
0c4ed5fc 561 if (!Init()) {
562 Error("Run", "Failed to intialize the train");
563 return;
564 }
e01b1d30 565 if (r) SaveSetup(*r, nEvents, asShell);
566 if (fExecOper == kInitialize) return;
567
568 // --- Create the chain ------------------------------------------
569 TChain* chain = CreateChain();
0c4ed5fc 570 if (fExecMode == kLocal) {
571 if (!chain) {
572 Error("Run", "No chain defined in local mode!");
573 return;
574 }
575 if (chain->GetListOfFiles()->GetEntries() < 1) {
576 Error("Run", "Empty chain in local mode!");
577 return;
578 }
e01b1d30 579 }
580
581 // --- Get manager and execute -----------------------------------
582 AliAnalysisManager *mgr =AliAnalysisManager::GetAnalysisManager();
583 Long64_t ret = StartAnalysis(mgr, chain, nEvents);
584
585 // Make sure we go back
586 gSystem->ChangeDirectory(cwd.Data());
587
588 // Return.
589 if (ret < 0) Error("Exec", "Analysis failed");
4bcdcbc1 590 }
e01b1d30 591 //------------------------------------------------------------------
592 /**
593 * Print the setup
594 *
595 */
596 virtual void Print() const
597 {
598 bool mc=AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler();
599 std::cout << fName << " train setup\n"
600 << std::boolalpha;
601 PrintField(std::cout, "Escaped name", fEscapedName);
602 PrintField(std::cout, "ROOT version", fRootVersion);
603 PrintField(std::cout, "AliROOT version", fAliRootVersion);
604 PrintField(std::cout, "AliEn API version", fAliEnAPIVersion);
605 PrintField(std::cout, "Name of proof server", fProofServer);
606 PrintField(std::cout, "Input directory", fDataDir);
607 PrintField(std::cout, "Data pattern", fDataPattern);
608 PrintField(std::cout, "Proof data set name", fDataSet);
609 PrintField(std::cout, "XML collection", fXML);
610 PrintField(std::cout, "Storage replication", fNReplica);
611 PrintField(std::cout, "Allow overwrite", fAllowOverwrite);
612 PrintField(std::cout, "Do GDB debugging", fUseGDB);
613 PrintField(std::cout, "Max # files per split", fMaxSplit);
614 PrintField(std::cout, "Monte-Carlo input", fMC);
615 PrintField(std::cout, "Monte-Carlo handler", mc);
616 PrintField(std::cout, "Per run merge", fPerRunMerge);
617 PrintFieldName(std::cout, "Run numbers");
618 for (Int_t i = 0; i < fRunNumbers.GetSize(); i++)
619 std::cout << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
620 std::cout << std::endl;
621
622 PrintFieldList(std::cout, "PAR files", fListOfPARs);
623 PrintFieldList(std::cout, "Script sources", fListOfSources);
624 PrintFieldList(std::cout, "Libraries", fListOfLibraries);
625 PrintFieldList(std::cout, "Extras", fListOfExtras, "\n ");
626
627 std::cout << std::noboolalpha << std::endl;
1d86b7ca 628
e01b1d30 629 AliAnalysisGrid* plugin =
630 AliAnalysisManager::GetAnalysisManager()->GetGridHandler();
631 if (!plugin) return;
632
633 }
634 /**
635 * Whether to be verbosity level. 0 means no messages, while higher
636 * numbers increase the verbosity
637 *
638 * @param verb Verbosity level
639 */
640 void SetVerbose(Int_t verb) { fVerbose = verb; }
641 /* @} */
1d86b7ca 642protected:
643 //__________________________________________________________________
e01b1d30 644 /**
645 * @{
646 * @name Copying
647 */
1d86b7ca 648 /**
649 * Copy constructor
650 *
651 * @param o Object to copy from
652 */
653 TrainSetup(const TrainSetup& o)
2a276c75 654 : fName(o.fName),
e01b1d30 655 fEscapedName(o.fEscapedName),
2a276c75 656 fRootVersion(o.fRootVersion),
657 fAliRootVersion(o.fAliRootVersion),
e01b1d30 658 fAliEnAPIVersion(o.fAliEnAPIVersion),
2a276c75 659 fProofServer(o.fProofServer),
660 fDataDir(o.fDataDir),
e01b1d30 661 fDataPattern(o.fDataPattern),
2a276c75 662 fDataSet(o.fDataSet),
663 fXML(o.fXML),
664 fNReplica(o.fNReplica),
2a276c75 665 fAllowOverwrite(o.fAllowOverwrite),
666 fUseGDB(o.fUseGDB),
667 fMaxSplit(o.fMaxSplit),
668 fRunNumbers(o.fRunNumbers),
669 fListOfPARs(),
670 fListOfSources(),
671 fListOfLibraries(),
672 fListOfExtras(),
e01b1d30 673 fDatime(o.fDatime),
674 fExecType(o.fExecType),
675 fExecMode(o.fExecMode),
676 fExecOper(o.fExecOper),
677 fUsePar(o.fUsePar),
678 fMC(o.fMC),
679 fPerRunMerge(o.fPerRunMerge),
680 fVerbose(o.fVerbose)
1d86b7ca 681 {
682 if (isdigit(fName[0])) {
683 Warning("TrainSetup", "Name starts with a digit, prepending 'a' to name");
684 fName = Form("a%s", fName.Data());
685 }
686 TObject* obj = 0;
687 TIter nextPar(&o.fListOfPARs);
688 while ((obj = nextPar())) fListOfPARs.Add(obj->Clone());
689 TIter nextSrc(&o.fListOfSources);
690 while ((obj = nextSrc())) fListOfSources.Add(obj->Clone());
691 TIter nextLib(&o.fListOfLibraries);
692 while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone());
693 TIter nextExa(&o.fListOfExtras);
694 while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
695 }
e01b1d30 696 //------------------------------------------------------------------
1d86b7ca 697 /**
698 * Assignment operator
699 *
700 * @param o Object to assign from
701 *
702 * @return Reference to this object.
703 */
704 TrainSetup& operator=(const TrainSetup& o)
705 {
706 fName = o.fName;
707 fRootVersion = o.fRootVersion;
708 fAliRootVersion = o.fAliRootVersion;
709 fProofServer = o.fProofServer;
710 fDataDir = o.fDataDir;
e01b1d30 711 fDataPattern = o.fDataPattern;
1d86b7ca 712 fDataSet = o.fDataSet;
713 fXML = o.fXML;
714 fNReplica = o.fNReplica;
1d86b7ca 715 fRunNumbers = o.fRunNumbers;
716 TObject* obj = 0;
717 TIter nextPar(&o.fListOfPARs);
718 while ((obj = nextPar())) fListOfPARs.Add(obj->Clone());
719 TIter nextSrc(&o.fListOfSources);
720 while ((obj = nextSrc())) fListOfSources.Add(obj->Clone());
721 TIter nextLib(&o.fListOfLibraries);
722 while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone());
723 TIter nextExa(&o.fListOfExtras);
724 while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
725
726 return *this;
727 }
e01b1d30 728 /* @} */
1d86b7ca 729
730 //__________________________________________________________________
731 /**
e01b1d30 732 * @{
733 * @name Utility functions
734 */
735 /**
736 * Escape bad elements of the name
737 *
738 * @param name Name to escape
739 * @param datime Date and Time
740 *
741 * @return escaped name
742 */
743 static TString EscapeName(const char* name, const TDatime& datime)
1d86b7ca 744 {
e01b1d30 745 TString escaped = name;
746 char c[] = { ' ', '/', '@', 0 };
747 char* p = c;
748 while (*p) {
749 escaped.ReplaceAll(Form("%c", *p), "_");
750 p++;
751 }
752 if (datime.GetYear() <= 1995 ||
753 datime.GetMonth() == 0 ||
754 datime.GetDay() == 0) return escaped;
755 escaped.Append(Form("_%04d%02d%02d_%02d%02d",
756 datime.GetYear(),
757 datime.GetMonth(),
758 datime.GetDay(),
759 datime.GetHour(),
760 datime.GetMinute()));
761 return escaped;
762 }
763 //------------------------------------------------------------------
764 static void PrintFieldName(std::ostream& o, const char* name)
765 {
766 o << " " << std::left << std::setw(25) << name << ": " << std::flush;
1d86b7ca 767 }
e01b1d30 768 //------------------------------------------------------------------
769 static void PrintFieldList(std::ostream& o, const char* name,
770 const TCollection& c, const char* sep=", ")
771 {
772 PrintFieldName(o, name);
773 Bool_t first = true;
774 TObject* obj = 0;
775 TIter next(&c);
776 while ((obj = next())) {
777 o << (first ? "" : sep) << obj->GetName();
778 first = false;
779 }
780 std::cout << std::endl;
781 }
782 //------------------------------------------------------------------
783 template <typename T>
784 static void PrintField(std::ostream& o, const char* name, T& value)
785 {
786 PrintFieldName(o, name);
787 o << value << std::endl;
788 }
789 //------------------------------------------------------------------
1d86b7ca 790 /**
e01b1d30 791 * Return a string that reflects the passed operation
792 *
793 * @param eOper Operation
794 *
795 * @return String representation of operation
796 */
797 static const char* OperString(EOper eOper)
1d86b7ca 798 {
e01b1d30 799 switch (eOper) {
800 case kTest: return "TEST";
801 case kOffline: return "OFFLINE";
802 case kSubmit: return "SUBMIT";
803 case kTerminate: return "TERMINATE";
804 case kFull: return "FULL";
805 case kInitialize: return "INIT";
1d86b7ca 806 }
e01b1d30 807 return 0;
1d86b7ca 808 }
e01b1d30 809 //------------------------------------------------------------------
1d86b7ca 810 /**
e01b1d30 811 * Parse an operation string
1d86b7ca 812 *
e01b1d30 813 * @param oper Operation
814 *
815 * @return An EOper value
1d86b7ca 816 */
e01b1d30 817 static EOper ParseOperation(const char* oper)
1d86b7ca 818 {
e01b1d30 819 TString sOper(oper);
820 sOper.ToUpper();
821 EOper eOper = kFull;
822 if (sOper.Contains("TEST")) eOper = kTest;
823 else if (sOper.Contains("OFFLINE")) eOper = kOffline;
824 else if (sOper.Contains("SUBMIT")) eOper = kSubmit;
825 else if (sOper.Contains("TERMINATE")) eOper = kTerminate;
826 else if (sOper.Contains("FULL")) eOper = kFull;
827 else if (sOper.Contains("INIT")) eOper = kInitialize;
828 else
829 Fatal("Run", "unknown operation '%s'", oper);
830 return eOper;
831 }
832 //------------------------------------------------------------------
833 /**
834 * Return a string that reflects the passed mode
835 *
836 * @param eType Type of analysis
837 *
838 * @return String representation of execution type
839 */
840 static const char* TypeString(EType eType)
841 {
842 switch (eType) {
843 case kESD: return "ESD";
844 case kAOD: return "AOD";
845 case kUser: return "USER";
1d86b7ca 846 }
e01b1d30 847 return 0;
1d86b7ca 848 }
e01b1d30 849 //------------------------------------------------------------------
1d86b7ca 850 /**
e01b1d30 851 * Parse a string into a type enum
1d86b7ca 852 *
e01b1d30 853 * @param type String to pass
854 *
855 * @return Enumaration value
1d86b7ca 856 */
e01b1d30 857 static EType ParseType(const char* type)
1d86b7ca 858 {
e01b1d30 859 // mc = false;
860 TString sType(type);
861 sType.ToUpper();
862 EType eType = kESD;
863 // if (sType.Contains("MC")) mc = true;
864 if (sType.Contains("ESD")) eType = kESD;
865 else if (sType.Contains("AOD")) eType = kAOD;
866 else
867 Fatal("Run", "Unknown type '%s'", type);
868
869 return eType;
870 }
871 //------------------------------------------------------------------
872 /**
873 * Return a string that reflects the passed mode
874 *
875 * @param eMode Mode
876 *
877 * @return String representation of mode
878 */
879 static const char* ModeString(EMode eMode)
880 {
881 switch (eMode) {
882 case kLocal: return "LOCAL";
883 case kProof: return "PROOF";
884 case kGrid: return "GRID";
885 }
886 return 0;
887 }
888 //------------------------------------------------------------------
889 /**
890 * Parse a string for mode specifier
891 *
892 * @param mode Mode string
893 *
894 * @return EMode value
895 */
896 static EMode ParseMode(const char* mode)
897 {
898 TString sMode(mode);
899 sMode.ToUpper();
900 EMode eMode = kLocal;
901 if (sMode.Contains("LOCAL")) eMode = kLocal;
902 else if (sMode.Contains("PROOF")) eMode = kProof;
903 else if (sMode.Contains("GRID")) eMode = kGrid;
904 else
905 Fatal("Run", "Unknown mode '%s'", mode);
906 return eMode;
1d86b7ca 907 }
e01b1d30 908 /* @} */
909
910
1d86b7ca 911 //__________________________________________________________________
e01b1d30 912 /**
913 * @{
914 * @name Overloadable creators
915 */
1d86b7ca 916 /**
917 * Create a grid handler
918 *
1d86b7ca 919 * @return Grid handler
920 */
921 virtual AliAnalysisAlien*
e01b1d30 922 CreateGridHandler()
1d86b7ca 923 {
e01b1d30 924 if (fExecMode != kGrid) return 0;
1d86b7ca 925
926 TString name = EscapedName();
927
928 // Create the plug-in object, and set run mode
929 AliAnalysisAlien* plugin = new AliAnalysisAlien();
e01b1d30 930 plugin->SetRunMode(OperString(fExecOper == kInitialize ?
931 kFull : fExecOper));
1d86b7ca 932
933 // Production mode - not used here
934 // plugin->SetProductionMode();
935
936 // Set output to be per run
e01b1d30 937 plugin->SetOutputToRunNo(true);
1d86b7ca 938
939 // Set the job tag
940 plugin->SetJobTag(fName);
941
942 // Set number of test files - used in test mode only
943 plugin->SetNtestFiles(1);
e01b1d30 944
945 // Set name of generated analysis macro
946 plugin->SetAnalysisMacro(Form("%s.C", name.Data()));
1d86b7ca 947
e01b1d30 948 // Maximum number of sub-jobs
949 // plugin->SetSplitMaxInputFileNumber(25);
950
951 // Set the Time-To-Live
952 plugin->SetTTL(70000);
953
954 // Re-submit failed jobs as long as the ratio of failed jobs is
955 // below this percentage.
956 plugin->SetMasterResubmitThreshold(95);
1d86b7ca 957
e01b1d30 958 // Set the input format
959 plugin->SetInputFormat("xml-single");
960
961 // Set the name of the generated jdl
962 plugin->SetJDLName(Form("%s.jdl", name.Data()));
963
964 // Set the name of the generated executable
965 plugin->SetExecutable(Form("%s.sh", name.Data()));
966
967 // Set the job price !?
968 plugin->SetPrice(1);
969
970 // Set whether to merge via JDL
971 plugin->SetMergeViaJDL(true);
972
973 // Fast read otion
974 plugin->SetFastReadOption(false);
975
976 // Whether to overwrite existing output
977 plugin->SetOverwriteMode(true);
978
979 // Set the executable binary name and options
980 plugin->SetExecutableCommand("aliroot -b -q -x");
981
982 // Split by storage element - must be lower case!
983 plugin->SetSplitMode("se");
984 plugin->SetSplitMaxInputFileNumber(fMaxSplit);
985
986 // Disable default outputs
987 plugin->SetDefaultOutputs(true);
988
989 // Merge parameters
990 plugin->SetMaxMergeFiles(20);
991 plugin->SetMergeExcludes("AliAOD.root "
992 "*EventStat*.root "
993 "*event_stat*.root");
994
995 // Keep log files
996 plugin->SetKeepLogs();
997
998 // Set the working directory to be the trains name (with special
999 // characters replaced by '_' and the date appended), and also set
1000 // the output directory (relative to working directory)
1001 plugin->SetGridWorkingDir(name.Data());
1002 plugin->SetGridOutputDir("output");
1003
1004 // Set required version of software
1005 if (!fAliEnAPIVersion.IsNull()) plugin->SetAPIVersion(fAliEnAPIVersion);
1006 if (!fRootVersion.IsNull()) plugin->SetROOTVersion(fRootVersion);
1007 if (!fAliRootVersion.IsNull()) plugin->SetAliROOTVersion(fAliRootVersion);
1d86b7ca 1008
1009 // Declare root of input data directory
f53fb4f6 1010 TString dataDir(fDataDir);
1011 if (dataDir.BeginsWith("alien://"))
1012 dataDir.ReplaceAll("alien://", "");
1013 plugin->SetGridDataDir(dataDir);
1d86b7ca 1014
1015 // Data search patterns
1016 TString pat;
e01b1d30 1017 if (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler())
1018 plugin->SetRunPrefix("");
1d86b7ca 1019 else {
1d86b7ca 1020 plugin->SetRunPrefix("000");
1021 }
e01b1d30 1022 pat = fDataPattern;
1023 if (!pat.EndsWith("/")) pat.Append("/");
1024 pat.Append(Form("*%s.root", fExecType == kESD ? "ESDs" : "AOD"));
1d86b7ca 1025 plugin->SetDataPattern(pat);
1026
1027 // Add the run numbers
e01b1d30 1028 Int_t nRun = 0;
1d86b7ca 1029 for (Int_t i = 0; i < fRunNumbers.fN; i++) {
1030 if (fRunNumbers[i] < 0) continue;
1031 plugin->AddRunNumber(fRunNumbers[i]);
e01b1d30 1032 nRun++;
1d86b7ca 1033 }
e01b1d30 1034 // Set number of runs per master - set to one to per run
1035 if (fPerRunMerge) plugin->SetNrunsPerMaster(1);
1036 else plugin->SetNrunsPerMaster(nRun+1);
1d86b7ca 1037
1d86b7ca 1038 // Enable configured PARs
1039 TIter nextPar(&fListOfPARs);
1040 TObject* parName;
1041 while ((parName = nextPar()))
1042 plugin->EnablePackage(parName->GetName());
1043
1044 // Add sources that need to be compiled on the workers using
1045 // AcLIC.
1046 TString addSources = SetupSources();
1047 if (!addSources.IsNull()) plugin->SetAnalysisSource(addSources.Data());
1048
1049 // Add binary libraries that should be uploaded to the workers
1050 TString addLibs = SetupLibraries();
1051 if (!addLibs.IsNull()) plugin->SetAdditionalLibs(addLibs.Data());
1052
1d86b7ca 1053 // Loop over defined containers in the analysis manager,
1054 // and declare these as outputs
1055 TString listOfAODs = "";
1056 TString listOfHists = "";
1057 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
1058 AliAnalysisDataContainer* cont = 0;
1059 TIter nextCont(mgr->GetOutputs());
1060 while ((cont = static_cast<AliAnalysisDataContainer*>(nextCont()))) {
1061 TString outName(cont->GetFileName());
1062 TString& list = (outName == "default" ? listOfAODs : listOfHists);
1063 if (outName == "default") {
1064 if (!mgr->GetOutputEventHandler()) continue;
1065
1066 outName = mgr->GetOutputEventHandler()->GetOutputFileName();
1067 }
1068 if (list.Contains(outName)) continue;
1069 if (!list.IsNull()) list.Append(",");
1070 list.Append(outName);
1071 }
1072 if (!mgr->GetExtraFiles().IsNull()) {
1073 if (!listOfAODs.IsNull()) listOfAODs.Append("+");
1074 TString extra = mgr->GetExtraFiles();
1075 extra.ReplaceAll(" ", ",");
1076 listOfAODs.Append(extra);
1077 }
1078 TString outArchive = Form("stderr, stdout@disk=%d", fNReplica);
1079 if (!listOfHists.IsNull())
1080 outArchive.Append(Form(" hist_archive.zip:%s@disk=%d",
1081 listOfHists.Data(), fNReplica));
1082 if (!listOfAODs.IsNull())
1083 outArchive.Append(Form(" aod_archive.zip:%s@disk=%d",
1084 listOfAODs.Data(), fNReplica));
1085 if (listOfAODs.IsNull() && listOfHists.IsNull())
1086 Fatal("CreateGridHandler", "No outputs defined");
1087 // Disabled for now
1088 // plugin->SetOutputArchive(outArchive);
1089
1d86b7ca 1090
1091 return plugin;
1092 }
e01b1d30 1093 //------------------------------------------------------------------
1d86b7ca 1094 /**
1095 * Create input handler
1096 *
1097 * @param type
1098 *
1099 * @return
1100 */
1101 virtual AliVEventHandler* CreateInputHandler(EType type)
1102 {
1103 switch (type) {
1104 case kESD: return new AliESDInputHandler();
1105 case kAOD: return new AliAODInputHandler();
e01b1d30 1106 case kUser: return 0;
1d86b7ca 1107 }
1108 return 0;
1109 }
e01b1d30 1110 //------------------------------------------------------------------
1d86b7ca 1111 /**
1112 * Create input handler
1113 *
1114 * @param type Run type (ESD or AOD)
1115 * @param mc Assume monte-carlo input
1116 *
1117 * @return
1118 */
e01b1d30 1119 virtual AliVEventHandler* CreateMCHandler(EType /*type*/, bool mc)
1d86b7ca 1120 {
1121 if (!mc) return 0;
e01b1d30 1122 // if (type != kESD) return 0;
1d86b7ca 1123 Info("CreateMCHandler", "Making MC handler");
1124 AliMCEventHandler* mcHandler = new AliMCEventHandler();
1125 mcHandler->SetReadTR(true);
1126 return mcHandler;
1127 }
e01b1d30 1128 //------------------------------------------------------------------
1d86b7ca 1129 /**
1130 * Create output event handler
1131 *
1132 * @param type
1133 *
1134 * @return
1135 */
1136 virtual AliVEventHandler* CreateOutputHandler(EType type)
1137 {
1138 AliAODHandler* ret = new AliAODHandler();
1139 switch (type) {
1140 case kESD:
1141 ret->SetOutputFileName("AliAOD.root");
1142 break;
1143 case kAOD:
1144 ret->SetOutputFileName("AliAOD.pass2.root");
1145 break;
e01b1d30 1146 case kUser:
1147 break;
1d86b7ca 1148 }
e01b1d30 1149
1d86b7ca 1150 return ret;
1151 }
e01b1d30 1152 //------------------------------------------------------------------
1d86b7ca 1153 /**
e01b1d30 1154 * Create physics selection, and add to manager
1d86b7ca 1155 *
1156 * @param mc Whether this is for MC
1157 * @param mgr Manager
1158 */
1159 virtual void CreatePhysicsSelection(Bool_t mc,
1160 AliAnalysisManager* mgr)
1161 {
1162 gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
1163 mgr->RegisterExtraFile("event_stat.root");
1164 }
e01b1d30 1165 //------------------------------------------------------------------
1d86b7ca 1166 /**
e01b1d30 1167 * Create centrality selection, and add to manager
1d86b7ca 1168 *
1169 * @param mc Whether this is for MC
1170 * @param mgr Manager
1171 */
1172 virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
1173 {
1174 gROOT->Macro("AddTaskCentrality.C");
2a276c75 1175 const char* name = "CentralitySelection";
1d86b7ca 1176 AliCentralitySelectionTask* ctask =
2a276c75 1177 dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
1d86b7ca 1178 if (!ctask) return;
1d86b7ca 1179 if (mc) ctask->SetMCInput();
1180 }
e01b1d30 1181 //------------------------------------------------------------------
1d86b7ca 1182 /**
e01b1d30 1183 * Create analysis tasks. Must be overloaded by sub-class
1d86b7ca 1184 *
1185 * @param mode Run mode
1186 * @param mgr Manager
1187 * @param par Whether to use pars
1188 */
1189 virtual void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)=0;
e01b1d30 1190 /* @} */
1191
1d86b7ca 1192 //__________________________________________________________________
e01b1d30 1193 /**
1194 * @{
1195 * @name Library loading
1196 */
1197 //------------------------------------------------------------------
1198 /**
1199 * Load common libraries
1200 *
1201 * @return true on success
1202 */
1203 Bool_t LoadCommonLibraries()
1204 {
1205 if (!gSystem->Getenv("ALICE_ROOT")) {
1206 Error("LoadCommonLibraries", "Local AliROOT not available");
1207 return false;
1208 }
1209 gSystem->Load("libTree.so");
1210 gSystem->Load("libGeom.so");
1211 gSystem->Load("libVMC.so");
1212 gSystem->Load("libPhysics.so");
1213 gSystem->Load("libMinuit.so");
1214 if (fExecMode == kProof) {
1215 gProof->Exec("gSystem->Load(\"libTree.so\");");
1216 gProof->Exec("gSystem->Load(\"libGeom.so\");");
1217 gProof->Exec("gSystem->Load(\"libMinuit.so\");");
1218 gProof->Exec("gSystem->Load(\"libVMC.so\");");
1219
1220
1221 }
1222
1223 Bool_t ret = true;
1224 Bool_t basic = fExecMode == kGrid ? false : fUsePar;
1225
1226 ret &= LoadLibrary("STEERBase", basic, false);
1227 ret &= LoadLibrary("ESD", basic, false);
1228 ret &= LoadLibrary("AOD", basic, false);
1229 ret &= LoadLibrary("ANALYSIS", basic, true);
1230 ret &= LoadLibrary("OADB", basic, true);
1231 ret &= LoadLibrary("ANALYSISalice", basic, true);
1232
1233 return ret;
1234 }
1235 //------------------------------------------------------------------
1236 /**
1237 * Load a library
1238 *
1239 * @param what What library to load
1240 * @param par If true, load as PAR
1241 * @param rec If true, also load on slaves
1242 *
1243 * @return true on success
1244 */
1245 Bool_t LoadLibrary(const char* what, Bool_t par, Bool_t rec=false)
1246 {
1247 if (!what || what[0] == '\0') return true;
1248
1249 TString module(what);
1250 TString libName(what);
1251 if (!libName.BeginsWith("lib")) {
1252 // Check if the library corresponds to a compiled macro
1253 if (!gSystem->AccessPathName(Form("%s_C.so", libName.Data()))) {
1254 libName.Append("_C");
1255 }
1256 else if (!gSystem->AccessPathName(Form("../%s_C.so", libName.Data()))) {
1257 libName = Form("../%s_C", what);
1258 }
1259 else
1260 libName = Form("lib%s", libName.Data());
1261 }
1262 if (!libName.EndsWith(".so")) libName.Append(".so");
1263
1264 Int_t ret = 0;
1265
1266 switch (fExecMode) {
1267 case kLocal: // Just load and exit
1268 if (gSystem->Load(libName.Data()) < 0) {
1269 Error("LoadLibrary", "Failed to load library %s", libName.Data());
1270 return false;
1271 }
1272 break;
1273 case kGrid:
1274 if (par) {
1275 ret = SetupPAR(what) ? 0 : -1;
1276 if (rec) fListOfPARs.Add(new TObjString(what));
1277 } else {
1278 ret = gSystem->Load(libName.Data());
1279 if (rec) fListOfLibraries.Add(new TObjString(libName));
1280 }
1281 break;
1282 case kProof:
1283 Info("LoadLibrary", "Uploading %s", what);
1284 ret = gProof->UploadPackage(what, TProof::kRemoveOld);
1285 if (ret < 0) {
1286 ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par",
1287 what)));
1288 if (ret < 0) {
1289 ret =
1290 gProof->UploadPackage(gSystem
1291 ->ExpandPathName(Form("$ALICE_ROOT/%s.par",
1292 what)));
1293 if (ret < 0) {
1294 Error("LoadLibrary",
1295 "Could not find module %s.par in current directory nor "
1296 "in $ALICE_ROOT", module.Data());
1297 return false;
1298 }
1299 }
1300 }
1301 Info("LoadLibrary", "Enabling package %s", what);
1302 ret = gProof->EnablePackage(what);
1303 break;
1304 }
1305 if (ret < 0) {
1306 Error("LoadLibrary", "Couldn't load %s", what);
1307 return false;
1308 }
1309 return true;
1310 }
1311 /* @} */
1312
1313 //__________________________________________________________________
1314 /**
1315 * @{
1316 * @name PAR generation from script
1317 */
1318 /**
1319 * Service function to make a PAR out of a script.
1320 *
1321 * The script should contain can contain a sub-class of AliAnalysisTask.
1322 * The script will be compiled on the slaves before loading the
1323 * AliAnalysisManager. Parts to (not) be compiled can be protected like
1324 *
1325 * @code
1326 * #ifdef BUILD_PAR
1327 * // This will _only_ be compiled in the servers
1328 * #endif
1329 * #ifndef BUILD_PAR
1330 * // This will not be compiled in the servers
1331 * #endif
1332 * @endcode
1333 *
1334 * @param mode Execution mode (Grid, PROOF, Local)
1335 * @param script Script to upload and compile in the PAR
1336 * @param deps Dependency pars
1337 *
1338 * @return true on success.
1339 */
1340 static Bool_t MakeScriptPAR(EMode mode, const char* script, const char* deps)
1341 {
1342 // Get the base name
1343 Info("MakeScriptPAR", "Making par file for %s", script);
1344 TString base(gSystem->BaseName(script));
1345 Int_t idx = base.Last('.');
1346 if (idx != kNPOS) base.Remove(idx);
1347 Bool_t retval = true;
1348 // Info("MakeScriptPAR", "script=%s, base=%s", script, base.Data());
1349
1350 if (mode == kLocal) {
1351 if (gROOT->LoadMacro(Form("%s.C++g", base.Data())) < 0)
1352 return false;
1353 return true;
1354 }
1355
1356 TString tmpdir(gSystem->TempDirectory());
1357 int ltempl = tmpdir.Length() + 1 + 5 + 6 + 1;
1358 char* templ = new char[ltempl];
1359 snprintf(templ, ltempl, "%s/trainXXXXXX", tmpdir.Data());
1360 if (!mkdtemp(templ)) {
1361 Error("MakeScriptPAR",
1362 "Failed to generate temporary directory from template %s",
1363 templ);
1364 return false;
1365 }
1366
1367 try {
1368 // Check name of script file
1369 TString scr(script);
1370 TString ext;
1371 if (scr.EndsWith(".C")) ext = "C";
1372 else if (scr.EndsWith(".cxx")) ext = "cxx";
1373 else { ext = "C"; scr.Append(".C"); }
1374
1375 // Check if we can access the file
1376 TString path = TString::Format(".:%s", TROOT::GetMacroPath());
1377 char* loc = gSystem->Which(path, scr);
1378 if (!loc) throw TString::Format("Script %s not found in %s",
1379 scr.Data(), path.Data());
1380 TString full(loc);
1381
1382 TString dir = TString::Format("%s/%s", templ, base.Data());
1383 // Set-up directories
1384 if (gSystem->MakeDirectory(dir) < 0)
1385 throw TString::Format("Could not make directory '%s'", base.Data());
1386
1387 if (gSystem->MakeDirectory(Form("%s/PROOF-INF", dir.Data())))
1388 throw TString::Format("Could not make directory %s/PROOF-INF",
1389 base.Data());
1390
1391 // Copy the script to the setup directory
1392 TString dest = TString::Format("%s/%s.%s", dir.Data(),
1393 base.Data(), ext.Data());
1394 Int_t ret = gSystem->CopyFile(full, dest, true);
1395 switch (ret) {
1396 case -1: throw TString::Format("Couldn't open %s for copy", scr.Data());
1397 case -2: throw TString::Format("File %s exists", dest.Data());
1398 case -3: throw TString::Format("Error while copying %s", scr.Data());
1399 }
1400
1401 // Make our build file
1402 // Info("MakeScriptPAR", "Making build script %s/PROOF-INF/BUILD.sh", dir.Data());
1403 std::ofstream b(Form("%s/PROOF-INF/BUILD.sh", dir.Data()));
1404 if (!b)
1405 throw TString::Format("Failed to open b shell script");
1406 b << "#!/bin/sh\n"
1407 << "echo BUILD.sh@`hostname`: Building " << base << "\n"
1408 << "root.exe -l -b -q PROOF-INF/BUILD.C 2>&1 | tee " << base << ".log\n"
1409 << "echo BUILD.sh@`hostname`: done: $?\n"
1410 << std::endl;
1411 b.close();
1412 if (gSystem->Chmod(Form("%s/PROOF-INF/BUILD.sh", dir.Data()), 0755) != 0)
1413 throw TString::Format("Failed to set exectuable flags on "
1414 "%s/PROOF-INF/BUILD.sh", dir.Data());
1415
1416 // Info("MakeScriptPAR", "Making utility script %s/PROOF-INF/UTIL.C", dir.Data());
1417 std::ofstream u(Form("%s/PROOF-INF/UTIL.C", dir.Data()));
1418 if (!u)
1419 throw TString::Format("Failed to open utility script");
1420 u << "void LoadROOTLibs() {\n"
1421 << " gSystem->Load(\"libVMC\");\n"
1422 << " gSystem->Load(\"libNet\");\n"
1423 << " gSystem->Load(\"libTree\");\n"
1424 << " gSystem->Load(\"libPhysics\");\n"
1425 << " gSystem->Load(\"libMinuit\");\n"
1426 << "}\n\n"
1427 << "void AddAliROOT() {\n"
1428 << " TString val(gSystem->Getenv(\"ALICE_ROOT\"));\n"
1429 << " if (val.IsNull())\n"
1430 << " Warning(\"Add\",\"ALICE_ROOT not defined\");\n"
1431 << " else\n"
1432 << " gSystem->AddIncludePath(Form(\"-I%s/include\",val.Data()));\n"
1433 << "}\n\n"
1434 << "void AddDep(const char* env) {\n"
1435 << " TString val(gSystem->Getenv(Form(\"%s_INCLUDE\",env)));\n"
1436 << " if (val.IsNull())\n"
1437 << " Warning(\"Add\",\"%s_INCLUDE not defined\", env);\n"
1438 << " else {\n"
1439 << " gSystem->AddIncludePath(Form(\"-I../%s\",val.Data()));\n"
1440 << " }\n"
1441 << "}\n\n"
1442 << "void LoadDep(const char* name) {\n"
1443 << " gSystem->AddDynamicPath(Form(\"../%s\",name));\n"
1444 << " char* full = gSystem->DynamicPathName(name,true);\n"
1445 << " if (!full) \n"
1446 << " full = gSystem->DynamicPathName(Form(\"lib%s\",name),true);\n"
1447 << " if (!full) \n"
1448 << " full = gSystem->DynamicPathName(Form(\"lib%s.so\",name),true);\n"
1449 << " if (!full) {\n"
1450 << " Warning(\"LoadDep\",\"Module %s not found\", name);\n"
1451 << " return;\n"
1452 << " }\n"
1453 << " gSystem->Load(full);\n"
1454 << "}\n"
1455 << std::endl;
1456 u.close();
1457
1458 // Info("MakeScriptPAR", "Making utility script %s/PROOF-INF/BUILD.C", dir.Data());
1459 std::ofstream cbuild(Form("%s/PROOF-INF/BUILD.C", dir.Data()));
1460 if (!cbuild)
1461 throw TString::Format("Failed to open build script");
1462 cbuild << "void BUILD() {\n"
1463 << " gSystem->AddIncludePath(\"-DBUILD_PAR=1\");\n"
1464 << " gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
1465 << " LoadROOTLibs();\n"
1466 << " AddAliROOT();\n";
1467 TObjArray* depList = TString(deps).Tokenize(",");
1468 TIter next(depList);
1469 TObject* dep = 0;
1470 while ((dep = next())) {
1471 cbuild << " AddDep(\"" << dep->GetName() << "\");\t"
1472 << " LoadDep(\"" << dep->GetName() << "\");\n";
1473 }
1474 cbuild << " // gDebug = 5;\n"
1475 << " int ret = gROOT->LoadMacro(\""
1476 << base << "." << ext << "++g\");\n"
1477 << " if (ret != 0) Fatal(\"BUILD\",\"Failed to build\");\n"
1478 << " // else Info(\"BUILD\", \"Made " << base << "\");\n"
1479 << "}\n"
1480 << std::endl;
1481 cbuild.close();
1482
1483 // Make our set-up script
1484 // Info("MakeScriptPAR", "Making setup script %s/PROOF-INF/SETUP.C", dir.Data());
1485 std::ofstream setup(Form("%s/PROOF-INF/SETUP.C", dir.Data()));
1486 if (!setup)
1487 throw TString::Format("Failed to open setup script");
1488 setup << "void SETUP() {\n"
1489 << " gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
1490 << " LoadROOTLibs();\n"
1491 << " // Info(\"SETUP\",\"Loading libraries\");\n";
1492 next.Reset();
1493 dep = 0;
1494 while ((dep = next()))
1495 setup << " LoadDep(\"" << dep->GetName() << "\");\n";
1496 setup << " // gDebug = 5;\n"
1497 << " // Info(\"SETUP\",\"Loading " << base << "_" << ext << ".so\");\n"
1498 << " gSystem->Load(\"" << base << "_" << ext << ".so\");\n"
1499 << " // gDebug = 0;\n"
1500 << " gROOT->ProcessLine(\".include " << base << "\");\n"
1501 << " gSystem->Setenv(\"" << base << "_INCLUDE\",\""
1502 << base << "\");\n"
1503 << " // Info(\"SETUP\", \"Done\");\n"
1504 << "}\n"
1505 << std::endl;
1506 setup.close();
1507
1508 // Info("MakeScriptPAR", "Packing up tar-archive");
1509 ret = gSystem->Exec(Form("(cd %s && tar -czf %s.par %s)",
1510 templ, base.Data(),base.Data()));
1511 if (ret != 0)
1512 throw TString::Format("Failed to create PAR file %s.PAR from %s",
1513 base.Data(), dir.Data());
1514
1515 // Info("MakeScriptPAR", "Moving PAR archive");
1516 ret = gSystem->Exec(Form("mv -f %s/%s.par %s.par", templ, base.Data(),
1517 base.Data()));
1518 if (ret != 0)
1519 throw TString::Format("Failed to rename %s/%s.par to %s.par: %s",
1520 templ, base.Data(), base.Data(),
1521 gSystem->GetError());
1522 }
1523 catch (TString& e) {
1524 Error("MakeScriptPAR", "%s", e.Data());
1525 retval = false;
1526 }
1527 // Info("MakeScriptPAR", "Removing temperary directory %s", templ);
1528 gSystem->Exec(Form("rm -rf %s", templ));
1529 return retval;
1530 }
1531 /* @} */
1532
1533 //__________________________________________________________________
1534 /**
1535 * @{
1536 * @name Execution implementation
1537 */
1538 /**
1539 * Start the analysis
1540 *
1541 * @param mgr Analysis manager
1542 * @param chain Input data (local and proof only)
1543 * @param nEvents Number of events to analyse
1544 */
1545 Long64_t StartAnalysis(AliAnalysisManager* mgr,
1546 TChain* chain,
1547 Int_t nEvents)
1548 {
1549 // --- Run the analysis ------------------------------------------
1550 TString mode = ModeString(fExecMode);
1551 switch (fExecMode) {
1552 case kLocal:
1553 if (!chain) {
1554 Error("StartAnalysis", "No chain defined");
1555 return -1;
1556 }
1557 if (nEvents < 0) nEvents = chain->GetEntries();
1558 return mgr->StartAnalysis(mode, chain, nEvents);
1559 case kProof:
1560 if (fDataSet.IsNull()) {
1561 if (!chain) {
1562 Error("StartAnalysis", "No chain defined");
1563 return -1;
1564 }
1565 if (nEvents < 0) nEvents = chain->GetEntries();
1566 return mgr->StartAnalysis(mode, chain, nEvents);
1567 }
1568 return mgr->StartAnalysis(mode, fDataSet);
1569 case kGrid:
1570 if (nEvents < 0)
1571 return mgr->StartAnalysis(mode);
1572 return mgr->StartAnalysis(mode, nEvents);
1573 }
1574 // We should never get here
1575 return -1;
1576 }
1577 //------------------------------------------------------------------
1d86b7ca 1578 /**
1579 * Connect to external services (Proof and/or grid)
1580 *
1d86b7ca 1581 * @return true on success
1582 */
e01b1d30 1583 virtual Bool_t Connect()
1d86b7ca 1584 {
e01b1d30 1585 if (fExecMode == kLocal) return true;
1d86b7ca 1586
1587 // --- Set-up connections to Proof cluster and alien -------------
e01b1d30 1588 if (fExecMode == kProof) {
d23503ee 1589 Info("Connect", "Opening connection to proof server");
1d86b7ca 1590 // --- Find user name ------------------------------------------
1591 TString userName(gSystem->Getenv("alien_API_USER"));
1592 if (userName.IsNull()) {
1593 userName = gSystem->GetUserInfo()->fUser;
1594 Warning("Connect",
1595 "environment variable 'alien_API_USER' not set, using %s",
1596 userName.Data());
1597 }
1598
1599 // --- Set prefered GSI method ---------------------------------
1600 gEnv->SetValue("XSec.GSI.DelegProxy", "2");
36619b75 1601
1602 // --- Figure out some server settings -------------------------
1d86b7ca 1603 TString serv = "";
1604 Bool_t lite = false;
1605 if (fProofServer.BeginsWith("workers=") || fProofServer.IsNull()) {
1606 lite = true;
1607 serv = fProofServer;
1608 }
1609 else
1610 serv = Form("%s@%s", userName.Data(), fProofServer.Data());
36619b75 1611
1612 // --- Possibly debug slave sessions with GDB ------------------
1613 if (fUseGDB) {
07ff2416 1614 TString gdbCmd("/usr/bin/gdb --batch -ex run -ex bt --args");
1615 // TString gdbCmd("\"gdb --batch -ex run -ex bt --args\"");
36619b75 1616 Info("Connect", "Using GDB to wrap slaves: %s", gdbCmd.Data());
1617 TProof::AddEnvVar("PROOF_WRAPPERCMD", gdbCmd);
1618 }
1619
1620 // --- Add ALICE_ROOT directory to search path for packages ----
d23503ee 1621 Info("Connect", "Set location of packages");
36619b75 1622 gEnv->SetValue("Proof.GlobalPackageDirs",
1623 Form("%s:%s",
1624 gEnv->GetValue("Proof.GlobalPackageDirs", "."),
1625 gSystem->Getenv("ALICE_ROOT")));
1626
1627 // --- Set OADB path on workers --------------------------------
1628 const char* oadbPath = AliAnalysisManager::GetOADBPath();
1629 TProof::AddEnvVar("OADB_PATH", oadbPath);
1630 // if (lite) gSystem->Setenv("OADB_PATH", oadbPath);
1631 // Info("Connect", "OADB_PATH=%s", gSystem->Getenv("OADB_PATH"));
1632
1633 // --- Now open connection to PROOF cluster --------------------
1d86b7ca 1634 TProof::Open(serv);
1635 if (!gProof) {
1636 Error("Connect", "Failed to connect to Proof cluster %s as %s",
1637 fProofServer.Data(), userName.Data());
1638 return false;
1639 }
d23503ee 1640 Info("Connect", "Now connected to Proof");
1641 // gProof->SetParameter("PROOF_LookupOpt", "all");
1d86b7ca 1642 if (lite) return true;
1643 }
1644
1645 // --- Open a connection to the grid -----------------------------
e01b1d30 1646
1d86b7ca 1647 TGrid::Connect("alien://");
1648 if (!gGrid || !gGrid->IsConnected()) {
1649 // This is only fatal in grid mode
1650 Error("Connect", "Failed to connect to AliEN");
e01b1d30 1651 if (fExecMode == kGrid) return false;
1d86b7ca 1652 return true;
1653 }
e01b1d30 1654 if (fExecMode == kGrid) return true;
1d86b7ca 1655
1d86b7ca 1656 // --- Set and make output directory -----------------------------
1657 TString name = EscapedName();
1658 TString homeDir(gGrid->GetHomeDirectory());
1659 TString workDir(homeDir);
1660 workDir.Append("/");
1661 workDir.Append(name);
1662
1663 // Make working directory
1664 if (!gGrid->Cd(workDir)) {
1665 gGrid->Cd(homeDir);
1666 if (gGrid->Mkdir(workDir)) {
1667 gGrid->Cd(name);
1668 Info("Connect", "Directory %s created", workDir.Data());
1669 }
1670 }
1671 // Make output directory
1672 gGrid->Mkdir("proof_output");
1673 gGrid->Cd("proof_output");
e01b1d30 1674
1d86b7ca 1675 return true;
1676 }
e01b1d30 1677 //------------------------------------------------------------------
1d86b7ca 1678 /**
e01b1d30 1679 * Get the output directory (local or Grid)
1d86b7ca 1680 *
e01b1d30 1681 * @param mode Mode of execution
1d86b7ca 1682 *
e01b1d30 1683 * @return Path to output directory
1d86b7ca 1684 */
e01b1d30 1685 TString GetOutputDirectory(EMode mode) const
1d86b7ca 1686 {
e01b1d30 1687 TString ret(fEscapedName);
1688 if (mode != kGrid) return ret;
1689
1690 AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
1691 if (!am) {
1692 Warning("GetOutputDirectory", "No analysis manager defined yet");
1693 return ret;
1d86b7ca 1694 }
e01b1d30 1695 AliAnalysisGrid* ag = am->GetGridHandler();
1696 if (!ag) {
1697 Warning("GetOutputDirectory", "No grid handler defined yet");
1698 return ret;
1699 }
1700 AliAnalysisAlien* aa = dynamic_cast<AliAnalysisAlien*>(ag);
1701 if (!aa) {
1702 Warning("GetOutputDirectory", "Grid handler isn't for AliEn");
1703 return ret;
1704 }
1705 ret = aa->GetGridOutputDir();
1706 if (!ret.BeginsWith("/")) {
1707 if (gGrid)
1708 ret = Form("%s/%s/%s", gGrid->GetHomeDirectory(),
1709 fEscapedName.Data(), aa->GetGridOutputDir());
1710 else
1711 ret = Form("%s/%s", fEscapedName.Data(), aa->GetGridOutputDir());
36619b75 1712 }
1d86b7ca 1713 return ret;
1714 }
e01b1d30 1715 /* @} */
1716
1d86b7ca 1717 //__________________________________________________________________
1718 /**
e01b1d30 1719 * @{
1720 * @name Setup
1721 */
1722 /**
1723 * Make our working directory if so requested
1d86b7ca 1724 *
e01b1d30 1725 * @return true on success
1d86b7ca 1726 */
e01b1d30 1727 Bool_t SetupWorkingDirectory()
1d86b7ca 1728 {
e01b1d30 1729 TString nam = EscapedName();
1730 //Info("Init","Current dir=%s, escaped name=%s",cwd.Data(),nam.Data());
1731 Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
1732 if (fExecOper == kTerminate && !exists) {
1733 Error("SetupWorkingDirectory", "File/directory %s does not exists",
1734 nam.Data());
1735 return false;
1736 }
1d86b7ca 1737
e01b1d30 1738
1739 if (!fAllowOverwrite && exists) {
1740 Error("SetupWorkingDirectory", "File/directory %s already exists",
1741 nam.Data());
1742 return false;
1743 }
1d86b7ca 1744
e01b1d30 1745 if (!exists) {
1746 if (gSystem->MakeDirectory(nam.Data())) {
1747 Error("SetupWorkingDirectory", "Failed to make directory '%s'",
1748 nam.Data());
1749 return false;
1d86b7ca 1750 }
1d86b7ca 1751 }
e01b1d30 1752
1753 if (!gSystem->ChangeDirectory(nam.Data())) {
1754 Error("SetupWorkingDirectory", "Failed to change directory to %s",
1755 nam.Data());
1d86b7ca 1756 return false;
1757 }
e01b1d30 1758 Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there",
1759 nam.Data());
1d86b7ca 1760 return true;
1761 }
e01b1d30 1762 //------------------------------------------------------------------
1763 /**
1764 * Set-up a PAR file
1765 *
1766 * @param what PAR file
1767 *
1768 * @return true on success
1769 */
1d86b7ca 1770 Bool_t SetupPAR(const char* what)
1771 {
1772 if (!what || what[0] == '\0') return -1;
1773
1774 TString parFile(Form("%s.par", what));
1775 if (gSystem->AccessPathName(parFile.Data())) {
1776 if (gSystem->AccessPathName(Form("../%s.par", what))) {
1777 // If not found
1778 TString aliParFile =
1779 gSystem->ExpandPathName(Form("$(ALICE_ROOT)/%s.par", what));
1780 if (gSystem->AccessPathName(aliParFile.Data())) {
1781 Error("SetupPAR", "PAR file %s not found in current directory or "
1782 "$(ALICE_ROOT)", what);
1783 return false;
1784 }
1785 // Copy to current directory
1786 TFile::Cp(aliParFile, parFile);
1787 }
1788 else
1789 gSystem->Exec(Form("ln -s ../%s.par .", what));
1790 }
1791
1792 // Extract archive
2a276c75 1793 gSystem->Exec(Form("tar xzf %s", parFile.Data()));
1d86b7ca 1794
1795 // Change directory into par archive
1796 TString cwd = gSystem->WorkingDirectory();
1797
1798 if (!gSystem->ChangeDirectory(what)) {
1799 Error("SetupPAR", "Failed to change directory to %s", what);
1800 return false;
1801 }
1802
1803 // Test the build
1804 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
1805 Info("SetupPar", "Building in PAR archive %s", what);
1806 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
1807 Error("SetupPar", "Failed to build in PAR directory %s", what);
1808 gSystem->ChangeDirectory(cwd.Data());
1809 return false;
1810 }
1811 }
1812
1813 // Check for setup script
1814 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
e01b1d30 1815 // Info("SetupPAR", "Setting up for PAR %s", what);
1d86b7ca 1816 gROOT->Macro("PROOF-INF/SETUP.C");
1817 }
1818 if (!gSystem->ChangeDirectory(cwd.Data())) return false;
1819
1820 return true;
1821 }
e01b1d30 1822 //------------------------------------------------------------------
1823 /**
1824 * Set-up extra sources.
1825 *
1826 * @return true on success
1827 */
1d86b7ca 1828 TString SetupExtras()
1829 {
1830 TString ret;
1831 TIter next(&fListOfExtras);
1832 TObjString* obj = 0;
1833 while ((obj = static_cast<TObjString*>(next()))) {
1834 TString path = gSystem->ExpandPathName(obj->GetName());
1835 if (!path.BeginsWith("/"))
1836 // If not an absolute path, prepend to up-one
1837 path = Form("../%s", path.Data());
1838 if (gSystem->AccessPathName(path.Data())) {
1839 // File not accessible
1840 Warning("SetupExtras", "File %s not accessible", path.Data());
1841 continue;
1842 }
1843 ret.Append(Form("%s ", gSystem->BaseName(obj->GetName())));
1844 gSystem->Exec(Form("ln -s %s .", path.Data()));
1845 }
1846 ret = ret.Strip();
1847 return ret;
1848 }
e01b1d30 1849 //------------------------------------------------------------------
1850 /**
1851 * Set-up sources for upload
1852 *
1853 *
1854 * @return String of sources
1855 */
1d86b7ca 1856 TString SetupSources()
1857 {
1858 TString nam = EscapedName();
1859 TString ret;
1860 TIter next(&fListOfSources);
1861 TObject* src;
1862 while ((src = next())) {
1863 TString path = gSystem->ExpandPathName(src->GetName());
1864 if (!path.BeginsWith("/"))
1865 // If not an absolute path, prepend to up-one
1866 path = Form("../%s", path.Data());
1867 if (gSystem->AccessPathName(path.Data())) {
1868 // File not accessible
1869 Warning("SetupSources", "File %s not accessible", path.Data());
1870 continue;
1871 }
1872 ret.Append(Form("%s ", gSystem->BaseName(src->GetName())));
1873 gSystem->Exec(Form("ln -s %s .", path.Data()));
1874 }
1875 ret = ret.Strip();
1876 return ret;
1877 }
e01b1d30 1878 //------------------------------------------------------------------
1879 /**
1880 * Set-up extra libraries to upload
1881 *
1882 * @return String of libraries
1883 */
1d86b7ca 1884 TString SetupLibraries()
1885 {
1886 TString ret;
1887 TIter next(&fListOfLibraries);
1888 TObject* lib;
1889 while ((lib = next())) {
1890 ret.Append(lib->GetName());
1891 ret.Append(" ");
1892 }
1893 // Also add extra files to this variable
1894 ret.Append(SetupExtras());
1895 ret = ret.Strip();
1896 return ret;
1897 }
e01b1d30 1898 /* @} */
1899
1d86b7ca 1900 //__________________________________________________________________
e01b1d30 1901 /**
1902 * @{
1903 * @name Chain building
1904 */
0c4ed5fc 1905 /**
1906 * Check if we can add a file to the chain
1907 *
1908 * @param path Full path to file
1909 * @param chain Chain
1910 *
1911 * @return true on success, false otherwise
1912 */
1913 Bool_t CheckFile(const TString& path, TChain* chain)
1914 {
1915 TFile* test = TFile::Open(path, "READ");
1916 if (!test) {
1917 Warning("CheckFile", "Failed to open %s", path.Data());
1918 return false;
1919 }
1920
1921 Bool_t ok = false; // Assume failure
1922 TObject* o = test->Get(chain->GetName());
1923 if (!o)
1924 Warning("CheckFile", "The file %s does not contain the object %s",
1925 path.Data(), chain->GetName());
1926 else if (!dynamic_cast<TTree*>(o))
1927 Warning("CheckFile", "Object %s found in %s is not a TTree",
1928 o->GetName(), path.Data());
1929 else
1930 ok = true;
1931 test->Close();
1932 if (ok) chain->AddFile(path);
1933
1934 return ok;
1935 }
1d86b7ca 1936 /**
1937 * Scan directory @a dir (possibly recursive) for tree files to add
1938 * to the chain. This does not follow sym-links
1939 *
1940 * @param dir Directory to scan
1941 * @param chain Chain to add to
1d86b7ca 1942 * @param recursive Whether to scan recursively
1d86b7ca 1943 *
1944 * @return true if any files where added
1945 */
1946 Bool_t ScanDirectory(TSystemDirectory* dir, TChain* chain,
e01b1d30 1947 bool recursive)
1d86b7ca 1948 {
1949 TString fnPattern;
e01b1d30 1950 switch (fExecType) {
1d86b7ca 1951 case kESD: fnPattern = "AliESD"; break;
1952 case kAOD: fnPattern = "AliAOD"; break;
e01b1d30 1953 case kUser: fnPattern = ""; break;
1d86b7ca 1954 }
1955
1956 // Assume failure
1957 Bool_t ret = false;
1958
1959 // Get list of files, and go back to old working directory
1960 TString oldDir(gSystem->WorkingDirectory());
1961 TList* files = dir->GetListOfFiles();
1962 if (!gSystem->ChangeDirectory(oldDir)) {
1963 Error("ScanDirectory", "Failed to go back to %s", oldDir.Data());
1964 return false;
1965 }
1966 if (!files) return false;
1967
1968 TList toAdd;
1969 toAdd.SetOwner();
e01b1d30 1970 Bool_t hasGAlice = (!fMC ? true : false);
1971 Bool_t hasKine = (!fMC ? true : false);
1972 Bool_t hasTrRef = (!fMC ? true : false);
1d86b7ca 1973
1974 // Sort list of files and check if we should add it
1975 files->Sort();
1976 TIter next(files);
1977 TSystemFile* file = 0;
1978 while ((file = static_cast<TSystemFile*>(next()))) {
1979 TString name(file->GetName());
1980 TString title(file->GetTitle());
1981 TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data()));
1982 if (dynamic_cast<TSystemDirectory*>(file)) full = title;
1983 // Ignore special links
1984 if (name == "." || name == "..") {
1985 // Info("ScanDirectory", "Ignoring %s", name.Data());
1986 continue;
1987 }
1988
1989 FileStat_t fs;
1990 if (gSystem->GetPathInfo(full.Data(), fs)) {
1991 Warning("ScanDirectory", "Cannot stat %s (%s)", full.Data(),
1992 gSystem->WorkingDirectory());
1993 continue;
1994 }
1995 // Check if this is a directory
1996 if (file->IsDirectory(full)) {
1997 if (recursive) {
1998 // if (title[0] == '/')
1999 TSystemDirectory* d = new TSystemDirectory(file->GetName(),
2000 full.Data());
e01b1d30 2001 if (ScanDirectory(d,chain,recursive))
1d86b7ca 2002 ret = true;
2003 delete d;
2004 }
2005 continue;
2006 }
2007
2008 // If this is not a root file, ignore
2009 if (!name.EndsWith(".root")) continue;
2010
2011 // If this file does not contain AliESDs, ignore
2012 if (!name.Contains(fnPattern)) {
2013 // Info("ScanDirectory", "%s does not match pattern %s",
2014 // name.Data(), fnPattern.Data());
e01b1d30 2015 if (fMC) {
1d86b7ca 2016 if (name.CompareTo("galice.root") == 0) hasGAlice = true;
2017 if (name.CompareTo("Kinematics.root") == 0) hasKine = true;
2018 if (name.CompareTo("TrackRefs.root") == 0) hasTrRef = true;
2019 }
2020 continue;
2021 }
2022
2023 // Add
2024 // Info("ScanDirectory", "Adding %s", full.Data());
2025 toAdd.Add(new TObjString(full));
2026 }
2027
e01b1d30 2028 if (fMC && toAdd.GetEntries() > 0 &&
1d86b7ca 2029 (!hasGAlice || !hasKine || !hasTrRef)) {
2030 Warning("ScanDirectory",
2031 "one or more of {galice,Kinematics,TrackRefs}.root missing from "
2032 "%s, not adding anything from this directory",
2033 dir->GetTitle());
2034 toAdd.Delete();
2035 }
2036
2037 TIter nextAdd(&toAdd);
2038 TObjString* s = 0;
0c4ed5fc 2039 Int_t added = 0;
1d86b7ca 2040 while ((s = static_cast<TObjString*>(nextAdd()))) {
2041 // Info("ScanDirectory", "Adding %s", s->GetString().Data());
0c4ed5fc 2042 TString fn = s->GetString();
2043 if (!CheckFile(fn, chain)) continue;
2044
2045 added++;
1d86b7ca 2046 }
0c4ed5fc 2047 if (added > 0) ret = true;
1d86b7ca 2048
2049 gSystem->ChangeDirectory(oldDir);
2050 return ret;
2051 }
e01b1d30 2052 //------------------------------------------------------------------
1d86b7ca 2053 /**
2054 * Create a chain from an XML containing an collection
2055 *
2056 * @param treeName Name of tree's
2057 * @param xmlFile XML collection
2058 *
2059 * @return Newly allocated chain or null
2060 */
2061 TChain* CreateChainFromXML(const char* treeName,
2062 const char* xmlFile)
2063 {
2064 TGridCollection* collection = TAlienCollection::Open(xmlFile);
2065 if (!collection) {
2066 Error("CreateChainFromXML", "Cannot create AliEn collection from "
2067 "XML file %s", xmlFile);
2068 return 0;
2069 }
2070
2071 TChain* chain = new TChain(treeName);
2072 collection->Reset();
2073 while (collection->Next()) chain->Add(collection->GetTURL(""));
2074
2075 return chain;
2076 }
e01b1d30 2077 //------------------------------------------------------------------
1d86b7ca 2078 /**
2079 * Create a chain of data
1d86b7ca 2080 *
2081 * @return TChain of data
2082 */
e01b1d30 2083 TChain* CreateChain()
1d86b7ca 2084 {
2085 TString treeName;
e01b1d30 2086 switch (fExecType) {
1d86b7ca 2087 case kESD: treeName = "esdTree"; break;
2088 case kAOD: treeName = "aodTree"; break;
e01b1d30 2089 case kUser: treeName = ""; break;
1d86b7ca 2090 }
2091
2092 TChain* chain = 0;
e01b1d30 2093 switch (fExecMode) {
1d86b7ca 2094 case kProof:
2095 if (!fDataSet.IsNull()) break;
2096 // Otherwise fall through
2097 case kLocal:
2098 if (fXML.IsNull()) {
2099 chain = new TChain(treeName.Data());
2100 TString dir(fDataDir);
2101 if (dir == ".") dir = "";
2102 if (!dir.BeginsWith("/")) dir = Form("../%s", dir.Data());
0c4ed5fc 2103 FileStat_t stat;
2104 gSystem->GetPathInfo(dir, stat);
2105 if (!R_ISDIR(stat.fMode)) { // A file, check it
2106 if (!CheckFile(dir, chain)) {
2107 delete chain;
2108 chain = 0;
2109 }
2110 break;
2111 }
1d86b7ca 2112 TString savdir(gSystem->WorkingDirectory());
2113 TSystemDirectory d(gSystem->BaseName(dir.Data()), dir.Data());
e01b1d30 2114 if (!ScanDirectory(&d, chain, true)) {
1d86b7ca 2115 delete chain;
2116 chain = 0;
2117 }
2118 gSystem->ChangeDirectory(savdir);
2119 }
2120 else
2121 chain = CreateChainFromXML(treeName.Data(), fXML.Data());
2122 break;
2123 case kGrid: break; // Do nothing - we use plugin
2124 }
2125
2126 if (chain && chain->GetNtrees() <= 0) {
2127 delete chain;
2128 return 0;
2129 }
2130 return chain;
2131 }
e01b1d30 2132 /* @} */
2133
2134public:
2135 //====================================================================
2136 /**
2137 * Option class
2138 *
2139 */
2140 struct Option
2a276c75 2141 {
e01b1d30 2142 /**
2143 * Constructor
2144 *
2145 * @param name Option name
2146 * @param desc Option description
2147 * @param arg Option argument, if any
2148 */
2149 Option(const char* name, const char* desc, const char* arg="")
2150 : fName(name),
2151 fDesc(desc),
2152 fArg(arg),
2153 fIsSet(false),
2154 fValue("")
2155 {}
2156 /**
2157 * Process an option string.
2158 *
2159 * @param opt String to process
2160 *
2161 * @return true, if this handled the option, false otherwise
2162 */
2163 Bool_t Process(const TString& opt)
2164 {
2165 // Info("Option::Process", "Option %s processing %s",
2166 // fName.Data(), opt.Data());
2167 if (!opt.BeginsWith(fName, TString::kIgnoreCase)) return false;
2168
2169 // We've got a value
2170 fIsSet = true;
2a276c75 2171
e01b1d30 2172 // No argument options shouldn't set a value
2173 if (fArg.IsNull()) return true;
2174
2175 // Parse out value
2176 Int_t eq = opt.Index("=");
2177
2178 // Empty string is an OK value
2179 if (eq == kNPOS) return true;
2180
2181 TString tmp = opt(eq+1,opt.Length()-eq-1);
2182 fValue = tmp.Strip();
2183
2184 return true;
2a276c75 2185 }
e01b1d30 2186 /**
2187 * Get option value as a string
2188 *
2189 * @return Option value
2190 */
2191 const TString& AsString() const { return fValue; }
2192 /**
2193 * Get option value as a double
2194 *
2195 * @return Option value
2196 */
2197 Double_t AsDouble() const { return fValue.Atof(); }
2198 /**
2199 * Get option value as an integer
2200 *
2201 * @return Option value
2202 */
2203 Int_t AsInt() const { return fValue.Atoi(); }
2204 /**
2205 * Get option value as a boolean
2206 *
2207 * @return Option value
2208 */
2209 Bool_t AsBool() const { return fIsSet; }
2210 /**
2211 * Test if the option has been set.
2212 *
2213 * @return True if the option was given
2214 */
2215 Bool_t IsSet() const { return fIsSet; }
2216 /**
2217 * Print help.
2218 *
2219 * @param o Stream to write on
2220 * @param prefix Prefix
2221 */
2222 void PrintHelp(std::ostream& o, const char* prefix) const
2223 {
2224 TString arg(fName);
2225 if (!fArg.IsNull()) arg.Append(Form("=%s", fArg.Data()));
2226 o << " " << (prefix ? prefix : "")
2227 << std::left << std::setw(30) << arg
2228 << " " << fDesc << std::endl;
2a276c75 2229 }
e01b1d30 2230 /**
2231 * Print the setting
2232 *
2233 * @param o Stream to write on
2234 */
2235 void PrintSettings(std::ostream& o) const
2236 {
2237 o << " " << std::left << std::setw(30) << fName << ": ";
2238 if (fArg.IsNull()) o << (IsSet() ? "true" : "false");
2239 else o << fValue;
2240 o << std::endl;
2a276c75 2241 }
e01b1d30 2242 /**
2243 * Save the setting
2244 *
2245 * @param str object nmae
2246 * @param val Value
2247 * @param o Stream to write on
2248 */
2249 void Save(std::ostream& o, const char* str, bool val)
2250 {
2251 if (!val) return;
2252 if (str[0] == '-') {
2253 o << " " << str << fName << " \\" << std::endl;
2254 return;
2255 }
2256 o << " " << str << ".Append(\"" << fName << ",\");" << std::endl;
2a276c75 2257 }
e01b1d30 2258 /**
2259 * Save the setting
2260 *
2261 * @param str object nmae
2262 * @param val Value
2263 * @param o Stream to write on
2264 */
2265 void Save(std::ostream& o, const char* str, Int_t val)
2266 {
2267 if (str[0] == '-') {
2268 o << " " << str << fName << "=" << val << " \\" << std::endl;
2269 return;
2270 }
2271 o << " " << str << ".Append(\"" << fName << "=" << val
2272 << ",\");" << std::endl;
2273 }
2274 /**
2275 * Save the setting
2276 *
2277 * @param str object nmae
2278 * @param val Value
2279 * @param o Stream to write on
2280 */
2281 void Save(std::ostream& o, const char* str, Double_t val)
2282 {
2283 if (str[0] == '-') {
2284 o << " " << str << fName << "=" << val << " \\" << std::endl;
2285 return;
2286 }
2287 o << " " << str << ".Append(\"" << fName << "=" << val
2288 << ",\");" << std::endl;
2289 }
2290 /**
2291 * Save the setting
2292 *
2293 * @param str object nmae
2294 * @param val Value
2295 * @param o Stream to write on
2296 */
2297 void Save(std::ostream& o, const char* str, const char* val)
2298 {
2299 if (str[0] == '-') {
2300 TString sval(val);
2301 sval.ReplaceAll(" ", "\\ ");
2302 o << " " << str << fName << "=" << sval << " \\" << std::endl;
2303 return;
2304 }
2305 o << " " << str << ".Append(\"" << fName << "=" << val
2306 << ",\");" << std::endl;
2307 }
2308
2309 TString fName; // Name of the option
2310 TString fDesc; // Decription
2311 TString fArg; // Argument, if any
2312 Bool_t fIsSet; // Whether the option has been set.
2313 TString fValue; // Value of the option.
2314 };
2315 //====================================================================
2316 /**
2317 * Run a train setup
2318 *
2319 */
2320 struct Runner
2a276c75 2321 {
e01b1d30 2322 /**
2323 * Constructor
2324 *
2325 * @param train Train to run
2326 * @param max Maximum number of options
2327 */
2328 Runner(TrainSetup& train, UShort_t max=30)
2329 : fTrain(&train), fOptions(0), fN(0), fMax(max)
2330 {
2331 fOptions = new Option*[fMax];
2332 for (Int_t i = 0; i < fMax; i++) fOptions[i] = 0;
2333 }
2334 /**
2335 * Add an option
2336 *
2337 * @param opt Option to add
2338 */
2339 void Add(Option* opt)
2340 {
2341 if (fN >= fMax) {
2342 Warning("AddOption", "No room for option %s", opt->fName.Data());
2343 return;
2344 }
2345 fOptions[fN++] = opt;
2346 }
2347 /**
2348 * Remove an option
2349 *
2350 * @param name
2351 */
2352 void Remove(const TString& name)
2353 {
2354 Option** ptr = fOptions;
2355 Option** tmp = 0;
2356 while (*ptr) {
2357 if (name.EqualTo((*ptr)->fName)) {
2358 tmp = ptr;
2359 break;
2360 }
2361 ptr++;
2362 }
2363 if (!tmp) // nothing found, returning
2364 return;
2365
2366 ptr = tmp;
2367 delete *tmp;
2368 tmp++;
2369 fN--;
2370 while (*tmp) {
2371 *ptr = *tmp;
2372 ptr++;
2373 tmp++;
2374 }
2375 *ptr = 0;
2376 }
2377
2378 /**
2379 * Parse option string
2380 *
2381 * @param options Option string.
2382 * @param delim Delimiters
2383 *
2384 * @return true on success.
2385 */
2386 Bool_t Parse(const TString& options, const char* delim=",;")
2387 {
2388 TObjArray* a = options.Tokenize(delim);
2389 return Parse(*a);
2390 }
2391 /**
2392 * Parse options
2393 *
2394 * @param options
2395 *
2396 * @return true on success
2397 */
2398 Bool_t Parse(TObjArray& options)
2399 {
2400 TIter next(&options);
2401 TObjString* os = 0;
2402 while ((os = static_cast<TObjString*>(next()))) {
2403 TString s(os->String());
2404 // Info("Runner::Parse", "Processing option %s", s.Data());
2405 if (s.IsNull()) continue;
2406
2407 Bool_t ok = false;
2408 Option** ptr = fOptions;
2409 while (*ptr && !ok) {
2410 Option* o = *ptr;
2411 if (o->Process(s)) ok = true;
2412 ptr++;
2413 }
2414
2415 if (!ok)
2416 Warning("Parse", "Unknown option %s", s.Data());
2417 }
2418 return true;
2419 }
2420 /**
2421 * Check if we asked for help
2422 *
2423 *
2424 * @return
2425 */
2426 Bool_t IsHelpAsked() const
2427 {
2428 Option* help = FindOption("help");
2429 return (help && help->IsSet());
2430 }
2431 /**
2432 * Print help
2433 *
2434 * @param out Stream to write on
2435 * @param prefix Prefix
2436 */
2437 void PrintHelp(std::ostream& out, const char* prefix="") const
2438 {
2439 Option** ptr = fOptions;
2440 while (*ptr) {
2441 (*ptr)->PrintHelp(out, prefix);
2442 ptr++;
2443 }
2444 }
2445 /**
2446 * Print the settings
2447 *
2448 * @param out Stream to write on.
2449 */
2450 void PrintSettings(std::ostream& out) const
2451 {
2452 Option** ptr = fOptions;
2453 while (*ptr) {
2454 (*ptr)->PrintSettings(out);
2455 ptr++;
2456 }
2457 }
2458 /**
2459 * Find an option by name
2460 *
2461 * @param name Name of option to find
2462 *
2463 * @return Pointer to option, or null
2464 */
2465 Option* FindOption(const TString& name) const
2466 {
2467 Option** ptr = fOptions;
2468 while (*ptr) {
2469 if (name.EqualTo((*ptr)->fName)) return *ptr;
2470 ptr++;
2471 }
2472 return 0;
2473 }
2474 /**
2475 * Initialize the train
2476 *
2477 * @param options Execution options
2478 *
2479 * @return true on success
2480 */
2481 Bool_t Init(const TString& options)
2482 {
2483 fTrain->MakeOptions(*this);
2484 if (!Parse(options)) return false;
2485 return true;
2486 }
2487 /**
2488 * Run the train
2489 *
2490 * @param runs Run numbers
2491 * @param nEvents Number of events
2492 * @param asShell Save set-up as shell script
2493 *
2494 * @return
2495 */
2496 Bool_t Run(const TString& runs, Int_t nEvents, Bool_t asShell=false)
2497 {
2498 PrintSettings(std::cout);
2499
2500 fTrain->SetOptions(*this);
2501 fTrain->SetRuns(runs);
2502 // fTrain->SaveSetup(*this, nEvents, asShell);
2503
2504 fTrain->Run(nEvents, this, asShell);
2505 return true;
2506 }
2507
2508 TrainSetup* fTrain;
2509 Option** fOptions; // Our options
2510 UShort_t fN; // Current number of options
2511 UShort_t fMax; // Maximum number of options
2512 };
2513protected:
2a276c75 2514 //__________________________________________________________________
e01b1d30 2515 /**
2516 * @{
2517 * @name Options
2518 */
2519 /**
2520 * Class name of this train setup. Sub-classes must define this.
2521 *
2522 * @return Class name of this setup
2523 */
2524 virtual const char* ClassName() const = 0;
2525 //------------------------------------------------------------------
2526 /**
2527 * Make the options for this train. Sub-classes can overload this
2528 * to define new options, or append to the set of default option.
2529 */
2530 virtual void MakeOptions(Runner& r)
2a276c75 2531 {
e01b1d30 2532 r.Add(new Option("help", "Show this help"));
2533 r.Add(new Option("par", "Use PAR files (PROOF and Grid)"));
2534 r.Add(new Option("mc", "Assume simulation input"));
2535 r.Add(new Option("debug", "Execute in debugger"));
2536 r.Add(new Option("type", "Type of train", "AOD|ESD"));
2537 r.Add(new Option("mode", "Execution mode", "LOCAL|PROOF|GRID"));
2538 r.Add(new Option("oper", "Operation mode", "TEST|TERMINATE|FULL|INIT"));
2539 r.Add(new Option("date", "Set date string", "YYYY-MM-DD HH:MM:SS"));
2540 r.Add(new Option("cluster","PROOF cluster", "HOST"));
2541 r.Add(new Option("dataSet","Data set (PROOF only)", "NAME"));
2542 r.Add(new Option("dataDir","Data directory", "DIRECTORY"));
2543 r.Add(new Option("pattern","Data pattern (grid only)", "GLOB"));
2544 r.Add(new Option("verb", "Verbosity", "NUMBER"));
2545 r.Add(new Option("root", "ROOT version (Grid)", "TAG"));
2546 r.Add(new Option("aliroot","AliROOT version (Grid)","TAG"));
2547 r.Add(new Option("alien", "AliEn API version (Grid)","TAG"));
2548 r.Add(new Option("overwrite", "Allow overwrite"));
2549 r.Add(new Option("per-run", "Per run merge"));
2a276c75 2550 }
e01b1d30 2551 //------------------------------------------------------------------
2552 /**
2553 * Set the option values on the train. Sub-classes can overload
2554 * this to set custom options on the train.
2555 */
2556 virtual void SetOptions(Runner& r)
2a276c75 2557 {
e01b1d30 2558 Option* debug = r.FindOption("debug");
2559 Option* date = r.FindOption("date");
2560 Option* cluster = r.FindOption("cluster");
2561 Option* dataSet = r.FindOption("dataSet");
2562 Option* dataDir = r.FindOption("dataDir");
2563 Option* pattern = r.FindOption("pattern");
2564 Option* par = r.FindOption("par");
2565 Option* type = r.FindOption("type");
2566 Option* mode = r.FindOption("mode");
2567 Option* oper = r.FindOption("oper");
2568 Option* mc = r.FindOption("mc");
2569 Option* verb = r.FindOption("verb");
2570 Option* root = r.FindOption("root");
2571 Option* aliroot = r.FindOption("aliroot");
2572 Option* alien = r.FindOption("alien");
2573 Option* overwrite = r.FindOption("overwrite");
2574 Option* run_merge = r.FindOption("per-run");
2575
2576 if (date && date->IsSet()) SetDateTime(date->AsString());
2577 if (cluster) SetProofServer(cluster->AsString());
2578 if (dataSet) SetDataSet(dataSet->AsString());
2579 if (dataDir) SetDataDir(dataDir->AsString());
2580 if (pattern) SetDataPattern(pattern->AsString());
2581 if (debug) SetUseGDB(debug->AsBool());
2582 if (type && type->IsSet()) SetType(type->AsString());
2583 if (mode && mode->IsSet()) SetMode(mode->AsString());
2584 if (oper && oper->IsSet()) SetOperation(oper->AsString());
2585 if (par) SetUsePar(par->AsBool());
2586 if (mc) SetMC(mc->AsBool());
2587 if (verb) SetVerbose(verb->AsInt());
2588 if (root) SetROOTVersion(root->AsString());
2589 if (aliroot) SetAliROOTVersion(aliroot->AsString());
2590 if (alien) SetAliEnAPIVersion(alien->AsString());
2591 if (overwrite) SetAllowOverwrite(overwrite->AsBool());
2592 if (run_merge) SetPerRunMerge(run_merge->AsBool());
2a276c75 2593 }
e01b1d30 2594 //------------------------------------------------------------------
2595 /**
2596 * Set the option values on the train. Sub-classes can overload
2597 * this to set custom options on the train.
2598 */
2599 virtual void SaveOptions(std::ostream& o, const char* str, Runner& r)
2a276c75 2600 {
e01b1d30 2601 Option* debug = r.FindOption("debug");
2602 Option* date = r.FindOption("date");
2603 Option* cluster = r.FindOption("cluster");
2604 Option* dataSet = r.FindOption("dataSet");
2605 Option* dataDir = r.FindOption("dataDir");
2606 Option* pattern = r.FindOption("pattern");
2607 Option* par = r.FindOption("par");
2608 Option* type = r.FindOption("type");
2609 Option* mode = r.FindOption("mode");
2610 Option* oper = r.FindOption("oper");
2611 Option* mc = r.FindOption("mc");
2612 Option* verb = r.FindOption("verb");
2613 Option* root = r.FindOption("root");
2614 Option* aliroot = r.FindOption("aliroot");
2615 Option* alien = r.FindOption("alien");
2616 Option* overwrite = r.FindOption("overwrite");
2617 Option* run_merge = r.FindOption("per-run");
2618
2619 if (date) date->Save(o, str,
2620 Form("%04d-%02d-%02d %02d:%02d:00",
2621 fDatime.GetYear(),
2622 fDatime.GetMonth(),
2623 fDatime.GetDay(),
2624 fDatime.GetHour(),
2625 fDatime.GetMinute()));
2626 if (cluster) cluster->Save(o, str, fProofServer);
2627 if (dataSet) dataSet->Save(o, str, fDataSet);
2628 if (dataDir) dataDir->Save(o, str, fDataDir);
2629 if (pattern) pattern->Save(o, str, fDataPattern);
2630 if (debug) debug->Save(o, str, fUseGDB);
2631 if (type) type->Save(o, str, TypeString(fExecType));
2632 if (mode) mode->Save(o, str, ModeString(fExecMode));
2633 if (oper) oper->Save(o, str, OperString(fExecOper));
2634 if (par) par->Save(o, str, fUsePar);
2635 if (mc) mc->Save(o, str, fMC);
2636 if (verb) verb->Save(o, str, fVerbose);
2637 if (root) root->Save(o, str, fRootVersion);
2638 if (aliroot) aliroot->Save(o, str, fAliRootVersion);
2639 if (alien) alien->Save(o, str, fAliEnAPIVersion);
2640 if (overwrite)overwrite->Save(o, str, fAllowOverwrite);
2641 if (run_merge)run_merge->Save(o, str, fPerRunMerge);
2a276c75 2642 }
e01b1d30 2643 /**
2644 * Save the setup to file for later re-execution
2645 *
2646 * @param r Runner object
2647 * @param nEvents Number of events
2648 * @param asShell If true, save as shell script - otherwise ROOT script
2649 */
2650 virtual void SaveSetup(Runner& r, Int_t nEvents, Bool_t asShell=false)
2a276c75 2651 {
e01b1d30 2652 if (asShell) SaveSetupShell(r, nEvents);
2653 /* else */ SaveSetupROOT(r, nEvents);
2a276c75 2654 }
e01b1d30 2655 /**
2656 * Save the setup to shell script for later re-execution
2657 *
2658 * @param r Runner object
2659 * @param nEvents Number of events
2660 */
2661 virtual void SaveSetupShell(Runner& r, Int_t nEvents)
2a276c75 2662 {
e01b1d30 2663 std::ofstream o("rerun.sh");
2664 o << "#!/bin/bash\n\n"
2665 << "oper=$1\n"
2666 << "if test x$oper = x ; then oper=full ; fi \n\n"
2667 << "class=\"" << ClassName() << "\"\n"
2668 << "name=\"" << fName << "\"\n"
2669 << "nev=" << nEvents << "\n\n"
2670 << "opts=(--class=$class \\\n"
2671 << " --name=$name \\\n"
2672 << " --events=$nev \\" << std::endl;
2a276c75 2673 for (Int_t i = 0; i < fRunNumbers.GetSize(); i++)
e01b1d30 2674 o << " --run=" << fRunNumbers.At(i) << " \\\n";
2675 SaveOptions(o, "--", r);
2676 o << " --oper=$oper)\n\n"
2677 << "echo \"Running runTrain ${opts[@]}\"\n"
2678 << "runTrain \"${opts[@]}\"\n\n"
6ff251d8 2679 << "# EOF" << std::endl;
e01b1d30 2680 o.close();
2681 gSystem->Exec("chmod a+x rerun.sh");
2a276c75 2682 }
e01b1d30 2683 /**
2684 * Save the setup to shell script for later re-execution
2685 *
2686 * @param r Runner object
2687 * @param nEvents Number of events
2688 */
2689 virtual void SaveSetupROOT(Runner& r, Int_t nEvents)
2a276c75 2690 {
e01b1d30 2691 std::ofstream o("rerun.C");
2692 o << "void rerun(bool terminate=false)\n"
2693 << "{\n"
2694 << " TString opts;" << std::endl;
2695 SaveOptions(o, "opts", r);
2696
2697 o << " if (terminate) opts.Append(\"mode=terminate;\");\n\n"
2698 << " TString runs(\"";
2699 for (Int_t i = 0; i < fRunNumbers.GetSize(); i++)
2700 o << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
2701 o << "\");\n\n"
2702 << " Int_t nEvents = " << nEvents << ";\n\n"
2703 << " gROOT->LoadMacro(\"$ALICE_ROOT/PWGLF/FORWARD/analysis2/trains/RunTrain.C\");\n"
2704 << " RunTrain(\"" << ClassName() << "\",\""
2705 << fName << "\",opts,runs,nEvents);\n"
2706 << "}\n"
2707 << "// EOF" << std::endl;
2a276c75 2708 o.close();
2709 }
e01b1d30 2710 /* @} */
2711
2a276c75 2712 //__________________________________________________________________
1d86b7ca 2713 TString fName; // Name of analysis
2a276c75 2714 TString fEscapedName; // Name escaped for special chars
1d86b7ca 2715 TString fRootVersion; // ROOT version to use
2716 TString fAliRootVersion; // AliROOT version to use
2717 TString fAliEnAPIVersion; // AliEn API version to use
2718 TString fProofServer; // Name of proof server
2719 TString fDataDir; // Grid Input directory
e01b1d30 2720 TString fDataPattern; // Data directory pattern
1d86b7ca 2721 TString fDataSet; // Proof data set name
2722 TString fXML; // XML collection for local/proof mode
1d86b7ca 2723 Int_t fNReplica; // Storage replication
871a9ac1 2724 Bool_t fAllowOverwrite; // Allow overwriting output dir
2725 Bool_t fUseGDB; // Wrap PROOF slaves in GDB
2a276c75 2726 Int_t fMaxSplit; // Maximum number of files per split
2727 TArrayI fRunNumbers; // List of run number
2728 TList fListOfPARs; // List of PAR files to use
2729 TList fListOfSources; // List of sources to upload and AcLIC
2730 TList fListOfLibraries; // List of libraries to load
2731 TList fListOfExtras; // List of extra files to upload
e01b1d30 2732 TDatime fDatime; // Date and time
2733 EType fExecType; // Execution type (ESD, AOD)
2734 EMode fExecMode; // Execution mode (PROOF, local, Grid)
2735 EOper fExecOper; // Execution operation (full, terminate, ...)
2736 Bool_t fUsePar; // Wether to use PAR files
2737 Bool_t fMC; // Whether to assume MC input
2738 Bool_t fPerRunMerge; // Whether to merge per run or over-all
2739 Int_t fVerbose; // Verbosity level
1d86b7ca 2740};
1d86b7ca 2741
2742//____________________________________________________________________
2743//
2744// EOF
2745//