Added option to write aux script as part of saving the setup.
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 23 Oct 2012 11:26:18 +0000 (11:26 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 23 Oct 2012 11:26:18 +0000 (11:26 +0000)
This is used by the Grid helper to write a Terminate.C ROOT
script and terminate.sh shell script.  This is better than
doing some option for ReRun.C/rerun.sh since TERMINATE is
really specific to Grid jobs.

PWGLF/FORWARD/trains/GridHelper.C
PWGLF/FORWARD/trains/Helper.C
PWGLF/FORWARD/trains/PluginHelper.C
PWGLF/FORWARD/trains/TrainSetup.C

index 4aa5d08..66ddbc3 100644 (file)
@@ -84,11 +84,13 @@ struct GridHelper : public PluginHelper
     : PluginHelper(url, verbose)
   {
     fOptions.Add("oper", "FULL|TERMINATE|SUBMIT", "Analysis operation", "FULL");
-    fOptions.Add("split",  "N", "Maximum number of files before split", "max");
-    fOptions.Add("merge",  "N", "Maximum number of files for merge", "max");
-    fOptions.Add("run",    "RUNS", "Range, list, and/or file of runs", "");
-    fOptions.Add("pattern","GLOB", "File/directory name pattern", "");
-    fOptions.Add("mc", "Assume MC input");
+    fOptions.Add("split",  "N|max",  "Max number of files before split","max");
+    fOptions.Add("merge",  "N|max",  "Max number of files for merge",   "max");
+    fOptions.Add("run",    "RUNS",   "Range, list, and/or file of runs");
+    fOptions.Add("pattern","GLOB",   "File/directory name pattern");
+    fOptions.Add("alien",  "VERSION","Alien API version",              "V1.1x");
+    fOptions.Add("concat", "Concatenate all runs");
+    fOptions.Add("mc",     "Assume MC input");
   }
   virtual ~GridHelper() {}
   /** 
@@ -129,12 +131,13 @@ struct GridHelper : public PluginHelper
       return -1;
     }
     Int_t       nRuns  = 0;
-    TString     runs   = fOptions.Get("runs");
+    TString     runs   = fOptions.Get("run");
     TObjArray*  tokens = runs.Tokenize(",");
     TObjString* part   = 0;
     TIter       next(tokens);
     Bool_t      range  = false;
     Bool_t      individual = false;
+    Info("GridHelper::RegisterRuns", "Runs specified are %s", runs.Data());
     while ((part = static_cast<TObjString*>(next()))) {
       TString& s = part->String();
       if (s.Contains("-")) { // Run range 
@@ -159,6 +162,8 @@ struct GridHelper : public PluginHelper
        Int_t first = static_cast<TObjString*>(ranges->At(0))->String().Atoi();
        Int_t last  = static_cast<TObjString*>(ranges->At(1))->String().Atoi();
        nRuns       = last-first+1;
+       Info("GridHelper::RegisterRuns", "Run range %d -> %d", 
+            first, last);
        fHandler->SetRunRange(first, last);
        ranges->Delete();
        range = true;
@@ -171,18 +176,20 @@ struct GridHelper : public PluginHelper
                  "ignoring %s", s.Data());
          continue;
        }
+       Info("GridHandler::RegisterRuns", "Adding run %s", s.Data());
        fHandler->AddRunNumber(s.Data());
        nRuns++;
        individual = true;
        continue;
       }
-       if (range) { 
-         Warning("GridHelper::RegisterRuns", "Run ranges and list file "
-                 "do not mix, ignoring %s", s.Data());
-         continue;
-       }
+      if (range) { 
+       Warning("GridHelper::RegisterRuns", "Run ranges and list file "
+               "do not mix, ignoring %s", s.Data());
+       continue;
+      }
 
       // We assume this part is a file 
+      Info("GridHelper::RegisterRuns", "Reading runs from %s", s.Data());
       std::ifstream in(s.Data());
       if (!in) { 
        Warning("GridHelper::RegisterRuns", "Failed to open %s", s.Data());
@@ -191,6 +198,7 @@ struct GridHelper : public PluginHelper
       while (!in.eof()) { 
        Int_t r;
        in >> r;
+       Info("GridHelper::RegisterRuns", "Read %d, adding", r);
        fHandler->AddRunNumber(r);
        nRuns++;
        Char_t c;
@@ -210,9 +218,15 @@ struct GridHelper : public PluginHelper
   virtual Bool_t PreSetup() 
   {
     if (!PluginHelper::PreSetup()) return false;
+    
+    // --- Add system library dir to load path -----------------------
+    gSystem->AddDynamicPath("/usr/lib");
 
     // --- Open a connection to the grid -----------------------------
-    TGrid::Connect(Form("%s://", fUrl.GetProtocol()));
+    if (!TGrid::Connect(Form("%s://", fUrl.GetProtocol()))) { 
+      Error("GridHelper::PreSetup", "Failed to connect to AliEN");
+      return false;
+    }
     if (!gGrid || !gGrid->IsConnected()) { 
       Error("GridHelper::PreSetup", "Failed to connect to AliEN");
       return false;
@@ -227,8 +241,14 @@ struct GridHelper : public PluginHelper
    */
   virtual Bool_t PostSetup() 
   {
+    Info("GridHelper::PostSetup", "Calling super.PostSetup");
     if (!PluginHelper::PostSetup()) return false;
 
+    // --- API version -----------------------------------------------
+    fHandler->SetAPIVersion(fOptions.Get("alien"));
+    
+    // --- Get the name ----------------------------------------------
+    Info("GridHandler", "Proceeding with plugin setup");
     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
     TString name(mgr->GetName());
 
@@ -237,6 +257,10 @@ struct GridHelper : public PluginHelper
     if (fOptions.Has("oper")) operation = fOptions.Get("oper");
     fHandler->SetRunMode(operation);
 
+    // --- Add the run numbers ---------------------------------------
+    fHandler->SetRunPrefix(mgr->GetMCtruthEventHandler() ? "%d" : "%09d");
+    Int_t nRun = RegisterRuns();
+
     // --- Do not test copying ---------------------------------------
     fHandler->SetCheckCopy(false);
     
@@ -285,21 +309,24 @@ struct GridHelper : public PluginHelper
     // --- How much to split -----------------------------------------
     if (fOptions.Has("split")) { 
       if (!fOptions.Get("split").EqualTo("max")) {
-       fHandler->SetSplitMaxInputFileNumber(fOptions.Get("split").Atoi());
+       fHandler->SetSplitMaxInputFileNumber(fOptions.AsInt("split"));
       }
     }
-    
-    // --- Enable default outputs ------------------------------------
-    fHandler->SetDefaultOutputs(true);
-
     // --- Merge parameters ------------------------------------------
     if (fOptions.Has("merge")) { 
       if (!fOptions.Get("merge").EqualTo("max")) { 
-       fHandler->SetMaxMergeFiles(fOptions.Get("merge").Atoi());
+       fHandler->SetMaxMergeFiles(fOptions.AsInt("merge"));
       }
     }
     fHandler->SetMergeExcludes("AliAOD.root *EventStat*.root "
                               "*event_stat*.root");
+    
+    // --- Set number of runs per master - 1 or all ------------------
+    fHandler->SetNrunsPerMaster(fOptions.Has("concat") ? nRun+1 : 1);
+
+
+    // --- Enable default outputs ------------------------------------
+    fHandler->SetDefaultOutputs(true);
 
     // --- Keep log files ------------------------------------------
     fHandler->SetKeepLogs();
@@ -325,13 +352,6 @@ struct GridHelper : public PluginHelper
       else if (treeName.EqualTo("aodTree")) pattern = "AliAOD";
     }
     fHandler->SetDataPattern(pattern);
-    fHandler->SetRunPrefix(mgr->GetMCtruthEventHandler() ? "" : "000");
-
-    // --- Add the run numbers ---------------------------------------
-    Int_t nRun = RegisterRuns();
-
-    // --- Set number of runs per master - set to one to per run -----
-    fHandler->SetNrunsPerMaster(fOptions.Has("run-merge") ? 1 : nRun+1);
 
     // --- Loop over defined containers in the analysis manager, and -
     // --- declare these as outputs
@@ -436,6 +456,194 @@ struct GridHelper : public PluginHelper
    * @return Short description
    */
   virtual const char* Desc() const { return "AliEn"; }
+  /** 
+   * Write auxillary ROOT (and possible shell) script for more 
+   * (post-)processing e.g., terminate
+   * 
+   * @param escaped        Escaped name  
+   * @param asShellScript  also save as shell script
+   */
+  void AuxSave(const TString& escaped, 
+              Bool_t asShellScript) 
+  {
+    // Write plug-in to file 
+    TFile* plug = TFile::Open(Form("%s_plugin.root", escaped.Data()), 
+                             "RECREATE");
+    fHandler->Write("plugin");
+    plug->Close();
+    
+    std::ofstream o("Terminate.C");
+    if (!o) { 
+      Error("GridHelper::AuxSave", "Failed to make terminate ROOT script");
+      return;
+    }
+    
+    o << "// Generated by GridHelper\n"
+      << "Bool_t LoadLib(const char* libName)\n"
+      << "{\n"
+      << "  if (gSystem->Load(libName) < 0) {\n"
+      << "    Error(\"Terminate\", \"Failed to load library %s\",libName);\n"
+      << "    return false;\n"
+      << "  }\n"
+      << "  Info(\"Terminate\",\"Loaded library %s\",libName);\n"
+      << "  return true;\n"
+      << "}\n\n"
+      << "Bool_t LoadPar(const char* parName)\n"
+      << "{\n"
+      << "  if (!AliAnalysisAlien::SetupPar(parName)) {\n"
+      << "    Error(\"Terminate\",\"Failed to load PAR %s\",parName);\n"
+      << "    return false;\n"
+      << "  }\n"
+      << "  Info(\"Terminate\",\"Loaded package %s\",parName);\n"
+      << "  return true;\n"
+      << "}\n\n"
+      << "Bool_t Terminate()\n"
+      << "{\n"
+      << "  // Name of job\n"
+      << "  TString name = \"" << escaped << "\";\n\n" 
+      << "  // Load basic ROOT libraries\n"
+      << "  gSystem->AddDynamicPath(\"/usr/lib\");\n"
+      << "  if (gSystem->Load(\"libTree.so\")       < 0) return false;\n"
+      << "  if (gSystem->Load(\"libGeom.so\")       < 0) return false;\n"
+      << "  if (gSystem->Load(\"libVMC.so\")        < 0) return false;\n"
+      << "  if (gSystem->Load(\"libPhysics.so\")    < 0) return false;\n"
+      << "  if (gSystem->Load(\"libMinuit.so\")     < 0) return false;\n\n"
+      << "  // Load basic AliROOT libraries\n"
+      << "  if (gSystem->Load(\"libSTEERBase\")     < 0) return false;\n"
+      << "  if (gSystem->Load(\"libESD\")           < 0) return false;\n"
+      << "  if (gSystem->Load(\"libAOD\")           < 0) return false;\n"
+      << "  if (gSystem->Load(\"libANALYSIS\")      < 0) return false;\n"
+      << "  if (gSystem->Load(\"libOADB\")          < 0) return false;\n"
+      << "  if (gSystem->Load(\"libANALYSISalice\") < 0) return false;\n\n";
+    // Now load libraries 
+    o << " // Load libraries\n";
+    TIter nextLib(&fExtraLibs);
+    TObjString* lib = 0;
+    while ((lib = static_cast<TObjString*>(nextLib()))) {
+      const TString& libName = lib->String();
+      if (libName.Contains("libSTEERBase") ||
+         libName.Contains("libESD") ||
+         libName.Contains("libAOD") ||
+         libName.Contains("libANALYSIS") ||
+         libName.Contains("libOADB") ||
+         libName.Contains("libANALYSISalice")) continue;
+      if (libName.Contains(".so")) continue;
+      o << "  if(!LoadLib(\"" << libName << "\")) return false;\n";
+    }
+    // Now load PARs
+    o << "\n"
+      << "  // Load packages\n";
+    TIter nextPar(&fExtraPars);
+    TObjString* par = 0;
+    while ((par = static_cast<TObjString*>(nextPar()))) {
+      TString parName(par->String());
+      if (parName.EndsWith(".par")) parName.ReplaceAll(".par", "");
+      if (parName.Contains("STEERBase") ||
+         parName.Contains("ESD") ||
+         parName.Contains("AOD") ||
+         parName.Contains("ANALYSIS") ||
+         parName.Contains("OADB") ||
+         parName.Contains("ANALYSISalice")) continue;
+      o << "  if (!LoadPar(\"" << parName << "\")) return false;\n";
+    }
+    // Now load scripts 
+    o << "\n"
+      << "  // Load sources\n";
+    TIter nextSrc(&fExtraSrcs);
+    TObjString* src = 0;
+    while ((src = static_cast<TObjString*>(nextSrc()))) {
+      const TString& srcName = src->String();
+      o << "  gROOT->ProcessLine(\".L " << srcName << "+g\");\n";
+    }
+       
+    // We're ready to load the analysis manager.  
+    o << "  \n"
+      << "  // Load the analysis manager from file\n"
+      << "  TString base(name);\n"
+      << "  base.Append(\".root\");\n"
+      << "  if (gSystem->AccessPathName(base.Data())) {\n"
+      << "    // Couldn't read from current directory, try sub-dir\n"
+      << "    TString sub(gSystem->ConcatFileName(name, base));\n"
+      << "    if (gSystem->AccessPathName(sub)) {\n"
+      << "      Error(\"Terminate\",\"Couldn't find manager file %s\","
+      << "base.Data());\n"
+      << "      return false;\n"
+      << "    }\n"
+      << "    base = sub;\n"
+      << "  }\n"
+      << "  AliAnalysisManager* mgr= "
+      << "AliAnalysisAlien::LoadAnalysisManager(base);\n"
+      << "  if (!mgr) {\n"
+      << "    Error(\"Terminate\", \"Failed to load manager from %s\","
+      << "base.Data());\n"
+      << "    return false;\n"
+      << "  }\n"
+      << "  if (!name.EqualTo(mgr->GetName())) {\n"
+      << "    Error(\"Terminate\",\"Read manager %s is not %s\","
+      << "mgr->GetName(),name.Data());\n"
+      << "    return false;\n"
+      << "  }\n"
+      << "  Info(\"Terminate\",\"Loaded analysis manager\");\n\n"
+      << "  // Load plugin\n"
+      << "  TFile* plug = TFile::Open(Form(\"%s_plugin.root\",name.Data()),"
+      << "\"READ\");\n"
+      << "  if (!plug) {\n"
+      << "    Error(\"Terminate\",\"Failed to open %s_plugin.root\","
+      << "name.Data());\n"
+      << "    return false;\n"
+      << "  }\n"
+      << "  AliAnalysisAlien* handler = "
+      << "static_cast<AliAnalysisAlien*>(plug->Get(\"plugin\"));\n"
+      << "  if (!handler) {\n"
+      << "    Error(\"Terminate\",\"Failed to load plugin\");\n"
+      << "    return false;\n"
+      << "  }\n"
+      << "  Info(\"Terminate\",\"Setting grid handler\");\n"
+      << "  handler->SetRunMode(\"terminate\");\n"
+      << "  mgr->SetGridHandler(handler);\n\n"
+      << "  // Run the terminate job\n"
+      << "  Info(\"Terminate\",\"Starting terminate job\");\n"
+      << "  if (mgr->StartAnalysis(\"grid\") < 0) return false;\n"
+      << "  return true;\n"
+      << "}\n"
+      << "// \n"
+      << "// EOF\n"
+      << "//\n"
+      << std::endl;
+    o.close();
+
+    if (!asShellScript) return;
+
+    std::ofstream s("terminate.sh");
+    if (!s) { 
+      Error("GridHelper::AuxSave", "Failed to make terminate shell script");
+      return;
+    }
+    s << "#!/bin/sh\n"
+      << "# Generated by GridHelper\n"
+      << "nam=" << escaped << "\n"
+      << "scr=Terminate.C\n"
+      << "mgr=$name.root\n"
+      << "\n"
+      << "if test ! -f $scr || test ! -f $mgr ; then\n"
+      << "  if test ! -d $nam ; then\n"
+      << "    echo \"Directory $nam not found\"\n"
+      << "    exit 1\n"
+      << "  fi\n\n"
+      << "  if test ! -f $nam/$scr || test -f $nam/$scr ; then\n"
+      << "    echo \"Script $nam/$scr, manager $nam/$scr not found\"\n"
+      << "    exit 1\n"
+      << "  fi\n\n"
+      << "  (cd $nam && aliroot -l $scr)\n"
+      << "fi\n\n"
+      << " aliroot -l $scr\n"
+      << "#\n"
+      << "# EOF\n"
+      << "#\n"
+      << std::endl;
+    s.close();
+    gSystem->Exec("chmod a+x terminate.sh");
+  }
 };
 #endif
 //
index c46471e..cae0715 100644 (file)
@@ -292,6 +292,15 @@ struct Helper
    * @return Reference to list of options 
    */
   const OptionList& Options() const { return fOptions; }
+  /** 
+   * Write auxillary ROOT (and possible shell) script for more 
+   * (post-)processing e.g., terminate
+   * 
+   * @param escaped        Escaped name  
+   * @param asShellScript  also save as shell script
+   */
+  virtual void AuxSave(const TString& /*escaped*/, 
+                      Bool_t /*asShellScript*/) {}
   /** 
    * Create an instance of a helper class 
    */
index 28e70aa..74b581d 100644 (file)
@@ -69,7 +69,8 @@ struct PluginHelper : public Helper
    * @param opts Options 
    */
   PluginHelper(const TUrl& url, Int_t verbose)
-    : Helper(url, verbose), fHandler(0), fUsePars(false)
+    : Helper(url, verbose), fHandler(0), fUsePars(false), 
+      fExtraLibs(), fExtraPars(), fExtraSrcs()
   {
     fHandler = new AliAnalysisAlien();
 
@@ -77,8 +78,12 @@ struct PluginHelper : public Helper
     fOptions.Add("root",    "VERSION", "ROOT version", "last");
     fOptions.Add("par", "Use par files");
     fOptions.Add("mode", "default|rec|sim", "AliROOT mode", "default");
-    fOptions.Add("storage", "URL", "Location for external storage", "");    
+    fOptions.Add("storage", "URL", "Location for external storage");    
     fOptions.Add("plugin", "Use AliEn handler");
+
+    fExtraLibs.SetOwner();
+    fExtraPars.SetOwner();
+    fExtraSrcs.SetOwner();
   }
   /** 
    * Copy constructor 
@@ -86,7 +91,8 @@ struct PluginHelper : public Helper
    * @param o Object to copy from 
    */
   PluginHelper(const PluginHelper& o) 
-    : Helper(o), fHandler(o.fHandler), fUsePars(o.fUsePars)
+    : Helper(o), fHandler(o.fHandler), fUsePars(o.fUsePars), 
+      fExtraLibs(), fExtraPars(), fExtraSrcs()
   {}
   /** 
    * Assignment operator 
@@ -123,7 +129,10 @@ struct PluginHelper : public Helper
       TString fullName(MakeLibraryName(name));
       Int_t ret = gSystem->Load(fullName);
       if (ret < 0) return false;
-      if (slaves) fHandler->AddAdditionalLibrary(fullName);
+      if (slaves) {
+       fHandler->AddAdditionalLibrary(fullName);
+       fExtraLibs.Add(new TObjString(fullName));
+      }
     }
     else { 
       if (!ParUtilities::Find(name)) { 
@@ -137,6 +146,7 @@ struct PluginHelper : public Helper
        return false;
       }
       fHandler->EnablePackage(name);
+      fExtraPars.Add(new TObjString(name));
     }
     return true;
   }
@@ -153,6 +163,7 @@ struct PluginHelper : public Helper
     if (!Helper::LoadSource(name)) return false;
     s.Append(Form(" %s", gSystem->BaseName(name.Data())));
     fHandler->SetAnalysisSource(s);
+    fExtraSrcs.Add(new TObjString(name));
     return true;
   }
   
@@ -266,6 +277,9 @@ struct PluginHelper : public Helper
   }
   AliAnalysisAlien* fHandler;
   Bool_t fUsePars;
+  TList  fExtraLibs;
+  TList  fExtraPars;
+  TList  fExtraSrcs;
 };
 #endif
 //
index 3dce85c..4aa7d72 100644 (file)
@@ -70,11 +70,12 @@ struct TrainSetup
     fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now");
     fOptions.Add("mc", "Assume MC input");
     fOptions.Add("bare-ps", "Use bare physics selection w/o task");
-    fOptions.Add("verbose", "LEVEL", "Set verbosity level", "0");
-    fOptions.Add("url", "URL", "Job location & input URL", "");
+    fOptions.Add("verbose", "LEVEL", "Set verbosity level", 0);
+    fOptions.Add("url", "URL", "Job location & input URL");
     fOptions.Add("overwrite", "Allow overwrite");
-    fOptions.Add("events", "N", "Number of events to analyse", "-1");
-    fOptions.Add("type", "ESD|AOD|USER", "Input data stype", "");
+    fOptions.Add("events", "N", "Number of events to analyse", -1);
+    fOptions.Add("type", "ESD|AOD|USER", "Input data stype");
+    fOptions.Add("setup", "Only do the setup");
     fEscapedName = EscapeName(fName, "");
   }
   TrainSetup(const TrainSetup& o) 
@@ -151,7 +152,7 @@ struct TrainSetup
     if (!fHelper->LoadAliROOT()) return false;
 
     // --- Create analysis manager -----------------------------------
-    AliAnalysisManager *mgr  = CreateAnalysisManager(fName);
+    AliAnalysisManager *mgr  = CreateAnalysisManager(fEscapedName);
 
     // In test mode, collect system information on every event 
     // if (oper == kTest)  mgr->SetNSysInfo(1); 
@@ -220,13 +221,19 @@ struct TrainSetup
 
     return true;
   }
-  Bool_t Run(Bool_t doExit=false)
+  Bool_t Run()
   {
     TString cwd = gSystem->WorkingDirectory();
     Bool_t status = false;
     try {
       if (!Init()) throw TString("Failed to intialize the train");
 
+      // Check if we're asked to only do the setup 
+      if (fOptions.Has("setup")) {
+       status = true;
+       throw TString("Only did setup, no running");
+      }
+
       // if (r) SaveSetup(*r, nEvents, asShell);
       
       Long64_t nEvents = fOptions.AsLong("events", -1);
@@ -241,14 +248,12 @@ struct TrainSetup
       status = true;
     }
     catch (TString& e) {
-      Error("Main", e);
-      status = false;
-    }
-    if (gApplication && doExit) {
-      gSystem->Sleep(3);
-      gApplication->Terminate(status ? 0 : 1);
+      if (status) 
+       Warning("Main", e);
+      else 
+       Error("Main", e);
     }
-    return true;
+    return status;
   }
   /** 
    * Get the options 
@@ -280,7 +285,7 @@ struct TrainSetup
     if (!fOptions.Has("help")) return true;
 
     if (asProg) 
-      o << "Usage: runTrain --name=NAME --class=CLASS [OPTIONS]";
+      o << "Usage: runTrain2 --name=NAME --class=CLASS [OPTIONS]";
     else 
       o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
     
@@ -334,47 +339,53 @@ struct TrainSetup
                     const TCollection* opts, 
                     Bool_t asProg=true)
   {
-    if (cls.IsNull()) { 
-      Error("Main", "No class name specified");
-      return false;
-    }
-    if (name.IsNull()) { 
-      Error("Main", "No train name specified");
-      return false;
-    }
-    Int_t error = 0;
-    Int_t r1 = gROOT->LoadMacro(Form("%s.C++g", cls.Data()), &error);
-    if (r1 < 0 || error) { 
-      Error("Main", "Failed to load setup %s: %d", cls.Data(), error);
-      return false;
-    }
+    Bool_t ret = false;
+    try {
+      if (cls.IsNull()) 
+       throw TString("No class name specified");
+      if (name.IsNull()) 
+       throw TString("No train name specified");
 
-    // Make our object using the interpreter 
-    TString create = TString::Format("new %s(\"%s\")", 
-                                  cls.Data(), name.Data());
-    gROOT->ProcessLine("gSystem->RedirectOutput(\"/dev/null\",\"w\");");
-    Long_t ret = gROOT->ProcessLine(create, &error);
-    gROOT->ProcessLine("gSystem->RedirectOutput(0);");
-    if (!ret || error) { 
-      Error("Main", "Failed to make object of class %s: 0x%08lx/%d\n\t%s", 
-           cls.Data(), ret, error, create.Data());
-      return false;
-    }
-    TrainSetup* train = reinterpret_cast<TrainSetup*>(ret);
+      Int_t error = 0;
+      Int_t r1 = gROOT->LoadMacro(Form("%s.C++g", cls.Data()), &error);
+      if (r1 < 0 || error) 
+       throw TString::Format("Failed to load setup %s: %d", cls.Data(), error);
+
+      // Make our object using the interpreter 
+      TString create = TString::Format("new %s(\"%s\")", 
+                                      cls.Data(), name.Data());
+      gROOT->ProcessLine("gSystem->RedirectOutput(\"/dev/null\",\"w\");");
+      Long_t retP = gROOT->ProcessLine(create, &error);
+      gROOT->ProcessLine("gSystem->RedirectOutput(0);");
+      if (!retP || error) 
+       throw TString::Format("Failed to make object of class %s: "
+                             "0x%08lx/%d\n\t%s", 
+                             cls.Data(), retP, error, create.Data());
+
+      TrainSetup* train = reinterpret_cast<TrainSetup*>(retP);
     
-    // Now parse the options 
-    if (!train->Options().Parse(opts)) { 
-      Error("Main", "Failed to parse options");
-      return false;
-    }
+      // Now parse the options 
+      if (!train->Options().Parse(opts)) 
+       throw TString("Failed to parse options");
 
-    // Check if we got a help request
-    if (train->Options().Has("help")) { 
-      train->Help(std::cout, asProg);
-      return true;
+      // Check if we got a help request
+      if (train->Options().Has("help")) { 
+       train->Help(std::cout, asProg);
+       ret = true;
+       throw TString("");
+      }
+
+      // return train->Init();
+      ret = train->Run();
+    }
+    catch (TString& e) { 
+      if (!e.IsNull()) Error("Main", e);
+    }
+    if (gApplication && asProg) {
+      gSystem->Sleep(3);
+      gApplication->Terminate(ret ? 0 : 1);
     }
-    // return train->Init();
-    return train->Run(asProg);
+    return ret;
   }
 protected:
   //__________________________________________________________________
@@ -534,6 +545,7 @@ protected:
                                  "%c", // Locale 
                                  "%Ex EX", // Locale 
                                  "%x %X", // Locale 
+                                 "%Y%m%d_%H%M", // YYYYMMDD_HHMM
                                  "%F %R", // ISO standard, no seconds 
                                  0 };
        const char** f = formats;
@@ -549,8 +561,10 @@ protected:
          if (strptime(datimeStr.Data(), *f, &t) != 0) found = true;
          f++;
        }
-       if (found) 
+       if (found) {
+         t.tm_mon += 1; // Return 0-based month
          datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0); 
+       }
       }
       if (datime.GetYear() <= 1995 ||
          datime.GetMonth() == 0 || 
@@ -617,10 +631,16 @@ protected:
   virtual void SaveSetup(Bool_t asShellScript)
   {
     OptionList tmp(fOptions);
+    const OptionList* uopts = (fHelper ? &fHelper->Options() : 0);
     if (tmp.Find("overwrite")) tmp.Set("overwrite");
+    if (tmp.Find("date") && fEscapedName.Length() > fName.Length()+1) {
+      Int_t n = fName.Length()+1;
+      tmp.Set("date", fEscapedName(n, fEscapedName.Length()-n));
+    }
     if (asShellScript) 
-      SaveSetupShell("rerun", ClassName(), fName, tmp);
-    SaveSetupROOT("ReRun", ClassName(), fName, tmp);
+      SaveSetupShell("rerun", ClassName(), fName, tmp, uopts);
+    SaveSetupROOT("ReRun", ClassName(), fName, tmp, uopts);
+    if (fHelper) fHelper->AuxSave(fEscapedName, asShellScript);
   }
   /** 
    * Save a setup as a shell script 
@@ -631,7 +651,8 @@ protected:
    * @param opts  Option list
    */
   static void SaveSetupShell(const TString& out, const TString& cls,
-                             const TString& name, const OptionList& opts)
+                            const TString& name, const OptionList& opts,
+                            const OptionList* uopts)
   {
     std::ofstream o(Form("%s.sh", out.Data()));
     o << "#!/bin/bash\n\n"
@@ -640,13 +661,19 @@ protected:
       << "# Available options\n"
       << "# \n";
     opts.Help(o, "#    --");
+    if (uopts) {
+      o << "#\n"
+       << "# Available URI options\n"
+       << "# \n";
+      uopts->Help(o, "#      ");
+    }
     o << "#\n"
       << "opts=(--class=$class \\\n"
       << "  --name=$name";
     opts.Store(o, " \\\n  --", "", true);
     o << ")\n\n"
-      << "echo \"Running runTrain ${opts[@]} $@\"\n"
-      << "runTrain \"${opts[@]}\" $@\n\n"
+      << "echo \"Running runTrain2 ${opts[@]} $@\"\n"
+      << "runTrain2 \"${opts[@]}\" $@\n\n"
       << "# EOF" << std::endl;
     o.close();
     gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
@@ -660,20 +687,28 @@ protected:
    * @param opts  Option list
    */
   static void SaveSetupROOT(const TString& out, const TString& cls,
-                           const TString& name, const OptionList& opts)
+                           const TString& name, const OptionList& opts,
+                           const OptionList* uopts)
   {
     OptionList tmp(opts);
     tmp.Remove("url");
+
     std::ofstream o(Form("%s.C", out.Data()));
-    o << "/* Available options:\n"
-      << " *\n";
-    tmp.Help(o, " *    ");
-    o << " */\n"
-      << "Bool_t " << out << "()\n"
+    o << "// Available options:\n"
+      << "// \n";
+    tmp.Help(o, "//     ");
+    if (uopts) {
+      o << "// \n"
+       << "// Available URI options\n";
+      uopts->Help(o, "//      ");
+    }
+    o << "//\n"
+      << "Bool_t " << out << "()\n" 
       << "{\n"
       << "  TString name(\"" << name << "\");\n"
       << "  TString cls(\"" << cls << "\");\n"
-      << "  TString uri(\"" << opts.Get("url") << "\");\n"
+      << "  TUrl    uri(\"" << opts.Get("url") << "\");\n"
+      << "  \n"
       << "  TString opts(";
     tmp.Store(o, "\"", ",\"\n               ", false);
     o << ");\n\n"