+//______________________________________________________________________________
+void AliAnalysisAlien::WriteMergingMacro()
+{
+// Write a macro to merge the outputs per master job.
+ if (!fMergeViaJDL) return;
+ if (!fOutputFiles.Length()) {
+ Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
+ return;
+ }
+ TString mergingMacro = fExecutable;
+ mergingMacro.ReplaceAll(".sh","_merge.C");
+ if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
+ if (!TestBit(AliAnalysisGrid::kSubmit)) {
+ ofstream out;
+ out.open(mergingMacro.Data(), ios::out);
+ if (!out.good()) {
+ Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
+ return;
+ }
+ Bool_t hasSTEERBase = kFALSE;
+ Bool_t hasESD = kFALSE;
+ Bool_t hasAOD = kFALSE;
+ Bool_t hasANALYSIS = kFALSE;
+ Bool_t hasANALYSISalice = kFALSE;
+ Bool_t hasCORRFW = kFALSE;
+ TString func = mergingMacro;
+ TString comment;
+ func.ReplaceAll(".C", "");
+ out << "void " << func.Data() << "(const char *dir, Int_t stage=0, Int_t laststage=0)" << endl;
+ out << "{" << endl;
+ out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
+ out << " TStopwatch timer;" << endl;
+ out << " timer.Start();" << endl << endl;
+ // Reset existing include path
+ out << "// Reset existing include path and add current directory first in the search" << endl;
+ out << " gSystem->SetIncludePath(\"-I.\");" << endl;
+ if (!fExecutableCommand.Contains("aliroot")) {
+ out << "// load base root libraries" << endl;
+ out << " gSystem->Load(\"libTree\");" << endl;
+ out << " gSystem->Load(\"libGeom\");" << endl;
+ out << " gSystem->Load(\"libVMC\");" << endl;
+ out << " gSystem->Load(\"libPhysics\");" << endl << endl;
+ out << " gSystem->Load(\"libMinuit\");" << endl << endl;
+ }
+ if (fAdditionalRootLibs.Length()) {
+ // in principle libtree /lib geom libvmc etc. can go into this list, too
+ out << "// Add aditional libraries" << endl;
+ TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
+ TIter next(list);
+ TObjString *str;
+ while((str=(TObjString*)next())) {
+ if (str->GetString().Contains(".so"))
+ out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
+ }
+ if (list) delete list;
+ }
+ out << "// Load analysis framework libraries" << endl;
+ if (!fPackages) {
+ if (!fExecutableCommand.Contains("aliroot")) {
+ out << " gSystem->Load(\"libSTEERBase\");" << endl;
+ out << " gSystem->Load(\"libESD\");" << endl;
+ out << " gSystem->Load(\"libAOD\");" << endl;
+ }
+ out << " gSystem->Load(\"libANALYSIS\");" << endl;
+ out << " gSystem->Load(\"libANALYSISalice\");" << endl;
+ out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
+ } else {
+ TIter next(fPackages);
+ TObject *obj;
+ TString pkgname;
+ TString setupPar = "AliAnalysisAlien::SetupPar";
+ while ((obj=next())) {
+ pkgname = obj->GetName();
+ if (pkgname == "STEERBase" ||
+ pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
+ if (pkgname == "ESD" ||
+ pkgname == "ESD.par") hasESD = kTRUE;
+ if (pkgname == "AOD" ||
+ pkgname == "AOD.par") hasAOD = kTRUE;
+ if (pkgname == "ANALYSIS" ||
+ pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
+ if (pkgname == "ANALYSISalice" ||
+ pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
+ if (pkgname == "CORRFW" ||
+ pkgname == "CORRFW.par") hasCORRFW = kTRUE;
+ }
+ if (hasANALYSISalice) setupPar = "SetupPar";
+ if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
+ else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
+ if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
+ else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
+ if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
+ else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
+ if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
+ else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
+ if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
+ else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
+ if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
+ else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
+ out << "// Compile other par packages" << endl;
+ next.Reset();
+ while ((obj=next())) {
+ pkgname = obj->GetName();
+ if (pkgname == "STEERBase" ||
+ pkgname == "STEERBase.par" ||
+ pkgname == "ESD" ||
+ pkgname == "ESD.par" ||
+ pkgname == "AOD" ||
+ pkgname == "AOD.par" ||
+ pkgname == "ANALYSIS" ||
+ pkgname == "ANALYSIS.par" ||
+ pkgname == "ANALYSISalice" ||
+ pkgname == "ANALYSISalice.par" ||
+ pkgname == "CORRFW" ||
+ pkgname == "CORRFW.par") continue;
+ out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
+ }
+ }
+ out << "// include path" << endl;
+ // Get the include path from the interpreter and remove entries pointing to AliRoot
+ out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
+ out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
+ out << " TIter nextpath(listpaths);" << endl;
+ out << " TObjString *pname;" << endl;
+ out << " while ((pname=(TObjString*)nextpath())) {" << endl;
+ out << " TString current = pname->GetName();" << endl;
+ out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
+ out << " gSystem->AddIncludePath(current);" << endl;
+ out << " }" << endl;
+ out << " if (listpaths) delete listpaths;" << endl;
+ if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
+ out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
+ out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
+ if (fAdditionalLibs.Length()) {
+ out << "// Add aditional AliRoot libraries" << endl;
+ TObjArray *list = fAdditionalLibs.Tokenize(" ");
+ TIter next(list);
+ TObjString *str;
+ while((str=(TObjString*)next())) {
+ if (str->GetString().Contains(".so"))
+ out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
+ }
+ if (list) delete list;
+ }
+ out << endl;
+ out << "// Analysis source to be compiled at runtime (if any)" << endl;
+ if (fAnalysisSource.Length()) {
+ TObjArray *list = fAnalysisSource.Tokenize(" ");
+ TIter next(list);
+ TObjString *str;
+ while((str=(TObjString*)next())) {
+ out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
+ }
+ if (list) delete list;
+ }
+ out << endl;
+
+ if (fFastReadOption) {
+ Warning("WriteMergingMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid merging jobs. Note that this may skip some files that could be accessed !!!");
+ out << "// fast xrootd reading enabled" << endl;
+ out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
+ out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
+ out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
+ out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
+ out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
+ out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
+ }
+ // Change temp directory to current one
+ out << "// Set temporary merging directory to current one" << endl;
+ out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
+ out << "// Connect to AliEn" << endl;
+ out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
+ out << " TString outputDir = dir;" << endl;
+ out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
+ out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
+ out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
+ out << " TIter *iter = new TIter(list);" << endl;
+ out << " TObjString *str;" << endl;
+ out << " TString outputFile;" << endl;
+ out << " Bool_t merged = kTRUE;" << endl;
+ out << " while((str=(TObjString*)iter->Next())) {" << endl;
+ out << " outputFile = str->GetString();" << endl;
+ out << " if (outputFile.Contains(\"*\")) continue;" << endl;
+ out << " Int_t index = outputFile.Index(\"@\");" << endl;
+ out << " if (index > 0) outputFile.Remove(index);" << endl;
+ out << " // Skip already merged outputs" << endl;
+ out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
+ out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
+ out << " continue;" << endl;
+ out << " }" << endl;
+ out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
+ out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
+ out << " if (!merged) {" << endl;
+ out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
+ out << " return;" << endl;
+ out << " }" << endl;
+ out << " }" << endl;
+ out << " // all outputs merged, validate" << endl;
+ out << " ofstream out;" << endl;
+ out << " out.open(\"outputs_valid\", ios::out);" << endl;
+ out << " out.close();" << endl;
+ out << " // read the analysis manager from file" << endl;
+ TString analysisFile = fExecutable;
+ analysisFile.ReplaceAll(".sh", ".root");
+ out << " if (laststage<10000) return;" << endl;
+ out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
+ out << " if (!file) return;" << endl;
+ out << " TIter nextkey(file->GetListOfKeys());" << endl;
+ out << " AliAnalysisManager *mgr = 0;" << endl;
+ out << " TKey *key;" << endl;
+ out << " while ((key=(TKey*)nextkey())) {" << endl;
+ out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
+ out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
+ out << " };" << endl;
+ out << " if (!mgr) {" << endl;
+ out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
+ out << " return;" << endl;
+ out << " }" << endl << endl;
+ out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
+ out << " mgr->SetSkipTerminate(kFALSE);" << endl;
+ out << " mgr->PrintStatus();" << endl;
+ if (AliAnalysisManager::GetAnalysisManager()) {
+ if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
+ out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
+ } else {
+ if (TestBit(AliAnalysisGrid::kTest))
+ out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
+ else
+ out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
+ }
+ }
+ out << " TTree *tree = NULL;" << endl;
+ out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
+ out << "}" << endl << endl;
+ if (hasANALYSISalice) {
+ out <<"//________________________________________________________________________________" << endl;
+ out << "Bool_t SetupPar(const char *package) {" << endl;
+ out << "// Compile the package and set it up." << endl;
+ out << " TString pkgdir = package;" << endl;
+ out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
+ out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
+ out << " TString cdir = gSystem->WorkingDirectory();" << endl;
+ out << " gSystem->ChangeDirectory(pkgdir);" << endl;
+ out << " // Check for BUILD.sh and execute" << endl;
+ out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
+ out << " printf(\"*******************************\\n\");" << endl;
+ out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
+ out << " printf(\"*******************************\\n\");" << endl;
+ out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
+ out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
+ out << " gSystem->ChangeDirectory(cdir);" << endl;
+ out << " return kFALSE;" << endl;
+ out << " }" << endl;
+ out << " } else {" << endl;
+ out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
+ out << " gSystem->ChangeDirectory(cdir);" << endl;
+ out << " return kFALSE;" << endl;
+ out << " }" << endl;
+ out << " // Check for SETUP.C and execute" << endl;
+ out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
+ out << " printf(\"*******************************\\n\");" << endl;
+ out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
+ out << " printf(\"*******************************\\n\");" << endl;
+ out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
+ out << " } else {" << endl;
+ out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
+ out << " gSystem->ChangeDirectory(cdir);" << endl;
+ out << " return kFALSE;" << endl;
+ out << " }" << endl;
+ out << " // Restore original workdir" << endl;
+ out << " gSystem->ChangeDirectory(cdir);" << endl;
+ out << " return kTRUE;" << endl;
+ out << "}" << endl;
+ }
+ }
+ Bool_t copy = kTRUE;
+ if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
+ if (copy) {
+ CdWork();
+ TString workdir = gGrid->GetHomeDirectory();
+ workdir += fGridWorkingDir;
+ if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
+ Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
+ TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
+ }
+}
+
+//______________________________________________________________________________
+Bool_t AliAnalysisAlien::SetupPar(const char *package)
+{
+// Compile the par file archive pointed by <package>. This must be present in the current directory.
+// Note that for loading the compiled library. The current directory should have precedence in
+// LD_LIBRARY_PATH
+ TString pkgdir = package;
+ pkgdir.ReplaceAll(".par","");
+ gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
+ TString cdir = gSystem->WorkingDirectory();
+ gSystem->ChangeDirectory(pkgdir);
+ // Check for BUILD.sh and execute
+ if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
+ printf("**************************************************\n");
+ printf("*** Building PAR archive %s\n", package);
+ printf("**************************************************\n");
+ if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
+ ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
+ gSystem->ChangeDirectory(cdir);
+ return kFALSE;
+ }
+ } else {
+ ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
+ gSystem->ChangeDirectory(cdir);
+ return kFALSE;
+ }
+ // Check for SETUP.C and execute
+ if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
+ printf("**************************************************\n");
+ printf("*** Setup PAR archive %s\n", package);
+ printf("**************************************************\n");
+ gROOT->Macro("PROOF-INF/SETUP.C");
+ printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
+ } else {
+ ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
+ gSystem->ChangeDirectory(cdir);
+ return kFALSE;
+ }
+ // Restore original workdir
+ gSystem->ChangeDirectory(cdir);
+ return kTRUE;
+}
+