]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/trains/TrainSetup.C
Added option to Grid railway to allow adding additional excludes.
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / TrainSetup.C
CommitLineData
fdfd93b4 1/**
67a4bb96 2 * @defgroup pwglf_forward_trains Trains.
fdfd93b4 3 *
67a4bb96
CHC
4 * Train specifications.
5 * See also @ref train_setup_doc
fdfd93b4 6 */
7/**
8 * @file TrainSetup.C
9 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
10 * @date Tue Oct 16 17:56:57 2012
11 *
12 * @brief Base classs for train specifications
13 *
14 * @ingroup pwglf_forward_trains
15 */
16#ifndef TRAINSETUP_C
17#define TRAINSETUP_C
18#ifndef __CINT__
19# include "Helper.C"
20# include "Option.C"
21# include <TDatime.h>
22# include <TUrl.h>
23# include <TString.h>
24# include <TApplication.h>
ddcc1bbd 25# include <TStopwatch.h>
fdfd93b4 26# include <AliAnalysisManager.h>
27# include <AliVEventHandler.h>
28# include <AliPhysicsSelection.h>
29# include <AliPhysicsSelectionTask.h>
30# include <AliCentralitySelectionTask.h>
31# include <AliESDInputHandler.h>
32# include <AliAODInputHandler.h>
33# include <AliAODHandler.h>
34# include <AliMCEventHandler.h>
46b25775 35# include <ctime>
fdfd93b4 36#else
37struct Helper;
38struct OptionList;
39class TDatime;
40class TUrl;
41class TString;
ddcc1bbd 42class TStopwatch;
fdfd93b4 43class AliVEventHandler;
44class AliAnalysisManager;
45class AliInputEventHandler;
46#endif
47
48//====================================================================
49/**
ddcc1bbd 50 * Generic set-up of an analysis train
fdfd93b4 51 *
52 * See also @ref train_setup_doc
53 *
54 * @ingroup pwglf_forward_trains
55 *
56 */
57struct TrainSetup
58{
59 /**
60 * Constructor
61 *
62 * @param name Name of the train
63 */
64 TrainSetup(const TString& name)
65 : fName(name),
66 fEscapedName(name),
bfab35d9 67 fDatimeString(""),
46b25775 68 fOptions(),
6ee074b7 69 fHelper(0),
70 fMonitored("")
fdfd93b4 71 {
33438b4c 72 fOptions.Add("help", "Show help", false);
fdfd93b4 73 fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now");
33438b4c 74 fOptions.Add("bare-ps", "Use bare physics selection w/o task", false);
a80dde0d 75 fOptions.Add("verbose", "LEVEL", "Set verbosity level", 0);
33438b4c 76 fOptions.Add("url", "URL", "Job location & input URL", "");
77 fOptions.Add("overwrite", "Allow overwrite", false);
a80dde0d 78 fOptions.Add("events", "N", "Number of events to analyse", -1);
33438b4c 79 fOptions.Add("type", "ESD|AOD|USER", "Input data stype", "");
80 fOptions.Add("setup", "Only do the setup", false);
81 fOptions.Add("branches", "Load only requested branches", false);
bfab35d9 82 fDatimeString = "";
83 fEscapedName = EscapeName(fName, fDatimeString);
fdfd93b4 84 }
8449e3e0 85 /**
86 * Copy constructor
87 *
88 * @param o Object to copy from
89 */
46b25775 90 TrainSetup(const TrainSetup& o)
91 : fName(o.fName),
92 fEscapedName(o.fEscapedName),
bfab35d9 93 fDatimeString(o.fDatimeString),
46b25775 94 fOptions(o.fOptions),
6ee074b7 95 fHelper(o.fHelper),
96 fMonitored(o.fMonitored)
46b25775 97 {}
8449e3e0 98 /**
99 * Assignment operator
100 *
101 * @param o Object to assign from
102 *
103 * @return Reference to this object
104 */
46b25775 105 TrainSetup& operator=(const TrainSetup& o)
106 {
107 if (&o == this) return *this;
bfab35d9 108 fName = o.fName;
109 fEscapedName = o.fEscapedName;
110 fDatimeString = o.fDatimeString;
111 fOptions = o.fOptions;
112 fHelper = o.fHelper;
6ee074b7 113 fMonitored = o.fMonitored;
46b25775 114 return *this;
115 }
116
fdfd93b4 117 /**
118 * Destructor
119 */
120 virtual ~TrainSetup() {}
121 /* @} */
122 //__________________________________________________________________
123 /**
124 * @{
125 * @name Execution
126 */
127 /**
128 * Initialize
129 *
130 * @return true on success
131 */
132 Bool_t Init()
133 {
134 // --- Create the helper -----------------------------------------
135 TString url = fOptions.Get("url");
136 Int_t verbose = fOptions.AsInt("verbose");
fdfd93b4 137
138 fHelper = Helper::Create(url.Data(), verbose);
139 if (!fHelper) {
140 Error("Init", "Failed to make the worker for URL %s", url.Data());
141 return false;
142 }
143
46b25775 144 // --- Check the type, if possible -------------------------------
fdfd93b4 145 UShort_t type = fHelper->InputType();
a54cc77b 146 Bool_t mc = fHelper->IsMC();
fdfd93b4 147 if (fOptions.Has("type")) {
148 const TString& it = fOptions.Get("type");
149 if (it.EqualTo("ESD",TString::kIgnoreCase)) type = Helper::kESD;
150 else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Helper::kAOD;
151 else if (it.EqualTo("user",TString::kIgnoreCase))
152 type = Helper::kUser;
153 }
154
46b25775 155 // --- Rewrite the escpaed name ----------------------------------
156 if (fOptions.Has("date")) {
bfab35d9 157 fDatimeString = fOptions.Get("date");
158 fEscapedName = EscapeName(fName, fDatimeString);
46b25775 159 }
160
fdfd93b4 161 // --- Get current directory and set-up sub-directory ------------
162 TString cwd = gSystem->WorkingDirectory();
163 if (!SetupWorkingDirectory()) return false;
164
165 // --- Do initial helper setup -----------------------------------
166 if (!fHelper->PreSetup()) return false;
167
168 // --- Load ROOT libraries ---------------------------------------
169 if (!fHelper->LoadROOT()) return false;
170
171 // --- Load AliROOT libraries ------------------------------------
172 if (!fHelper->LoadAliROOT()) return false;
173
174 // --- Create analysis manager -----------------------------------
a80dde0d 175 AliAnalysisManager *mgr = CreateAnalysisManager(fEscapedName);
fdfd93b4 176
177 // In test mode, collect system information on every event
178 // if (oper == kTest) mgr->SetNSysInfo(1);
179 if (verbose > 0) mgr->SetDebugLevel(verbose);
a54cc77b 180 mgr->SetAutoBranchLoading(!fOptions.Has("branches"));
fdfd93b4 181 if (fHelper->Mode() == Helper::kLocal)
182 mgr->SetUseProgressBar(kTRUE, 100);
183
184 // --- ESD input handler ------------------------------------------
185 AliVEventHandler* inputHandler = CreateInputHandler(type);
186 if (inputHandler) mgr->SetInputEventHandler(inputHandler);
187
188 // --- Monte-Carlo ------------------------------------------------
189 AliVEventHandler* mcHandler = CreateMCHandler(type,mc);
190 if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
191
192 // --- AOD output handler -----------------------------------------
193 AliVEventHandler* outputHandler = CreateOutputHandler(type);
194 if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
195
196 // --- Include analysis macro path in search path ----------------
197 gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
198 cwd.Data(), gROOT->GetMacroPath()));
199
200 // --- Physics selction - only for ESD ---------------------------
201 if (type == Helper::kESD) CreatePhysicsSelection(mc, mgr);
202
203 // --- Create centrality task ------------------------------------
204 CreateCentralitySelection(mc, mgr);
205
206 // --- Create tasks ----------------------------------------------
207 CreateTasks(mgr);
208
6ee074b7 209 // --- Create monitor objects ------------------------------------
210 CreateMonitors();
211
fdfd93b4 212 // --- Post set-up initialization of helper ----------------------
213 if (!fHelper->PostSetup()) return false;
214
215 // --- Set debug level on defined tasks --------------------------
216 if (verbose > 0) {
217 TIter next(mgr->GetTasks());
218 AliAnalysisTask* sub = 0;
219 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
220 AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
221 if (!se) continue;
222 se->SetDebugLevel(verbose);
223 }
224 }
225
226 // --- Print this setup ------------------------------------------
227 Print();
228
229 // --- Initialise the train --------------------------------------
230 if (!mgr->InitAnalysis()) {
231 gSystem->ChangeDirectory(cwd.Data());
232 Error("Init","Failed to initialise train");
233 return false;
234 }
235
236 // --- Enable progress bar ---------------------------------------
237 if (fHelper->Mode() != Helper::kGrid)
238 mgr->SetUseProgressBar(true, 100);
239
240 // --- Save setup to disk ----------------------------------------
241 SaveSetup(true);
242
ddcc1bbd 243 // --- Some information ------------------------------------------
fdfd93b4 244 mgr->PrintStatus();
ddcc1bbd 245 if (fHelper->Mode() != Helper::kLocal) {
246 TIter next(mgr->GetTasks());
247 AliAnalysisTask* sub = 0;
248 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
249 sub->Print();
250 }
251 }
fdfd93b4 252 return true;
253 }
8449e3e0 254 /**
255 * Print timer information
256 *
257 * @param timer The timer
258 * @param where Where this was called from
259 */
ddcc1bbd 260 void PrintTimer(TStopwatch& timer, const char* where)
261 {
262 timer.Stop();
263 Double_t t = timer.RealTime();
264 Int_t h = Int_t(t / 3600); t -= h * 3600;
265 Int_t m = Int_t(t / 60); t -= m * 60;
266 if (t < 0) t = 0;
267 Info(where, "took %4d:%02d:%06.3f", h, m, t);
268 }
8449e3e0 269 /**
270 * Run this train
271 *
272 * @return true on success
273 */
a80dde0d 274 Bool_t Run()
fdfd93b4 275 {
276 TString cwd = gSystem->WorkingDirectory();
277 Bool_t status = false;
ddcc1bbd 278 TStopwatch timer;
279 timer.Start();
fdfd93b4 280 try {
281 if (!Init()) throw TString("Failed to intialize the train");
ddcc1bbd 282 PrintTimer(timer, "Initialization");
283 timer.Continue();
284
a80dde0d 285 // Check if we're asked to only do the setup
286 if (fOptions.Has("setup")) {
287 status = true;
288 throw TString("Only did setup, no running");
289 }
290
fdfd93b4 291 // if (r) SaveSetup(*r, nEvents, asShell);
292
293 Long64_t nEvents = fOptions.AsLong("events", -1);
294 Long64_t ret = fHelper->Run(nEvents);
ddcc1bbd 295 PrintTimer(timer, "Processing");
296 timer.Continue();
fdfd93b4 297
298 // Make sure we go back
299 gSystem->ChangeDirectory(cwd.Data());
300
301 // Return.
302 if (ret < 0) throw TString("Analysis failed");
303
304 status = true;
305 }
306 catch (TString& e) {
a54cc77b 307 if (status) Warning("Run", "%s", e.Data());
308 else Error("Run", "%s", e.Data());
ddcc1bbd 309 }
310 if (fOptions.Has("date")) {
bfab35d9 311 TString tmp = "";
312 TString escaped = EscapeName(fName, tmp);
ddcc1bbd 313 gSystem->Exec(Form("rm -f last_%s", escaped.Data()));
314 gSystem->Exec(Form("ln -sf %s last_%s",
315 fEscapedName.Data(), escaped.Data()));
fdfd93b4 316 }
ddcc1bbd 317 PrintTimer(timer, "Finish");
318 timer.Continue();
a80dde0d 319 return status;
fdfd93b4 320 }
321 /**
322 * Get the options
323 *
324 *
325 * @return Reference ot the options
326 */
327 OptionList& Options() { return fOptions; }
328 /**
329 * Print information to standard output
330 *
331 */
332 void Print(Option_t* ="") const
333 {
334 std::cout << "Train: " << fName << " (" << fEscapedName << ")"
335 << std::endl;
336 fOptions.Show(std::cout);
337 if (fHelper) fHelper->Print();
338 }
339 /**
340 * Show the help
341 *
33438b4c 342 * @param o Output stream
343 * @param asProg If true, output as program options
fdfd93b4 344 *
345 * @return
346 */
347 Bool_t Help(std::ostream& o=std::cout, bool asProg=false)
348 {
349 if (!fOptions.Has("help")) return true;
350
73b32206 351 if (!asProg)
fdfd93b4 352 o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
353
73b32206 354 o << "\n\nTrain Options:\n";
355 fOptions.Help(o, asProg ? " --" : " ");
fdfd93b4 356 o << "\n";
357
358 if (!fHelper && fOptions.Has("url")) {
359 TString url = fOptions.Get("url");
360 fHelper = Helper::Create(url.Data());
361 }
362 if (fHelper) {
363 o << fHelper->Desc() << " URL form:\n\n"
364 << " " << fHelper->UrlHelp() << "\n\n"
365 << "Options:\n";
366 fHelper->Options().Help(o, " ");
367 o << "\n";
368 }
369 else {
370 o << "Possible URL forms:\n\n";
371 Helper::ShowUrlHelp("LocalHelper");
372 Helper::ShowUrlHelp("ProofHelper");
373 Helper::ShowUrlHelp("LiteHelper");
374 Helper::ShowUrlHelp("AAFHelper");
375 Helper::ShowUrlHelp("AAFPluginHelper");
376 Helper::ShowUrlHelp("GridHelper");
377 o << "\n";
378 }
379 return false;
380 }
381 /**
382 * Run train. This will AcLic compile the setup script, create
383 * an object of that type with the given name, and then pass the
384 * options to it. Then, it will run the setup.
385 *
33438b4c 386 * @param name Train name
387 * @param cls Class name
388 * @param opts Comma seperated list of options
389 * @param asProg Run as program
390 * @param spawn Spawn ROOT shell after execution
fdfd93b4 391 *
392 * @return true on success
393 */
394 static Bool_t Main(const TString& name, const TString& cls,
395 const TCollection* opts,
73b32206 396 Bool_t asProg=true,
397 Bool_t spawn=false)
fdfd93b4 398 {
a80dde0d 399 Bool_t ret = false;
400 try {
401 if (cls.IsNull())
402 throw TString("No class name specified");
403 if (name.IsNull())
404 throw TString("No train name specified");
fdfd93b4 405
73b32206 406 gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"w\");");
a80dde0d 407 Int_t error = 0;
8449e3e0 408 Int_t r1 = gROOT->LoadMacro(Form("%s.C+g", cls.Data()), &error);
73b32206 409 gROOT->ProcessLine("gSystem->RedirectOutput(0);");
a80dde0d 410 if (r1 < 0 || error)
73b32206 411 throw TString::Format("Failed to load setup %s: %d - see build.log",
412 cls.Data(), error);
a80dde0d 413
414 // Make our object using the interpreter
415 TString create = TString::Format("new %s(\"%s\")",
416 cls.Data(), name.Data());
85f21ab4 417 gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"a\");");
a80dde0d 418 Long_t retP = gROOT->ProcessLine(create, &error);
419 gROOT->ProcessLine("gSystem->RedirectOutput(0);");
420 if (!retP || error)
85f21ab4 421 throw TString::Format("Failed to make object of class %s "
422 "(see build.log): 0x%08lx/%d\n\t%s",
a80dde0d 423 cls.Data(), retP, error, create.Data());
424
425 TrainSetup* train = reinterpret_cast<TrainSetup*>(retP);
fdfd93b4 426
a80dde0d 427 // Now parse the options
428 if (!train->Options().Parse(opts))
429 throw TString("Failed to parse options");
fdfd93b4 430
024ec5ac 431 // Info("", "URL=%s", train->Options().Get("url").Data());
33438b4c 432
a80dde0d 433 // Check if we got a help request
434 if (train->Options().Has("help")) {
435 train->Help(std::cout, asProg);
436 ret = true;
437 throw TString("");
438 }
439
440 // return train->Init();
441 ret = train->Run();
442 }
443 catch (TString& e) {
a54cc77b 444 if (!e.IsNull()) Error("Main", "%s", e.Data());
a80dde0d 445 }
85f21ab4 446 // Info("Main", "End of main loop (app=%p, asProg=%s, spawn=%s)",
447 // gApplication, asProg ? "true" : "false", spawn ? "true" : "false");
a80dde0d 448 if (gApplication && asProg) {
73b32206 449 if (!spawn) {
450 gSystem->Sleep(3);
451 gApplication->Terminate(ret ? 0 : 1);
452 }
fdfd93b4 453 }
a80dde0d 454 return ret;
fdfd93b4 455 }
456protected:
457 //__________________________________________________________________
458 /**
459 * @{
33438b4c 460 * @name Overloadable behaviour
fdfd93b4 461 */
462 //------------------------------------------------------------------
463 /**
464 * Create the analysis manager
465 *
466 * @param name Name of the analysis
467 *
468 * @return Created analysis manager
469 */
470 virtual AliAnalysisManager* CreateAnalysisManager(const char* name)
471 {
472 return new AliAnalysisManager(name,"Analysis Train");
473 }
474 //------------------------------------------------------------------
475 /**
476 * Create input handler
477 *
478 * @param type
479 *
480 * @return
481 */
482 virtual AliVEventHandler* CreateInputHandler(UShort_t type)
483 {
484 switch (type) {
485 case Helper::kESD: return new AliESDInputHandler();
486 case Helper::kAOD: return new AliAODInputHandler();
487 case Helper::kUser: return 0;
488 }
489 return 0;
490 }
491 //------------------------------------------------------------------
492 /**
493 * Create MC input handler
494 *
fdfd93b4 495 * @param mc Assume monte-carlo input
496 *
497 * @return
498 */
499 virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc)
500 {
501 if (!mc) return 0;
502 AliMCEventHandler* mcHandler = new AliMCEventHandler();
503 mcHandler->SetReadTR(true);
504 return mcHandler;
505 }
506 //------------------------------------------------------------------
507 /**
508 * Create output event handler
509 *
510 * @param type
511 *
512 * @return
513 */
514 virtual AliVEventHandler* CreateOutputHandler(UShort_t type)
515 {
516 AliAODHandler* ret = new AliAODHandler();
517 switch (type) {
518 case Helper::kESD:
519 ret->SetOutputFileName("AliAOD.root");
520 break;
521 case Helper::kAOD:
522 ret->SetOutputFileName("AliAOD.pass2.root");
523 break;
524 case Helper::kUser:
525 break;
526 }
527
528 return ret;
529 }
530 //------------------------------------------------------------------
531 /**
532 * Create physics selection, and add to manager
533 *
534 * @param mc Whether this is for MC
535 * @param mgr Manager
536 */
537 virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
538 {
539 if (fOptions.Has("bare-ps")) {
540 AliInputEventHandler* input =
541 dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler());
542 if (!input) return;
543
544 AliPhysicsSelection* ps = new AliPhysicsSelection();
545 if (mc) ps->SetAnalyzeMC();
546
547 input->SetEventSelection(ps);
548
549 return;
550 }
551 gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
552 mgr->RegisterExtraFile("event_stat.root");
33438b4c 553 mgr->AddStatisticsTask(AliVEvent::kAny);
fdfd93b4 554 }
555 //------------------------------------------------------------------
556 /**
557 * Create centrality selection, and add to manager
558 *
559 * @param mc Whether this is for MC
560 * @param mgr Manager
561 */
562 virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
563 {
73b32206 564 gROOT->Macro("AddTaskCentrality.C(true)");
fdfd93b4 565 const char* name = "CentralitySelection";
566 AliCentralitySelectionTask* ctask =
567 dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
568 if (!ctask) return;
569 if (mc) ctask->SetMCInput();
570 }
571 //------------------------------------------------------------------
572 /**
573 * Create analysis tasks. Must be overloaded by sub-class
574 *
575 * @param mgr Manager
576 */
577 virtual void CreateTasks(AliAnalysisManager* mgr)=0;
33438b4c 578 /**
579 * Add a task using a script and possibly some arguments
580 *
581 * @param macro Script to execute
582 * @param args Optional arguments to the script
583 *
584 * @return Created task or null
585 */
586 virtual AliAnalysisTask* AddTask(const TString& macro,
587 const TString& args)
588 {
589 TString p = gSystem->Which(gROOT->GetMacroPath(), macro.Data());
590 if (p.IsNull()) {
591 Error("AddTask", "Macro %s not found", macro.Data());
592 return 0;
593 }
594 TString cmd(p);
595 if (!args.IsNull())
596 cmd.Append(TString::Format("(%s)", args.Data()));
597
598 Int_t err;
599 Long_t ret = gROOT->Macro(cmd.Data(), &err, false);
600 if (!ret) {
66ee9f2f 601 Error("AddTask", "Failed to execute %s (%ld)", cmd.Data(), ret);
33438b4c 602 return 0;
603 }
604 return reinterpret_cast<AliAnalysisTask*>(ret);
605 }
606 /**
607 * Add a task to the train with no arguments passed to the script
608 *
609 * @param macro The <b>AddTask</b> macro.
610 *
611 * @return The added task, if any
612 */
613 virtual AliAnalysisTask* AddTask(const TString& macro)
614 {
615 TString args;
616 return AddTask(macro, args);
617 }
618 /**
619 * Add a single event analysis task to the train, passing the
620 * specified arguments to the macro.
621 *
622 * @param macro The <b>AddTask</b> macro
623 * @param args Arguments to pass the macro
624 *
625 * @return The added task, if any
626 */
627 virtual AliAnalysisTaskSE* AddSETask(const TString& macro,
628 const TString& args)
629 {
630 return dynamic_cast<AliAnalysisTaskSE*>(AddTask(macro, args));
631 }
632 /**
633 * Add a single event task to the train with no arguments passed to
634 * the script
635 *
636 * @param macro The <b>AddTask</b> macro.
637 *
638 * @return The added task, if any
639 */
640 virtual AliAnalysisTaskSE* AddSETask(const TString& macro)
641 {
642 TString args;
643 return AddSETask(macro, args);
644 }
56039ab4 645 /**
646 * Find an already added task
647 *
648 * @param name Name of the task
649 * @param verbose If true,
650 *
651 * @return
652 */
653 virtual AliAnalysisTask* FindTask(const TString& name,
654 Bool_t verbose=true) const
655 {
656 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
657 if (!mgr) {
658 ::Warning("FindTask", "No manager defined");
659 return 0;
660 }
661 AliAnalysisTask* task = mgr->GetTask(name);
662 if (!task && verbose)
663 ::Warning("FindTask", "Task \"%s\" not found in train",
664 name.Data());
665 return task;
666 }
340c93ea 667 /**
668 * Check if we have an MC handler attached
669 *
670 * @return True if MC handler is found in a valid manager. False if
671 * manager is not defined, or has no MC handler.
672 */
673 virtual Bool_t HasMCHandler() const
674 {
675 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
676 if (!mgr) return false;
677 return mgr->GetMCtruthEventHandler() != 0;
678 }
73b32206 679 /**
680 * Set the name of the train - should be name of the class. Must be
681 * overloaded.
682 *
683 * @return Class name as a constant C string
684 */
fdfd93b4 685 virtual const Char_t* ClassName() const = 0;
686 /* @} */
687 //__________________________________________________________________
6ee074b7 688 virtual void AddMonitor(const TString& name)
689 {
690 if (!fMonitored.IsNull()) fMonitored.Append(":");
691 fMonitored.Append(name);
692 }
693 virtual void CreateMonitors()
694 {
695 if (fMonitored.IsNull()) return;
696 if (fHelper->Mode() != Helper::kProof) return;
697
698 TObjArray* tokens = fMonitored.Tokenize(":");
699 TObject* token = 0;
700 TIter next(tokens);
701 while ((token = next())) {
702 gROOT->ProcessLine(Form("gProof->AddFeedback(\"%s\");",
703 token->GetName()));
704
705 }
706 tokens->Delete();
707 }
708 //__________________________________________________________________
fdfd93b4 709 /**
710 * @{
711 * @name Utility functions
712 */
713 /**
714 * Escape bad elements of the name
715 *
33438b4c 716 * @param name Name to escape
717 * @param datimeStr Date and Time string
fdfd93b4 718 *
719 * @return escaped name
720 */
bfab35d9 721 static TString EscapeName(const char* name, TString& datimeStr)
fdfd93b4 722 {
723 TString escaped = name;
724 char c[] = { ' ', '/', '@', 0 };
725 char* p = c;
726 while (*p) {
46b25775 727 char tmp[] = { *p, '\0' };
728 escaped.ReplaceAll(tmp, "_");
fdfd93b4 729 p++;
730 }
7095962e
CHC
731 if (!datimeStr.IsNull() &&
732 !datimeStr.EqualTo("none", TString::kIgnoreCase)) {
fdfd93b4 733 TDatime datime;
734 if (datimeStr.EqualTo("now", TString::kIgnoreCase))
735 datime.Set();
46b25775 736 else {
737 // Try various formats
738 struct tm t;
739 const char* formats[] = { "%Ec", // Locale
740 "%c", // Locale
741 "%Ex EX", // Locale
742 "%x %X", // Locale
a80dde0d 743 "%Y%m%d_%H%M", // YYYYMMDD_HHMM
46b25775 744 "%F %R", // ISO standard, no seconds
745 0 };
746 const char** f = formats;
747 Bool_t found = false;
748 while (*f && !found) {
749 // Reset needed fields
750 t.tm_year = 0;
751 t.tm_mon = 0;
752 t.tm_mday = 0;
753 t.tm_hour = 0;
754 t.tm_min = 0;
755 // Stop processing on first match
756 if (strptime(datimeStr.Data(), *f, &t) != 0) found = true;
757 f++;
758 }
a80dde0d 759 if (found) {
760 t.tm_mon += 1; // Return 0-based month
46b25775 761 datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0);
a80dde0d 762 }
46b25775 763 }
fdfd93b4 764 if (datime.GetYear() <= 1995 ||
765 datime.GetMonth() == 0 ||
766 datime.GetDay() == 0) return escaped;
bfab35d9 767 datimeStr = Form("%04d%02d%02d_%02d%02d",
768 datime.GetYear(),
769 datime.GetMonth(),
770 datime.GetDay(),
771 datime.GetHour(),
772 datime.GetMinute());
773 escaped.Append(Form("_%s", datimeStr.Data()));
fdfd93b4 774 }
775 return escaped;
776 }
777 /**
778 * Make our working directory if so requested
779 *
780 * @return true on success
781 */
782 Bool_t SetupWorkingDirectory()
783 {
784 // Get the name of the target directory
785 TString& nam = fEscapedName;
786
787 // Check if the directory exists already
788 Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
789 if (fHelper->Operation() == Helper::kTerminate && !exists) {
790 Error("SetupWorkingDirectory", "File/directory %s does not exists",
791 nam.Data());
792 return false;
793 }
794
795 Bool_t overwrite = fOptions.Has("overwrite");
796 // If we're not allowed to overwrite, then complain
797 if (!overwrite && exists) {
798 Error("SetupWorkingDirectory", "File/directory %s already exists",
799 nam.Data());
800 return false;
801 }
802
803 // Make the target directory if it doesn't exists
804 if (!exists) {
805 if (gSystem->MakeDirectory(nam.Data())) {
806 Error("SetupWorkingDirectory", "Failed to make directory '%s'",
807 nam.Data());
808 return false;
809 }
810 }
811
812 // Change directory to target directory
813 if (!gSystem->ChangeDirectory(nam.Data())) {
814 Error("SetupWorkingDirectory", "Failed to change directory to %s",
815 nam.Data());
816 return false;
817 }
85f21ab4 818 // Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there",
819 // nam.Data());
fdfd93b4 820 return true;
821 }
822 /**
823 * Save the setup as a ROOT script and possibly also a shell script
824 *
825 * @param asShellScript If true, also save as shell script
826 */
827 virtual void SaveSetup(Bool_t asShellScript)
828 {
46b25775 829 OptionList tmp(fOptions);
a80dde0d 830 const OptionList* uopts = (fHelper ? &fHelper->Options() : 0);
46b25775 831 if (tmp.Find("overwrite")) tmp.Set("overwrite");
a80dde0d 832 if (tmp.Find("date") && fEscapedName.Length() > fName.Length()+1) {
833 Int_t n = fName.Length()+1;
834 tmp.Set("date", fEscapedName(n, fEscapedName.Length()-n));
835 }
fdfd93b4 836 if (asShellScript)
a80dde0d 837 SaveSetupShell("rerun", ClassName(), fName, tmp, uopts);
838 SaveSetupROOT("ReRun", ClassName(), fName, tmp, uopts);
839 if (fHelper) fHelper->AuxSave(fEscapedName, asShellScript);
aeab3a4e 840 SavePostShellScript();
fdfd93b4 841 }
842 /**
843 * Save a setup as a shell script
844 *
845 * @param out Output name of shell script
846 * @param cls Class of the train
847 * @param name Name of the train
848 * @param opts Option list
33438b4c 849 * @param uopts Url options
fdfd93b4 850 */
851 static void SaveSetupShell(const TString& out, const TString& cls,
a80dde0d 852 const TString& name, const OptionList& opts,
853 const OptionList* uopts)
fdfd93b4 854 {
855 std::ofstream o(Form("%s.sh", out.Data()));
856 o << "#!/bin/bash\n\n"
857 << "class=\"" << cls << "\"\n"
858 << "name=\"" << name << "\"\n\n"
859 << "# Available options\n"
860 << "# \n";
861 opts.Help(o, "# --");
a80dde0d 862 if (uopts) {
863 o << "#\n"
864 << "# Available URI options\n"
865 << "# \n";
866 uopts->Help(o, "# ");
867 }
fdfd93b4 868 o << "#\n"
869 << "opts=(--class=$class \\\n"
870 << " --name=$name";
871 opts.Store(o, " \\\n --", "", true);
872 o << ")\n\n"
92f304b1 873 << "echo \"Running runTrain ${opts[@]} $@\"\n"
874 << "runTrain \"${opts[@]}\" $@\n\n"
fdfd93b4 875 << "# EOF" << std::endl;
876 o.close();
877 gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
878 }
879 /**
880 * Save a setup as a ROOT script
881 *
882 * @param out Output name of shell script
883 * @param cls Class of the train
884 * @param name Name of the train
885 * @param opts Option list
33438b4c 886 * @param uopts Url options
fdfd93b4 887 */
888 static void SaveSetupROOT(const TString& out, const TString& cls,
a80dde0d 889 const TString& name, const OptionList& opts,
890 const OptionList* uopts)
fdfd93b4 891 {
892 OptionList tmp(opts);
893 tmp.Remove("url");
a80dde0d 894
fdfd93b4 895 std::ofstream o(Form("%s.C", out.Data()));
a80dde0d 896 o << "// Available options:\n"
897 << "// \n";
898 tmp.Help(o, "// ");
899 if (uopts) {
900 o << "// \n"
901 << "// Available URI options\n";
902 uopts->Help(o, "// ");
903 }
904 o << "//\n"
905 << "Bool_t " << out << "()\n"
fdfd93b4 906 << "{\n"
907 << " TString name(\"" << name << "\");\n"
908 << " TString cls(\"" << cls << "\");\n"
a80dde0d 909 << " TUrl uri(\"" << opts.Get("url") << "\");\n"
910 << " \n"
fdfd93b4 911 << " TString opts(";
912 tmp.Store(o, "\"", ",\"\n ", false);
913 o << ");\n\n"
46b25775 914 << " TString path(";
915 TString path(gROOT->GetMacroPath());
916 TObjArray* elements = path.Tokenize(":");
917 TObjString* element = 0;
918 TIter next(elements);
919 while ((element = static_cast<TObjString*>(next()))) {
920 if (element->String().IsNull()) continue;
921 o << "\n \"" << element->GetName() << ":\"";
922 }
923 elements->Delete();
924 o << ");\n"
925 << " path.Append(\"$ALICE_ROOT/PWGLF/FORWARD/trains\");\n"
926 << " gROOT->SetMacroPath(path);\n\n"
fdfd93b4 927 << " gROOT->LoadMacro(\"RunTrain.C\");\n\n"
928 << " return RunTrain(name, cls, uri, opts);\n"
929 << "}\n"
930 << "//\n"
931 << "// EOF\n"
932 << "//" << std::endl;
933 o.close();
934 }
aeab3a4e 935 /**
936 * Write shell code to do post processing after terminate. This
937 * code should deal with a single run (or run range). The following
938 * shell variables are available to the code:
939 *
940 * - @c $prefix Relative path to job directory or empty
941 * - @c $dest Destination for output to be stored
942 *
943 * Note, the code is injected into a shell function, and should
944 * therefor not define new functions or the like.
945 *
946 * @param o The output stream.
947 */
948 virtual void PostShellCode(std::ostream& o)
949 {
950 o << " echo \"Nothing to do for " << ClassName()
951 << " train\"" << std::endl;
952 }
953 /**
954 * Save a script to do post processing after terminate on each run
955 * or run-range.
956 *
957 * The shell script will execute the train defined code (in
958 * PostShellCode) for each run or run-range. The train defined code
959 * and call drawing and summarizing macros or the like.
960 *
961 * In case of Grid analysis, this script will download and extract
962 * the appropriate ZIP files to separate directories, and then
963 * change directory to these directories and execute the train
964 * defined shell code there. In this case, the script defines the
965 * shell variable @c $prefix as the relative path to the job
966 * directory.
967 *
968 */
969 void SavePostShellScript()
970 {
971 std::ofstream f("post.sh");
972 if (!f) {
973 Error("SavePostAll", "Failed to open post.sh script");
974 return;
975 }
976 f << "#!/bin/bash\n"
977 << "# Generated by " << ClassName() << "\n"
978 << "set -e\n"
979 << "\n"
980 << "dest=$1\n"
981 << "prefix=\n"
982 << "\n"
983 << "doall() {"
984 << std::endl;
985 PostShellCode(f);
986 f << "}\n"
987 << "\n"
988 << "if test ! -f Download.C ;then\n"
989 << " doall\n"
990 << " exit\n"
991 << "fi\n"
992 << "\n"
993 << "if test ! -f .download ; then\n"
994 << " aliroot -l -b -q Download.C\\(1\\)\n"
995 << " touch .download\n"
996 << "fi\n"
997 << "prefix=../\n"
998 << "\n"
999 << "for i in root_archive_*.zip ; do\n"
1000 << " d=`basename $i .zip` \n"
1001 << " if test ! -d $d ; then\n"
1002 << " echo \"Directory $d missing\"\n"
1003 << " continue\n"
1004 << " fi\n"
1005 << " \n"
1006 << " (cd $d && doall)\n"
1007 << "done\n"
1008 << "# EOF"
1009 << std::endl;
1010 f.close();
1011 gSystem->Exec("chmod a+x post.sh");
1012 }
1013
fdfd93b4 1014 /* @} */
1015 TString fName;
1016 TString fEscapedName;
bfab35d9 1017 TString fDatimeString;
fdfd93b4 1018 OptionList fOptions;
1019 Helper* fHelper;
6ee074b7 1020 TString fMonitored;
fdfd93b4 1021};
1022#endif