2 * @defgroup pwglf_forward_trains Trains.
4 * Train specifications.
5 * See also @ref train_setup_doc
9 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
10 * @date Tue Oct 16 17:56:57 2012
12 * @brief Base classs for train specifications
14 * @ingroup pwglf_forward_trains
24 # include <TApplication.h>
25 # include <TStopwatch.h>
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>
43 class AliVEventHandler;
44 class AliAnalysisManager;
45 class AliInputEventHandler;
48 //====================================================================
50 * Generic set-up of an analysis train
52 * See also @ref train_setup_doc
54 * @ingroup pwglf_forward_trains
62 * @param name Name of the train
64 TrainSetup(const TString& name)
72 fOptions.Add("help", "Show help", false);
73 fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now");
74 fOptions.Add("bare-ps", "Use bare physics selection w/o task", false);
75 fOptions.Add("verbose", "LEVEL", "Set verbosity level", 0);
76 fOptions.Add("url", "URL", "Job location & input URL", "");
77 fOptions.Add("overwrite", "Allow overwrite", false);
78 fOptions.Add("events", "N", "Number of events to analyse", -1);
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);
83 fEscapedName = EscapeName(fName, fDatimeString);
88 * @param o Object to copy from
90 TrainSetup(const TrainSetup& o)
92 fEscapedName(o.fEscapedName),
93 fDatimeString(o.fDatimeString),
96 fMonitored(o.fMonitored)
101 * @param o Object to assign from
103 * @return Reference to this object
105 TrainSetup& operator=(const TrainSetup& o)
107 if (&o == this) return *this;
109 fEscapedName = o.fEscapedName;
110 fDatimeString = o.fDatimeString;
111 fOptions = o.fOptions;
112 fRailway = o.fRailway;
113 fMonitored = o.fMonitored;
120 virtual ~TrainSetup() {}
122 //__________________________________________________________________
130 * @return true on success
134 // --- Create the helper -----------------------------------------
135 TString url = fOptions.Get("url");
136 Int_t verbose = fOptions.AsInt("verbose");
138 fRailway = Railway::Create(url.Data(), verbose);
140 Error("Init", "Failed to make the worker for URL %s", url.Data());
144 // --- Check the type, if possible -------------------------------
145 UShort_t type = fRailway->InputType();
146 Bool_t mc = fRailway->IsMC();
147 if (fOptions.Has("type")) {
148 const TString& it = fOptions.Get("type");
149 if (it.EqualTo("ESD",TString::kIgnoreCase)) type = Railway::kESD;
150 else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Railway::kAOD;
151 else if (it.EqualTo("user",TString::kIgnoreCase))
152 type = Railway::kUser;
155 // --- Rewrite the escpaed name ----------------------------------
156 if (fOptions.Has("date")) {
157 fDatimeString = fOptions.Get("date");
158 fEscapedName = EscapeName(fName, fDatimeString);
161 // --- Get current directory and set-up sub-directory ------------
162 TString cwd = gSystem->WorkingDirectory();
163 if (!SetupWorkingDirectory()) return false;
165 // --- Do initial helper setup -----------------------------------
166 if (!fRailway->PreSetup()) return false;
168 // --- Load ROOT libraries ---------------------------------------
169 if (!fRailway->LoadROOT()) return false;
171 // --- Load AliROOT libraries ------------------------------------
172 if (!fRailway->LoadAliROOT()) return false;
174 // --- Create analysis manager -----------------------------------
175 AliAnalysisManager *mgr = CreateAnalysisManager(fEscapedName);
177 // In test mode, collect system information on every event
178 // if (oper == kTest) mgr->SetNSysInfo(1);
179 if (verbose > 0) mgr->SetDebugLevel(verbose);
180 mgr->SetAutoBranchLoading(!fOptions.Has("branches"));
181 if (fRailway->Mode() == Railway::kLocal)
182 mgr->SetUseProgressBar(kTRUE, 100);
184 // --- ESD input handler ------------------------------------------
185 AliVEventHandler* inputHandler = CreateInputHandler(type);
186 if (inputHandler) mgr->SetInputEventHandler(inputHandler);
188 // --- Monte-Carlo ------------------------------------------------
189 AliVEventHandler* mcHandler = CreateMCHandler(type,mc);
190 if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
192 // --- AOD output handler -----------------------------------------
193 AliVEventHandler* outputHandler = CreateOutputHandler(type);
194 if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
196 // --- Include analysis macro path in search path ----------------
197 gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
198 cwd.Data(), gROOT->GetMacroPath()));
200 // --- Physics selction - only for ESD ---------------------------
201 if (type == Railway::kESD) CreatePhysicsSelection(mc, mgr);
203 // --- Create centrality task ------------------------------------
204 CreateCentralitySelection(mc);
206 // --- Create tasks ----------------------------------------------
209 // --- Create monitor objects ------------------------------------
212 // --- Post set-up initialization of helper ----------------------
213 if (!fRailway->PostSetup()) return false;
215 // --- Set debug level on defined tasks --------------------------
217 TIter next(mgr->GetTasks());
218 AliAnalysisTask* sub = 0;
219 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
220 AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
222 se->SetDebugLevel(verbose);
226 // --- Print this setup ------------------------------------------
229 // --- Initialise the train --------------------------------------
230 if (!mgr->InitAnalysis()) {
231 gSystem->ChangeDirectory(cwd.Data());
232 Error("Init","Failed to initialise train");
236 // --- Enable progress bar ---------------------------------------
237 if (fRailway->Mode() != Railway::kGrid)
238 mgr->SetUseProgressBar(true, 100);
240 // --- Save setup to disk ----------------------------------------
243 // --- Some information ------------------------------------------
245 if (fRailway->Mode() != Railway::kLocal) {
246 TIter next(mgr->GetTasks());
247 AliAnalysisTask* sub = 0;
248 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
255 * Print timer information
257 * @param timer The timer
258 * @param where Where this was called from
260 void PrintTimer(TStopwatch& timer, const char* where)
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;
267 Info(where, "took %4d:%02d:%06.3f", h, m, t);
272 * @return true on success
276 TString cwd = gSystem->WorkingDirectory();
277 Bool_t status = false;
281 if (!Init()) throw TString("Failed to intialize the train");
282 PrintTimer(timer, "Initialization");
285 // Check if we're asked to only do the setup
286 if (fOptions.Has("setup")) {
288 throw TString("Only did setup, no running");
291 // if (r) SaveSetup(*r, nEvents, asShell);
293 Long64_t nEvents = fOptions.AsLong("events", -1);
294 Long64_t ret = fRailway->Run(nEvents);
295 PrintTimer(timer, "Processing");
298 // Make sure we go back
299 gSystem->ChangeDirectory(cwd.Data());
302 if (ret < 0) throw TString("Analysis failed");
307 if (status) Warning("Run", "%s", e.Data());
308 else Error("Run", "%s", e.Data());
310 if (fOptions.Has("date")) {
312 TString escaped = EscapeName(fName, tmp);
313 gSystem->Exec(Form("rm -f last_%s", escaped.Data()));
314 gSystem->Exec(Form("ln -sf %s last_%s",
315 fEscapedName.Data(), escaped.Data()));
317 PrintTimer(timer, "Finish");
325 * @return Reference ot the options
327 OptionList& Options() { return fOptions; }
329 * Print information to standard output
332 void Print(Option_t* ="") const
334 std::cout << "Train: " << fName << " (" << fEscapedName << ")"
336 fOptions.Show(std::cout);
337 if (fRailway) fRailway->Print();
342 * @param o Output stream
343 * @param asProg If true, output as program options
347 Bool_t Help(std::ostream& o=std::cout, bool asProg=false)
349 if (!fOptions.Has("help")) return true;
352 o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
354 o << "\n\nTrain Options:\n";
355 fOptions.Help(o, asProg ? " --" : " ");
358 if (!fRailway && fOptions.Has("url")) {
359 TString url = fOptions.Get("url");
360 fRailway = Railway::Create(url.Data());
363 o << fRailway->Desc() << " URL form:\n\n"
364 << " " << fRailway->UrlHelp() << "\n\n"
366 fRailway->Options().Help(o, " ");
370 o << "Possible URL forms:\n\n";
371 Railway::ShowUrlHelp("LocalRailway");
372 Railway::ShowUrlHelp("ProofRailway");
373 Railway::ShowUrlHelp("LiteRailway");
374 Railway::ShowUrlHelp("AAFRailway");
375 Railway::ShowUrlHelp("AAFPluginRailway");
376 Railway::ShowUrlHelp("GridRailway");
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.
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
392 * @return true on success
394 static Bool_t Main(const TString& name, const TString& cls,
395 const TCollection* opts,
402 throw TString("No class name specified");
404 throw TString("No train name specified");
406 gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"w\");");
408 Int_t r1 = gROOT->LoadMacro(Form("%s.C+g", cls.Data()), &error);
409 gROOT->ProcessLine("gSystem->RedirectOutput(0);");
411 throw TString::Format("Failed to load setup %s: %d - see build.log",
414 // Make our object using the interpreter
415 TString create = TString::Format("new %s(\"%s\")",
416 cls.Data(), name.Data());
417 gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"a\");");
418 Long_t retP = gROOT->ProcessLine(create, &error);
419 gROOT->ProcessLine("gSystem->RedirectOutput(0);");
421 throw TString::Format("Failed to make object of class %s "
422 "(see build.log): 0x%08lx/%d\n\t%s",
423 cls.Data(), retP, error, create.Data());
425 TrainSetup* train = reinterpret_cast<TrainSetup*>(retP);
427 // Now parse the options
428 if (!train->Options().Parse(opts))
429 throw TString("Failed to parse options");
431 // Info("", "URL=%s", train->Options().Get("url").Data());
433 // Check if we got a help request
434 if (train->Options().Has("help")) {
435 train->Help(std::cout, asProg);
440 // return train->Init();
444 if (!e.IsNull()) Error("Main", "%s", e.Data());
446 // Info("Main", "End of main loop (app=%p, asProg=%s, spawn=%s)",
447 // gApplication, asProg ? "true" : "false", spawn ? "true" : "false");
448 if (gApplication && asProg) {
451 gApplication->Terminate(ret ? 0 : 1);
457 //__________________________________________________________________
460 * @name Overloadable behaviour
462 //------------------------------------------------------------------
464 * Create the analysis manager
466 * @param name Name of the analysis
468 * @return Created analysis manager
470 virtual AliAnalysisManager* CreateAnalysisManager(const char* name)
472 return new AliAnalysisManager(name,"Analysis Train");
474 //------------------------------------------------------------------
476 * Create input handler
482 virtual AliVEventHandler* CreateInputHandler(UShort_t type)
485 case Railway::kESD: return new AliESDInputHandler();
486 case Railway::kAOD: return new AliAODInputHandler();
487 case Railway::kUser: return 0;
491 //------------------------------------------------------------------
493 * Create MC input handler
495 * @param mc Assume monte-carlo input
499 virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc)
502 AliMCEventHandler* mcHandler = new AliMCEventHandler();
503 mcHandler->SetReadTR(true);
506 //------------------------------------------------------------------
508 * Create output event handler
514 virtual AliVEventHandler* CreateOutputHandler(UShort_t type)
516 AliAODHandler* ret = new AliAODHandler();
519 ret->SetOutputFileName("AliAOD.root");
522 ret->SetOutputFileName("AliAOD.pass2.root");
530 //------------------------------------------------------------------
532 * Create physics selection, and add to manager
534 * @param mc Whether this is for MC
537 virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
539 if (fOptions.Has("bare-ps")) {
540 AliInputEventHandler* input =
541 dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler());
544 AliPhysicsSelection* ps = new AliPhysicsSelection();
545 if (mc) ps->SetAnalyzeMC();
547 input->SetEventSelection(ps);
551 CoupleCar("AddTaskPhysicsSelection.C", Form("%d", mc));
552 mgr->RegisterExtraFile("event_stat.root");
553 mgr->AddStatisticsTask(AliVEvent::kAny);
555 //------------------------------------------------------------------
557 * Create centrality selection, and add to manager
559 * @param mc Whether this is for MC
562 virtual void CreateCentralitySelection(Bool_t mc)
564 AliAnalysisTask* task = CoupleCar("AddTaskCentrality.C","true");
565 AliCentralitySelectionTask* ctask =
566 dynamic_cast<AliCentralitySelectionTask*>(task);
568 if (mc) ctask->SetMCInput();
570 //------------------------------------------------------------------
572 * Create analysis tasks. Must be overloaded by sub-class
576 virtual void CreateTasks(AliAnalysisManager* mgr)=0;
578 * Add a task using a script and possibly some arguments
580 * @param macro Script to execute
581 * @param args Optional arguments to the script
583 * @return Created task or null
585 virtual AliAnalysisTask* CoupleCar(const TString& macro,
588 TString p = gSystem->Which(gROOT->GetMacroPath(), macro.Data());
590 Error("CoupleCar", "Macro %s not found", macro.Data());
595 cmd.Append(TString::Format("(%s)", args.Data()));
598 Long_t ret = gROOT->Macro(cmd.Data(), &err, false);
600 Error("CoupleCar", "Failed to execute %s (%ld)", cmd.Data(), ret);
603 return reinterpret_cast<AliAnalysisTask*>(ret);
606 * Add a task to the train with no arguments passed to the script
608 * @param macro The <b>AddTask</b> macro.
610 * @return The added task, if any
612 virtual AliAnalysisTask* CoupleCar(const TString& macro)
615 return CoupleCar(macro, args);
618 * Add a single event analysis task to the train, passing the
619 * specified arguments to the macro.
621 * @param macro The <b>AddTask</b> macro
622 * @param args Arguments to pass the macro
624 * @return The added task, if any
626 virtual AliAnalysisTaskSE* CoupleSECar(const TString& macro,
629 return dynamic_cast<AliAnalysisTaskSE*>(CoupleCar(macro, args));
632 * Add a single event task to the train with no arguments passed to
635 * @param macro The <b>AddTask</b> macro.
637 * @return The added task, if any
639 virtual AliAnalysisTaskSE* CoupleSECar(const TString& macro)
642 return CoupleSECar(macro, args);
645 * Find an already added task
647 * @param name Name of the task
648 * @param verbose If true,
652 virtual AliAnalysisTask* FindCar(const TString& name,
653 Bool_t verbose=true) const
655 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
657 ::Warning("FindCar", "No manager defined");
660 AliAnalysisTask* task = mgr->GetTask(name);
661 if (!task && verbose)
662 ::Warning("FindCar", "Task \"%s\" not found in train",
667 * Check if we have an MC handler attached
669 * @return True if MC handler is found in a valid manager. False if
670 * manager is not defined, or has no MC handler.
672 virtual Bool_t HasMCHandler() const
674 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
675 if (!mgr) return false;
676 return mgr->GetMCtruthEventHandler() != 0;
679 * Set the name of the train - should be name of the class. Must be
682 * @return Class name as a constant C string
684 virtual const Char_t* ClassName() const = 0;
686 //__________________________________________________________________
687 virtual void AddMonitor(const TString& name)
689 if (!fMonitored.IsNull()) fMonitored.Append(":");
690 fMonitored.Append(name);
692 virtual void CreateMonitors()
694 if (fMonitored.IsNull()) return;
695 if (fRailway->Mode() != Railway::kProof) return;
697 TObjArray* tokens = fMonitored.Tokenize(":");
700 while ((token = next())) {
701 gROOT->ProcessLine(Form("gProof->AddFeedback(\"%s\");",
707 //__________________________________________________________________
710 * @name Utility functions
713 * Escape bad elements of the name
715 * @param name Name to escape
716 * @param datimeStr Date and Time string
718 * @return escaped name
720 static TString EscapeName(const char* name, TString& datimeStr)
722 TString escaped = name;
723 char c[] = { ' ', '/', '@', 0 };
726 char tmp[] = { *p, '\0' };
727 escaped.ReplaceAll(tmp, "_");
730 if (!datimeStr.IsNull() &&
731 !datimeStr.EqualTo("none", TString::kIgnoreCase)) {
733 if (datimeStr.EqualTo("now", TString::kIgnoreCase))
736 // Try various formats
738 const char* formats[] = { "%Ec", // Locale
742 "%Y%m%d_%H%M", // YYYYMMDD_HHMM
743 "%F %R", // ISO standard, no seconds
745 const char** f = formats;
746 Bool_t found = false;
747 while (*f && !found) {
748 // Reset needed fields
754 // Stop processing on first match
755 if (strptime(datimeStr.Data(), *f, &t) != 0) found = true;
759 t.tm_mon += 1; // Return 0-based month
760 datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0);
763 if (datime.GetYear() <= 1995 ||
764 datime.GetMonth() == 0 ||
765 datime.GetDay() == 0) return escaped;
766 datimeStr = Form("%04d%02d%02d_%02d%02d",
772 escaped.Append(Form("_%s", datimeStr.Data()));
777 * Make our working directory if so requested
779 * @return true on success
781 Bool_t SetupWorkingDirectory()
783 // Get the name of the target directory
784 TString& nam = fEscapedName;
786 // Check if the directory exists already
787 Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
788 if (fRailway->Operation() == Railway::kTerminate && !exists) {
789 Error("SetupWorkingDirectory", "File/directory %s does not exists",
794 Bool_t overwrite = fOptions.Has("overwrite");
795 // If we're not allowed to overwrite, then complain
796 if (!overwrite && exists) {
797 Error("SetupWorkingDirectory", "File/directory %s already exists",
802 // Make the target directory if it doesn't exists
804 if (gSystem->MakeDirectory(nam.Data())) {
805 Error("SetupWorkingDirectory", "Failed to make directory '%s'",
811 // Change directory to target directory
812 if (!gSystem->ChangeDirectory(nam.Data())) {
813 Error("SetupWorkingDirectory", "Failed to change directory to %s",
817 // Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there",
822 * Save the setup as a ROOT script and possibly also a shell script
824 * @param asShellScript If true, also save as shell script
826 virtual void SaveSetup(Bool_t asShellScript)
828 OptionList tmp(fOptions);
829 const OptionList* uopts = (fRailway ? &fRailway->Options() : 0);
830 if (tmp.Find("overwrite")) tmp.Set("overwrite");
831 if (tmp.Find("date") && fEscapedName.Length() > fName.Length()+1) {
832 Int_t n = fName.Length()+1;
833 tmp.Set("date", fEscapedName(n, fEscapedName.Length()-n));
836 SaveSetupShell("rerun", ClassName(), fName, tmp, uopts);
837 SaveSetupROOT("ReRun", ClassName(), fName, tmp, uopts);
838 if (fRailway) fRailway->AuxSave(fEscapedName, asShellScript);
839 SavePostShellScript();
842 * Save a setup as a shell script
844 * @param out Output name of shell script
845 * @param cls Class of the train
846 * @param name Name of the train
847 * @param opts Option list
848 * @param uopts Url options
850 static void SaveSetupShell(const TString& out, const TString& cls,
851 const TString& name, const OptionList& opts,
852 const OptionList* uopts)
854 std::ofstream o(Form("%s.sh", out.Data()));
855 o << "#!/bin/bash\n\n"
856 << "class=\"" << cls << "\"\n"
857 << "name=\"" << name << "\"\n\n"
858 << "# Available options\n"
860 opts.Help(o, "# --");
863 << "# Available URI options\n"
865 uopts->Help(o, "# ");
868 << "opts=(--class=$class \\\n"
870 opts.Store(o, " \\\n --", "", true);
872 << "echo \"Running runTrain ${opts[@]} $@\"\n"
873 << "runTrain \"${opts[@]}\" $@\n\n"
874 << "# EOF" << std::endl;
876 gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
879 * Save a setup as a ROOT script
881 * @param out Output name of shell script
882 * @param cls Class of the train
883 * @param name Name of the train
884 * @param opts Option list
885 * @param uopts Url options
887 static void SaveSetupROOT(const TString& out, const TString& cls,
888 const TString& name, const OptionList& opts,
889 const OptionList* uopts)
891 OptionList tmp(opts);
894 std::ofstream o(Form("%s.C", out.Data()));
895 o << "// Available options:\n"
900 << "// Available URI options\n";
901 uopts->Help(o, "// ");
904 << "Bool_t " << out << "()\n"
906 << " TString name(\"" << name << "\");\n"
907 << " TString cls(\"" << cls << "\");\n"
908 << " TUrl uri(\"" << opts.Get("url") << "\");\n"
911 tmp.Store(o, "\"", ",\"\n ", false);
914 TString path(gROOT->GetMacroPath());
915 TObjArray* elements = path.Tokenize(":");
916 TObjString* element = 0;
917 TIter next(elements);
918 while ((element = static_cast<TObjString*>(next()))) {
919 if (element->String().IsNull()) continue;
920 o << "\n \"" << element->GetName() << ":\"";
924 << " path.Append(\"$ALICE_ROOT/PWGLF/FORWARD/trains\");\n"
925 << " gROOT->SetMacroPath(path);\n\n"
926 << " gROOT->LoadMacro(\"RunTrain.C\");\n\n"
927 << " return RunTrain(name, cls, uri, opts);\n"
931 << "//" << std::endl;
935 * Write shell code to do post processing after terminate. This
936 * code should deal with a single run (or run range). The following
937 * shell variables are available to the code:
939 * - @c $prefix Relative path to job directory or empty
940 * - @c $dest Destination for output to be stored
942 * Note, the code is injected into a shell function, and should
943 * therefor not define new functions or the like.
945 * @param o The output stream.
947 virtual void PostShellCode(std::ostream& o)
949 o << " echo \"Nothing to do for " << ClassName()
950 << " train\"" << std::endl;
953 * Save a script to do post processing after terminate on each run
956 * The shell script will execute the train defined code (in
957 * PostShellCode) for each run or run-range. The train defined code
958 * and call drawing and summarizing macros or the like.
960 * In case of Grid analysis, this script will download and extract
961 * the appropriate ZIP files to separate directories, and then
962 * change directory to these directories and execute the train
963 * defined shell code there. In this case, the script defines the
964 * shell variable @c $prefix as the relative path to the job
968 void SavePostShellScript()
970 std::ofstream f("post.sh");
972 Error("SavePostAll", "Failed to open post.sh script");
976 << "# Generated by " << ClassName() << "\n"
987 << "if test ! -f Download.C ;then\n"
992 << "if test ! -f .download ; then\n"
993 << " aliroot -l -b -q Download.C\\(1\\)\n"
994 << " touch .download\n"
998 << "for i in root_archive_*.zip ; do\n"
999 << " d=`basename $i .zip` \n"
1000 << " if test ! -d $d ; then\n"
1001 << " echo \"Directory $d missing\"\n"
1005 << " (cd $d && doall)\n"
1010 gSystem->Exec("chmod a+x post.sh");
1015 TString fEscapedName;
1016 TString fDatimeString;
1017 OptionList fOptions;