1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "AliAnalysisAlien.h"
25 #include "Riostream.h"
33 #include "TFileCollection.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
39 #include "TGridResult.h"
40 #include "TGridCollection.h"
42 #include "TGridJobStatusList.h"
43 #include "TGridJobStatus.h"
44 #include "TFileMerger.h"
45 #include "AliAnalysisManager.h"
46 #include "AliAnalysisTaskCfg.h"
47 #include "AliVEventHandler.h"
48 #include "AliAnalysisDataContainer.h"
49 #include "AliMultiInputEventHandler.h"
51 ClassImp(AliAnalysisAlien)
57 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
59 TString sl(Form("file:%s", loc));
60 TString sr(Form("alien://%s", rem));
61 Bool_t ret = TFile::Cp(sl, sr);
63 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
69 //______________________________________________________________________________
70 AliAnalysisAlien::AliAnalysisAlien()
76 fSplitMaxInputFileNumber(0),
78 fMasterResubmitThreshold(0),
91 fNproofWorkersPerSlave(0),
101 fAdditionalRootLibs(),
130 fRootVersionForProof(),
142 //______________________________________________________________________________
143 AliAnalysisAlien::AliAnalysisAlien(const char *name)
144 :AliAnalysisGrid(name),
149 fSplitMaxInputFileNumber(0),
151 fMasterResubmitThreshold(0),
164 fNproofWorkersPerSlave(0),
168 fExecutableCommand(),
174 fAdditionalRootLibs(),
203 fRootVersionForProof(),
215 //______________________________________________________________________________
216 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
217 :AliAnalysisGrid(other),
220 fPrice(other.fPrice),
222 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
223 fMaxInitFailed(other.fMaxInitFailed),
224 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
225 fNtestFiles(other.fNtestFiles),
226 fNrunsPerMaster(other.fNrunsPerMaster),
227 fMaxMergeFiles(other.fMaxMergeFiles),
228 fMaxMergeStages(other.fMaxMergeStages),
229 fNsubmitted(other.fNsubmitted),
230 fProductionMode(other.fProductionMode),
231 fOutputToRunNo(other.fOutputToRunNo),
232 fMergeViaJDL(other.fMergeViaJDL),
233 fFastReadOption(other.fFastReadOption),
234 fOverwriteMode(other.fOverwriteMode),
235 fNreplicas(other.fNreplicas),
236 fNproofWorkers(other.fNproofWorkers),
237 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
238 fProofReset(other.fProofReset),
239 fRunNumbers(other.fRunNumbers),
240 fExecutable(other.fExecutable),
241 fExecutableCommand(other.fExecutableCommand),
242 fArguments(other.fArguments),
243 fExecutableArgs(other.fExecutableArgs),
244 fAnalysisMacro(other.fAnalysisMacro),
245 fAnalysisSource(other.fAnalysisSource),
246 fValidationScript(other.fValidationScript),
247 fAdditionalRootLibs(other.fAdditionalRootLibs),
248 fAdditionalLibs(other.fAdditionalLibs),
249 fSplitMode(other.fSplitMode),
250 fAPIVersion(other.fAPIVersion),
251 fROOTVersion(other.fROOTVersion),
252 fAliROOTVersion(other.fAliROOTVersion),
253 fExternalPackages(other.fExternalPackages),
255 fGridWorkingDir(other.fGridWorkingDir),
256 fGridDataDir(other.fGridDataDir),
257 fDataPattern(other.fDataPattern),
258 fGridOutputDir(other.fGridOutputDir),
259 fOutputArchive(other.fOutputArchive),
260 fOutputFiles(other.fOutputFiles),
261 fInputFormat(other.fInputFormat),
262 fDatasetName(other.fDatasetName),
263 fJDLName(other.fJDLName),
264 fTerminateFiles(other.fTerminateFiles),
265 fMergeExcludes(other.fMergeExcludes),
266 fRegisterExcludes(other.fRegisterExcludes),
267 fIncludePath(other.fIncludePath),
268 fCloseSE(other.fCloseSE),
269 fFriendChainName(other.fFriendChainName),
270 fJobTag(other.fJobTag),
271 fOutputSingle(other.fOutputSingle),
272 fRunPrefix(other.fRunPrefix),
273 fProofCluster(other.fProofCluster),
274 fProofDataSet(other.fProofDataSet),
275 fFileForTestMode(other.fFileForTestMode),
276 fRootVersionForProof(other.fRootVersionForProof),
277 fAliRootMode(other.fAliRootMode),
278 fMergeDirName(other.fMergeDirName),
285 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
286 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
287 fRunRange[0] = other.fRunRange[0];
288 fRunRange[1] = other.fRunRange[1];
289 if (other.fInputFiles) {
290 fInputFiles = new TObjArray();
291 TIter next(other.fInputFiles);
293 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
294 fInputFiles->SetOwner();
296 if (other.fPackages) {
297 fPackages = new TObjArray();
298 TIter next(other.fPackages);
300 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
301 fPackages->SetOwner();
303 if (other.fModules) {
304 fModules = new TObjArray();
305 fModules->SetOwner();
306 TIter next(other.fModules);
307 AliAnalysisTaskCfg *mod, *crt;
308 while ((crt=(AliAnalysisTaskCfg*)next())) {
309 mod = new AliAnalysisTaskCfg(*crt);
315 //______________________________________________________________________________
316 AliAnalysisAlien::~AliAnalysisAlien()
324 fProofParam.DeleteAll();
327 //______________________________________________________________________________
328 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
331 if (this != &other) {
332 AliAnalysisGrid::operator=(other);
333 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
334 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
335 fPrice = other.fPrice;
337 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
338 fMaxInitFailed = other.fMaxInitFailed;
339 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
340 fNtestFiles = other.fNtestFiles;
341 fNrunsPerMaster = other.fNrunsPerMaster;
342 fMaxMergeFiles = other.fMaxMergeFiles;
343 fMaxMergeStages = other.fMaxMergeStages;
344 fNsubmitted = other.fNsubmitted;
345 fProductionMode = other.fProductionMode;
346 fOutputToRunNo = other.fOutputToRunNo;
347 fMergeViaJDL = other.fMergeViaJDL;
348 fFastReadOption = other.fFastReadOption;
349 fOverwriteMode = other.fOverwriteMode;
350 fNreplicas = other.fNreplicas;
351 fNproofWorkers = other.fNproofWorkers;
352 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
353 fProofReset = other.fProofReset;
354 fRunNumbers = other.fRunNumbers;
355 fExecutable = other.fExecutable;
356 fExecutableCommand = other.fExecutableCommand;
357 fArguments = other.fArguments;
358 fExecutableArgs = other.fExecutableArgs;
359 fAnalysisMacro = other.fAnalysisMacro;
360 fAnalysisSource = other.fAnalysisSource;
361 fValidationScript = other.fValidationScript;
362 fAdditionalRootLibs = other.fAdditionalRootLibs;
363 fAdditionalLibs = other.fAdditionalLibs;
364 fSplitMode = other.fSplitMode;
365 fAPIVersion = other.fAPIVersion;
366 fROOTVersion = other.fROOTVersion;
367 fAliROOTVersion = other.fAliROOTVersion;
368 fExternalPackages = other.fExternalPackages;
370 fGridWorkingDir = other.fGridWorkingDir;
371 fGridDataDir = other.fGridDataDir;
372 fDataPattern = other.fDataPattern;
373 fGridOutputDir = other.fGridOutputDir;
374 fOutputArchive = other.fOutputArchive;
375 fOutputFiles = other.fOutputFiles;
376 fInputFormat = other.fInputFormat;
377 fDatasetName = other.fDatasetName;
378 fJDLName = other.fJDLName;
379 fTerminateFiles = other.fTerminateFiles;
380 fMergeExcludes = other.fMergeExcludes;
381 fRegisterExcludes = other.fRegisterExcludes;
382 fIncludePath = other.fIncludePath;
383 fCloseSE = other.fCloseSE;
384 fFriendChainName = other.fFriendChainName;
385 fJobTag = other.fJobTag;
386 fOutputSingle = other.fOutputSingle;
387 fRunPrefix = other.fRunPrefix;
388 fProofCluster = other.fProofCluster;
389 fProofDataSet = other.fProofDataSet;
390 fFileForTestMode = other.fFileForTestMode;
391 fRootVersionForProof = other.fRootVersionForProof;
392 fAliRootMode = other.fAliRootMode;
393 fMergeDirName = other.fMergeDirName;
394 if (other.fInputFiles) {
395 fInputFiles = new TObjArray();
396 TIter next(other.fInputFiles);
398 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
399 fInputFiles->SetOwner();
401 if (other.fPackages) {
402 fPackages = new TObjArray();
403 TIter next(other.fPackages);
405 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
406 fPackages->SetOwner();
408 if (other.fModules) {
409 fModules = new TObjArray();
410 fModules->SetOwner();
411 TIter next(other.fModules);
412 AliAnalysisTaskCfg *mod, *crt;
413 while ((crt=(AliAnalysisTaskCfg*)next())) {
414 mod = new AliAnalysisTaskCfg(*crt);
422 //______________________________________________________________________________
423 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
425 // Add a single additional library to be loaded. Extension must be present.
427 if (!lib.Contains(".")) {
428 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
431 if (fAdditionalLibs.Contains(name)) {
432 Warning("AddAdditionalLibrary", "Library %s already added.", name);
435 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
436 fAdditionalLibs += lib;
439 //______________________________________________________________________________
440 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
442 // Adding a module. Checks if already existing. Becomes owned by this.
444 if (GetModule(module->GetName())) {
445 Error("AddModule", "A module having the same name %s already added", module->GetName());
449 fModules = new TObjArray();
450 fModules->SetOwner();
452 fModules->Add(module);
455 //______________________________________________________________________________
456 void AliAnalysisAlien::AddModules(TObjArray *list)
458 // Adding a list of modules. Checks if already existing. Becomes owned by this.
460 AliAnalysisTaskCfg *module;
461 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
464 //______________________________________________________________________________
465 Bool_t AliAnalysisAlien::CheckDependencies()
467 // Check if all dependencies are satisfied. Reorder modules if needed.
468 Int_t nmodules = GetNmodules();
470 Warning("CheckDependencies", "No modules added yet to check their dependencies");
473 AliAnalysisTaskCfg *mod = 0;
474 AliAnalysisTaskCfg *dep = 0;
477 for (i=0; i<nmodules; i++) {
478 mod = (AliAnalysisTaskCfg*) fModules->At(i);
479 Int_t ndeps = mod->GetNdeps();
481 for (j=0; j<ndeps; j++) {
482 depname = mod->GetDependency(j);
483 dep = GetModule(depname);
485 Error("CheckDependencies","Dependency %s not added for module %s",
486 depname.Data(), mod->GetName());
489 if (dep->NeedsDependency(mod->GetName())) {
490 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
491 mod->GetName(), dep->GetName());
494 Int_t idep = fModules->IndexOf(dep);
495 // The dependency task must come first
497 // Remove at idep and move all objects below up one slot
498 // down to index i included.
499 fModules->RemoveAt(idep);
500 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
501 fModules->AddAt(dep, i++);
503 //Redo from istart if dependencies were inserted
504 if (i>istart) i=istart-1;
510 //______________________________________________________________________________
511 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
513 // Create the analysis manager and optionally execute the macro in filename.
514 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
516 mgr = new AliAnalysisManager(name);
517 mgr->SetGridHandler((AliAnalysisGrid*)this);
518 if (strlen(filename)) {
519 TString line = gSystem->ExpandPathName(filename);
521 gROOT->ProcessLine(line.Data());
526 //______________________________________________________________________________
527 Int_t AliAnalysisAlien::GetNmodules() const
529 // Get number of modules.
530 if (!fModules) return 0;
531 return fModules->GetEntries();
534 //______________________________________________________________________________
535 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
537 // Get a module by name.
538 if (!fModules) return 0;
539 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
542 //______________________________________________________________________________
543 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
545 // Load a given module.
546 if (mod->IsLoaded()) return kTRUE;
547 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
549 Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
552 Int_t ndeps = mod->GetNdeps();
554 for (Int_t j=0; j<ndeps; j++) {
555 depname = mod->GetDependency(j);
556 AliAnalysisTaskCfg *dep = GetModule(depname);
558 Error("LoadModule","Dependency %s not existing for module %s",
559 depname.Data(), mod->GetName());
562 if (!LoadModule(dep)) {
563 Error("LoadModule","Dependency %s for module %s could not be loaded",
564 depname.Data(), mod->GetName());
568 // Load libraries for the module
569 if (!mod->CheckLoadLibraries()) {
570 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
573 // Check if a custom file name was requested
574 if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
576 // Check if a custom terminate file name was requested
577 if (strlen(mod->GetTerminateFileName())) {
578 if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
579 fTerminateFiles += mod->GetTerminateFileName();
583 if (mod->ExecuteMacro()<0) {
584 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
585 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
588 // Configure dependencies
589 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
590 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
591 mod->GetConfigMacro()->GetTitle(), mod->GetName());
594 // Adjust extra libraries
595 Int_t nlibs = mod->GetNlibs();
597 for (Int_t i=0; i<nlibs; i++) {
598 lib = mod->GetLibrary(i);
599 if (fAdditionalLibs.Contains(lib)) continue;
600 lib = Form("lib%s.so", lib.Data());
601 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
602 fAdditionalLibs += lib;
607 //______________________________________________________________________________
608 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
610 // Generate the full train.
611 fAdditionalLibs = "";
612 if (!LoadModules()) return kFALSE;
613 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
614 if (!mgr->InitAnalysis()) return kFALSE;
617 Int_t productionMode = fProductionMode;
619 TString macro = fAnalysisMacro;
620 TString executable = fExecutable;
621 TString validation = fValidationScript;
622 TString execCommand = fExecutableCommand;
623 SetAnalysisMacro(Form("%s.C", name));
624 SetExecutable(Form("%s.sh", name));
625 // SetExecutableCommand("aliroot -b -q ");
626 SetValidationScript(Form("%s_validation.sh", name));
628 SetProductionMode(productionMode);
629 fAnalysisMacro = macro;
630 fExecutable = executable;
631 fExecutableCommand = execCommand;
632 fValidationScript = validation;
636 //______________________________________________________________________________
637 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
639 // Generate test macros for a single module or for the full train.
640 fAdditionalLibs = "";
641 if (strlen(modname)) {
642 if (!CheckDependencies()) return kFALSE;
643 AliAnalysisTaskCfg *mod = GetModule(modname);
645 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
648 if (!LoadModule(mod)) return kFALSE;
649 } else if (!LoadModules()) return kFALSE;
650 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
651 if (!mgr->InitAnalysis()) return kFALSE;
655 Int_t productionMode = fProductionMode;
657 TString macro = fAnalysisMacro;
658 TString executable = fExecutable;
659 TString validation = fValidationScript;
660 TString execCommand = fExecutableCommand;
661 SetAnalysisMacro(Form("%s.C", name));
662 SetExecutable(Form("%s.sh", name));
663 // SetExecutableCommand("aliroot -b -q ");
664 SetValidationScript(Form("%s_validation.sh", name));
666 WriteAnalysisMacro();
668 WriteValidationScript();
669 SetLocalTest(kFALSE);
670 SetProductionMode(productionMode);
671 fAnalysisMacro = macro;
672 fExecutable = executable;
673 fExecutableCommand = execCommand;
674 fValidationScript = validation;
678 //______________________________________________________________________________
679 Bool_t AliAnalysisAlien::LoadModules()
681 // Load all modules by executing the AddTask macros. Checks first the dependencies.
682 fAdditionalLibs = "";
683 Int_t nmodules = GetNmodules();
685 Warning("LoadModules", "No module to be loaded");
688 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
690 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
693 if (!CheckDependencies()) return kFALSE;
694 nmodules = GetNmodules();
695 AliAnalysisTaskCfg *mod;
696 for (Int_t imod=0; imod<nmodules; imod++) {
697 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
698 if (!LoadModule(mod)) return kFALSE;
703 //______________________________________________________________________________
704 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
706 // Set the run number format. Can be a prefix or a format like "%09d"
708 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
711 //______________________________________________________________________________
712 void AliAnalysisAlien::AddIncludePath(const char *path)
714 // Add include path in the remote analysis macro.
716 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
717 else fIncludePath += Form("-I%s ", path);
720 //______________________________________________________________________________
721 void AliAnalysisAlien::AddRunNumber(Int_t run)
723 // Add a run number to the list of runs to be processed.
724 if (fRunNumbers.Length()) fRunNumbers += " ";
725 fRunNumbers += Form(fRunPrefix.Data(), run);
728 //______________________________________________________________________________
729 void AliAnalysisAlien::AddRunList(const char* runList)
731 // Add several runs into the list of runs; they are expected to be separated by a blank character.
732 TString sList = runList;
733 TObjArray *list = sList.Tokenize(" ");
734 Int_t n = list->GetEntries();
735 for (Int_t i = 0; i < n; i++) {
736 TObjString *os = (TObjString*)list->At(i);
737 AddRunNumber(os->GetString().Atoi());
742 //______________________________________________________________________________
743 void AliAnalysisAlien::AddRunNumber(const char* run)
745 // Add a run number to the list of runs to be processed.
748 TObjArray *arr = runs.Tokenize(" ");
751 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
752 while ((os=(TObjString*)next())){
753 if (fRunNumbers.Length()) fRunNumbers += " ";
754 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
759 //______________________________________________________________________________
760 void AliAnalysisAlien::AddDataFile(const char *lfn)
762 // Adds a data file to the input to be analysed. The file should be a valid LFN
763 // or point to an existing file in the alien workdir.
764 if (!fInputFiles) fInputFiles = new TObjArray();
765 fInputFiles->Add(new TObjString(lfn));
768 //______________________________________________________________________________
769 void AliAnalysisAlien::AddExternalPackage(const char *package)
771 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
772 if (fExternalPackages) fExternalPackages += " ";
773 fExternalPackages += package;
776 //______________________________________________________________________________
777 Bool_t AliAnalysisAlien::Connect()
779 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
780 if (gGrid && gGrid->IsConnected()) return kTRUE;
781 if (fProductionMode) return kTRUE;
783 Info("Connect", "Trying to connect to AliEn ...");
784 TGrid::Connect("alien://");
786 if (!gGrid || !gGrid->IsConnected()) {
787 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
790 fUser = gGrid->GetUser();
791 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
795 //______________________________________________________________________________
796 void AliAnalysisAlien::CdWork()
798 // Check validity of alien workspace. Create directory if possible.
800 Error("CdWork", "Alien connection required");
803 TString homedir = gGrid->GetHomeDirectory();
804 TString workdir = homedir + fGridWorkingDir;
805 if (DirectoryExists(workdir)) {
809 // Work directory not existing - create it
811 if (gGrid->Mkdir(workdir, "-p")) {
812 gGrid->Cd(fGridWorkingDir);
813 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
815 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
816 workdir.Data(), homedir.Data());
817 fGridWorkingDir = "";
821 //______________________________________________________________________________
822 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
824 // Check if file copying is possible.
825 if (fProductionMode) return kTRUE;
826 TString salienpath(alienpath);
827 if (salienpath.Contains(" ")) {
828 Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
832 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
835 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
836 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
837 // Check if alien_CLOSE_SE is defined
838 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
839 if (!closeSE.IsNull()) {
840 Info("CheckFileCopy", "Your current close storage is pointing to: \
841 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
843 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
845 // Check if grid directory exists.
846 if (!DirectoryExists(alienpath)) {
847 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
850 TString stest = "plugin_test_copy";
851 TFile f(stest, "RECREATE");
852 // User may not have write permissions to current directory
854 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
855 gSystem->WorkingDirectory());
859 if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
860 if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
861 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
862 \n# 1. Make sure you have write permissions there. If this is the case: \
863 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
864 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
865 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
866 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
867 gSystem->Unlink(stest.Data());
870 gSystem->Unlink(stest.Data());
871 gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
872 Info("CheckFileCopy", "### ...SUCCESS ###");
876 //______________________________________________________________________________
877 Bool_t AliAnalysisAlien::CheckInputData()
879 // Check validity of input data. If necessary, create xml files.
880 if (fProductionMode) return kTRUE;
881 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
882 if (!fGridDataDir.Length()) {
883 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
887 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
890 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
891 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
892 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
895 // Process declared files
896 Bool_t isCollection = kFALSE;
897 Bool_t isXml = kFALSE;
898 Bool_t useTags = kFALSE;
899 Bool_t checked = kFALSE;
900 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
902 TString workdir = gGrid->GetHomeDirectory();
903 workdir += fGridWorkingDir;
906 TIter next(fInputFiles);
907 while ((objstr=(TObjString*)next())) {
910 file += objstr->GetString();
911 // Store full lfn path
912 if (FileExists(file)) objstr->SetString(file);
914 file = objstr->GetName();
915 if (!FileExists(objstr->GetName())) {
916 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
917 objstr->GetName(), workdir.Data());
921 Bool_t iscoll, isxml, usetags;
922 CheckDataType(file, iscoll, isxml, usetags);
925 isCollection = iscoll;
928 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
930 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
931 Error("CheckInputData", "Some conflict was found in the types of inputs");
937 // Process requested run numbers
938 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
939 // Check validity of alien data directory
940 if (!fGridDataDir.Length()) {
941 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
944 if (!DirectoryExists(fGridDataDir)) {
945 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
949 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
953 if (checked && !isXml) {
954 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
957 // Check validity of run number(s)
962 TString schunk, schunk2;
966 useTags = fDataPattern.Contains("tag");
967 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
969 if (useTags != fDataPattern.Contains("tag")) {
970 Error("CheckInputData", "Cannot mix input files using/not using tags");
973 if (fRunNumbers.Length()) {
974 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
975 arr = fRunNumbers.Tokenize(" ");
977 while ((os=(TObjString*)next())) {
978 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
979 if (!DirectoryExists(path)) {
980 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
983 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
984 TString msg = "\n##### file: ";
986 msg += " type: xml_collection;";
987 if (useTags) msg += " using_tags: Yes";
988 else msg += " using_tags: No";
989 Info("CheckDataType", "%s", msg.Data());
990 if (fNrunsPerMaster<2) {
991 AddDataFile(Form("%s.xml", os->GetString().Data()));
994 if (((nruns-1)%fNrunsPerMaster) == 0) {
995 schunk = os->GetString();
997 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
998 schunk += Form("_%s.xml", os->GetString().Data());
1004 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1005 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1006 format = Form("%%s/%s ", fRunPrefix.Data());
1007 path = Form(format.Data(), fGridDataDir.Data(), irun);
1008 if (!DirectoryExists(path)) {
1011 format = Form("%%s/%s.xml", fRunPrefix.Data());
1012 path = Form(format.Data(), workdir.Data(),irun);
1013 TString msg = "\n##### file: ";
1015 msg += " type: xml_collection;";
1016 if (useTags) msg += " using_tags: Yes";
1017 else msg += " using_tags: No";
1018 Info("CheckDataType", "%s", msg.Data());
1019 if (fNrunsPerMaster<2) {
1020 format = Form("%s.xml", fRunPrefix.Data());
1021 AddDataFile(Form(format.Data(),irun));
1024 if (((nruns-1)%fNrunsPerMaster) == 0) {
1025 schunk = Form(fRunPrefix.Data(),irun);
1027 format = Form("_%s.xml", fRunPrefix.Data());
1028 schunk2 = Form(format.Data(), irun);
1029 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1031 AddDataFile(schunk);
1036 AddDataFile(schunk);
1042 //______________________________________________________________________________
1043 Bool_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1045 // Copy data from the given grid directory according a pattern and make a local
1047 // archivefile (optional) results in that the archive containing the file <pattern> is copied. archivefile can contain a list of files (semicolon-separated) which are all copied
1049 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1052 if (!DirectoryExists(griddir)) {
1053 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1056 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1057 printf("Running command: %s\n", command.Data());
1058 TGridResult *res = gGrid->Command(command);
1059 Int_t nfound = res->GetEntries();
1061 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1064 printf("... found %d files. Copying locally ...\n", nfound);
1067 TObjArray* additionalArchives = 0;
1068 if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1069 additionalArchives = TString(archivefile).Tokenize(";");
1070 archivefile = additionalArchives->At(0)->GetName();
1071 additionalArchives->RemoveAt(0);
1072 additionalArchives->Compress();
1075 // Copy files locally
1077 out.open(output, ios::out);
1079 TString turl, dirname, filename, temp;
1080 TString cdir = gSystem->WorkingDirectory();
1081 gSystem->MakeDirectory(outputdir);
1082 gSystem->ChangeDirectory(outputdir);
1083 for (Int_t i=0; i<nfound; i++) {
1084 map = (TMap*)res->At(i);
1085 turl = map->GetValue("turl")->GetName();
1086 filename = gSystem->BaseName(turl.Data());
1087 dirname = gSystem->DirName(turl.Data());
1088 dirname = gSystem->BaseName(dirname.Data());
1089 gSystem->MakeDirectory(dirname);
1091 TString source(turl);
1092 TString targetFileName(filename);
1094 if (strlen(archivefile) > 0) {
1095 // TODO here the archive in which the file resides should be determined
1096 // however whereis returns only a guid, and guid2lfn does not work
1097 // Therefore we use the one provided as argument for now
1098 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1099 targetFileName = archivefile;
1101 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1102 Bool_t success = kTRUE;
1103 if (additionalArchives)
1104 for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++)
1107 target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1108 gSystem->MakeDirectory(gSystem->DirName(target));
1109 success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1113 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1114 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1118 gSystem->ChangeDirectory(cdir);
1120 if (additionalArchives)
1121 delete additionalArchives;
1125 //______________________________________________________________________________
1126 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1128 // Create dataset for the grid data directory + run number.
1129 const Int_t gMaxEntries = 15000;
1130 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1132 Error("CreateDataset", "Cannot create dataset with no grid connection");
1137 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1138 TString workdir = gGrid->GetHomeDirectory();
1139 workdir += fGridWorkingDir;
1141 // Compose the 'find' command arguments
1144 TString options = "-x collection ";
1145 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1146 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1147 TString conditions = "";
1154 TString schunk, schunk2;
1155 TGridCollection *cbase=0, *cadd=0;
1156 if (!fRunNumbers.Length() && !fRunRange[0]) {
1157 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1158 // Make a single data collection from data directory.
1159 path = fGridDataDir;
1160 if (!DirectoryExists(path)) {
1161 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1165 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1166 else file = Form("%s.xml", gSystem->BaseName(path));
1170 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1172 command += Form("%s -o %d ",options.Data(), nstart);
1176 command += conditions;
1177 printf("command: %s\n", command.Data());
1178 TGridResult *res = gGrid->Command(command);
1179 if (res) delete res;
1180 // Write standard output to file
1181 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1182 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1183 Bool_t nullFile = kFALSE;
1185 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1187 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1189 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1190 gSystem->Exec("rm -f __tmp*");
1198 gSystem->Exec("rm -f __tmp__");
1199 ncount = line.Atoi();
1202 if (ncount == gMaxEntries) {
1203 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1204 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1205 if (!cbase) cbase = cadd;
1213 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1214 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1217 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1218 delete cbase; cbase = 0;
1220 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1222 gSystem->Exec("rm -f __tmp*");
1223 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1227 Bool_t fileExists = FileExists(file);
1228 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1229 // Copy xml file to alien space
1230 if (fileExists) gGrid->Rm(file);
1231 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1232 if (!FileExists(file)) {
1233 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1236 // Update list of files to be processed.
1238 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1242 Bool_t nullResult = kTRUE;
1243 if (fRunNumbers.Length()) {
1244 TObjArray *arr = fRunNumbers.Tokenize(" ");
1247 while ((os=(TObjString*)next())) {
1250 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
1251 if (!DirectoryExists(path)) continue;
1253 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1254 else file = Form("%s.xml", os->GetString().Data());
1255 // If local collection file does not exist, create it via 'find' command.
1259 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1261 command += Form("%s -o %d ",options.Data(), nstart);
1264 command += conditions;
1265 TGridResult *res = gGrid->Command(command);
1266 if (res) delete res;
1267 // Write standard output to file
1268 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1269 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1270 Bool_t nullFile = kFALSE;
1272 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1274 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1276 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1277 gSystem->Exec("rm -f __tmp*");
1278 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1286 gSystem->Exec("rm -f __tmp__");
1287 ncount = line.Atoi();
1289 nullResult = kFALSE;
1291 if (ncount == gMaxEntries) {
1292 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1293 if (fNrunsPerMaster > 1) {
1294 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1295 file.Data(),gMaxEntries);
1298 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1299 if (!cbase) cbase = cadd;
1306 if (cbase && fNrunsPerMaster<2) {
1307 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1308 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1311 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1312 delete cbase; cbase = 0;
1314 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1316 gSystem->Exec("rm -f __tmp*");
1317 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1321 if (TestBit(AliAnalysisGrid::kTest)) break;
1322 // Check if there is one run per master job.
1323 if (fNrunsPerMaster<2) {
1324 if (FileExists(file)) {
1325 if (fOverwriteMode) gGrid->Rm(file);
1327 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1331 // Copy xml file to alien space
1332 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1333 if (!FileExists(file)) {
1334 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1340 if (((nruns-1)%fNrunsPerMaster) == 0) {
1341 schunk = os->GetString();
1342 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1344 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1345 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1349 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1352 schunk += Form("_%s.xml", os->GetString().Data());
1353 if (FileExists(schunk)) {
1354 if (fOverwriteMode) gGrid->Rm(file);
1356 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1360 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1361 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1362 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1363 if (!FileExists(schunk)) {
1364 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1372 Error("CreateDataset", "No valid dataset corresponding to the query!");
1376 // Process a full run range.
1377 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1378 format = Form("%%s/%s ", fRunPrefix.Data());
1381 path = Form(format.Data(), fGridDataDir.Data(), irun);
1382 if (!DirectoryExists(path)) continue;
1384 format = Form("%s.xml", fRunPrefix.Data());
1385 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1386 else file = Form(format.Data(), irun);
1387 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1388 if (fOverwriteMode) gGrid->Rm(file);
1390 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1394 // If local collection file does not exist, create it via 'find' command.
1398 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1400 command += Form("%s -o %d ",options.Data(), nstart);
1403 command += conditions;
1404 TGridResult *res = gGrid->Command(command);
1405 if (res) delete res;
1406 // Write standard output to file
1407 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1408 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1409 Bool_t nullFile = kFALSE;
1411 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1413 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1415 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1416 gSystem->Exec("rm -f __tmp*");
1424 gSystem->Exec("rm -f __tmp__");
1425 ncount = line.Atoi();
1427 nullResult = kFALSE;
1429 if (ncount == gMaxEntries) {
1430 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1431 if (fNrunsPerMaster > 1) {
1432 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1433 file.Data(),gMaxEntries);
1436 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1437 if (!cbase) cbase = cadd;
1444 if (cbase && fNrunsPerMaster<2) {
1445 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1446 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1449 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1450 delete cbase; cbase = 0;
1452 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1454 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1458 if (TestBit(AliAnalysisGrid::kTest)) break;
1459 // Check if there is one run per master job.
1460 if (fNrunsPerMaster<2) {
1461 if (FileExists(file)) {
1462 if (fOverwriteMode) gGrid->Rm(file);
1464 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1468 // Copy xml file to alien space
1469 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1470 if (!FileExists(file)) {
1471 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1476 // Check if the collection for the chunk exist locally.
1477 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1478 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1479 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1482 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1483 if (((nruns-1)%fNrunsPerMaster) == 0) {
1484 schunk = Form(fRunPrefix.Data(), irun);
1485 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1487 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1491 format = Form("%%s_%s.xml", fRunPrefix.Data());
1492 schunk2 = Form(format.Data(), schunk.Data(), irun);
1493 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1497 if (FileExists(schunk)) {
1498 if (fOverwriteMode) gGrid->Rm(schunk);
1500 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1504 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1505 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1506 if (FileExists(schunk)) {
1507 if (fOverwriteMode) gGrid->Rm(schunk);
1509 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1513 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1514 if (!FileExists(schunk)) {
1515 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1521 Error("CreateDataset", "No valid dataset corresponding to the query!");
1528 //______________________________________________________________________________
1529 Bool_t AliAnalysisAlien::CreateJDL()
1531 // Generate a JDL file according to current settings. The name of the file is
1532 // specified by fJDLName.
1533 Bool_t error = kFALSE;
1535 Bool_t copy = kTRUE;
1536 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1537 Bool_t generate = kTRUE;
1538 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1540 Error("CreateJDL", "Alien connection required");
1543 // Check validity of alien workspace
1545 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1546 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1547 workdir += fGridWorkingDir;
1551 Error("CreateJDL()", "Define some input files for your analysis.");
1554 // Compose list of input files
1555 // Check if output files were defined
1556 if (!fOutputFiles.Length()) {
1557 Error("CreateJDL", "You must define at least one output file");
1560 // Check if an output directory was defined and valid
1561 if (!fGridOutputDir.Length()) {
1562 Error("CreateJDL", "You must define AliEn output directory");
1565 if (!fProductionMode) {
1566 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1567 if (!DirectoryExists(fGridOutputDir)) {
1568 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1569 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1571 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1575 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1580 // Exit if any error up to now
1581 if (error) return kFALSE;
1583 if (!fUser.IsNull()) {
1584 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1585 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1587 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1588 TString mergeExec = fExecutable;
1589 mergeExec.ReplaceAll(".sh", "_merge.sh");
1590 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1591 mergeExec.ReplaceAll(".sh", ".C");
1592 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1593 if (!fArguments.IsNull())
1594 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1595 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1597 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1598 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1601 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1602 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1603 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1604 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1606 if (fMaxInitFailed > 0) {
1607 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1608 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1610 if (fSplitMaxInputFileNumber > 0) {
1611 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1612 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1614 if (!IsOneStageMerging()) {
1615 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1616 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1618 if (fSplitMode.Length()) {
1619 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1620 fGridJDL->SetDescription("Split", "We split per SE or file");
1622 fMergingJDL->SetValue("Split", "\"se\"");
1623 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1624 if (!fAliROOTVersion.IsNull()) {
1625 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1626 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1628 if (!fROOTVersion.IsNull()) {
1629 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1630 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1632 if (!fAPIVersion.IsNull()) {
1633 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1634 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1636 if (!fExternalPackages.IsNull()) {
1637 arr = fExternalPackages.Tokenize(" ");
1639 while ((os=(TObjString*)next())) {
1640 TString pkgname = os->GetString();
1641 Int_t index = pkgname.Index("::");
1642 TString pkgversion = pkgname(index+2, pkgname.Length());
1643 pkgname.Remove(index);
1644 fGridJDL->AddToPackages(pkgname, pkgversion);
1645 fMergingJDL->AddToPackages(pkgname, pkgversion);
1649 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1650 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1651 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1652 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1653 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1654 TString analysisFile = fExecutable;
1655 analysisFile.ReplaceAll(".sh", ".root");
1656 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1657 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1658 if (fAdditionalLibs.Length()) {
1659 arr = fAdditionalLibs.Tokenize(" ");
1661 while ((os=(TObjString*)next())) {
1662 if (os->GetString().Contains(".so")) continue;
1663 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1664 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1669 TIter next(fPackages);
1671 while ((obj=next())) {
1672 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1673 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1676 if (fOutputArchive.Length()) {
1677 TString outputArchive = fOutputArchive;
1678 if (!fRegisterExcludes.IsNull()) {
1679 arr = fRegisterExcludes.Tokenize(" ");
1681 while ((os=(TObjString*)next1())) {
1682 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1683 outputArchive.ReplaceAll(os->GetString(),"");
1687 arr = outputArchive.Tokenize(" ");
1689 Bool_t first = kTRUE;
1690 const char *comment = "Files to be archived";
1691 const char *comment1 = comment;
1692 while ((os=(TObjString*)next())) {
1693 if (!first) comment = NULL;
1694 if (!os->GetString().Contains("@") && fCloseSE.Length())
1695 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1697 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1701 // Output archive for the merging jdl
1702 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1703 outputArchive = "log_archive.zip:std*@disk=1 ";
1704 // Add normal output files, extra files + terminate files
1705 TString files = GetListOfFiles("outextter");
1706 // Do not register files in fRegisterExcludes
1707 if (!fRegisterExcludes.IsNull()) {
1708 arr = fRegisterExcludes.Tokenize(" ");
1710 while ((os=(TObjString*)next1())) {
1711 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1712 files.ReplaceAll(os->GetString(),"");
1716 files.ReplaceAll(".root", "*.root");
1717 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1719 TString files = fOutputArchive;
1720 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1721 outputArchive = files;
1723 arr = outputArchive.Tokenize(" ");
1727 while ((os=(TObjString*)next2())) {
1728 if (!first) comment = NULL;
1729 TString currentfile = os->GetString();
1730 if (!currentfile.Contains("@") && fCloseSE.Length())
1731 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1733 fMergingJDL->AddToOutputArchive(currentfile, comment);
1738 arr = fOutputFiles.Tokenize(",");
1740 Bool_t first = kTRUE;
1741 const char *comment = "Files to be saved";
1742 while ((os=(TObjString*)next())) {
1743 // Ignore ouputs in jdl that are also in outputarchive
1744 TString sout = os->GetString();
1745 sout.ReplaceAll("*", "");
1746 sout.ReplaceAll(".root", "");
1747 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1748 if (fOutputArchive.Contains(sout)) continue;
1749 // Ignore fRegisterExcludes
1750 if (fRegisterExcludes.Contains(sout)) continue;
1751 if (!first) comment = NULL;
1752 if (!os->GetString().Contains("@") && fCloseSE.Length())
1753 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1755 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1757 if (fMergeExcludes.Contains(sout)) continue;
1758 if (!os->GetString().Contains("@") && fCloseSE.Length())
1759 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1761 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1764 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1765 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1766 TString validationScript = fValidationScript;
1767 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1768 validationScript.ReplaceAll(".sh", "_merge.sh");
1769 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1770 if (fMasterResubmitThreshold) {
1771 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1772 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1774 // Write a jdl with 2 input parameters: collection name and output dir name.
1777 // Copy jdl to grid workspace
1779 // Check if an output directory was defined and valid
1780 if (!fGridOutputDir.Length()) {
1781 Error("CreateJDL", "You must define AliEn output directory");
1784 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1785 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1786 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1787 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1789 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1795 if (TestBit(AliAnalysisGrid::kSubmit)) {
1796 TString mergeJDLName = fExecutable;
1797 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1798 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1799 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1800 if (fProductionMode) {
1801 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1802 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1804 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1805 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1806 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1807 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1808 Fatal("","Terminating");
1809 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1811 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1812 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1813 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1814 Fatal("","Terminating");
1817 if (fAdditionalLibs.Length()) {
1818 arr = fAdditionalLibs.Tokenize(" ");
1821 while ((os=(TObjString*)next())) {
1822 if (os->GetString().Contains(".so")) continue;
1823 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1824 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1825 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1826 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1827 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1828 Fatal("","Terminating");
1833 TIter next(fPackages);
1835 while ((obj=next())) {
1836 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1837 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1838 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1839 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1840 Form("%s/%s", workdir.Data(), obj->GetName())))
1841 Fatal("","Terminating");
1848 //______________________________________________________________________________
1849 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1851 // Writes one or more JDL's corresponding to findex. If findex is negative,
1852 // all run numbers are considered in one go (jdl). For non-negative indices
1853 // they correspond to the indices in the array fInputFiles.
1854 if (!fInputFiles) return kFALSE;
1857 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1858 workdir += fGridWorkingDir;
1859 TString stageName = "$2";
1860 if (fProductionMode) stageName = "$4";
1861 if (!fMergeDirName.IsNull()) {
1862 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1863 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1865 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1866 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1868 if (fProductionMode) {
1869 TIter next(fInputFiles);
1870 while ((os=next())) {
1871 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1873 if (!fOutputToRunNo)
1874 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1876 fGridJDL->SetOutputDirectory(fGridOutputDir);
1878 if (!fRunNumbers.Length() && !fRunRange[0]) {
1879 // One jdl with no parameters in case input data is specified by name.
1880 TIter next(fInputFiles);
1882 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1883 if (!fOutputSingle.IsNull())
1884 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1886 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1887 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1890 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1891 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1892 if (!fOutputSingle.IsNull()) {
1893 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1894 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1896 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1901 // Generate the JDL as a string
1902 TString sjdl = fGridJDL->Generate();
1903 TString sjdl1 = fMergingJDL->Generate();
1905 if (!fMergeDirName.IsNull()) {
1906 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1907 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1909 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1910 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1912 TString sjdl2 = fMergingJDL->Generate();
1913 Int_t index, index1;
1914 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1915 sjdl.ReplaceAll("(member", "\n (member");
1916 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1917 sjdl.ReplaceAll("{", "{\n ");
1918 sjdl.ReplaceAll("};", "\n};");
1919 sjdl.ReplaceAll("{\n \n", "{\n");
1920 sjdl.ReplaceAll("\n\n", "\n");
1921 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1922 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1923 sjdl1.ReplaceAll("(member", "\n (member");
1924 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1925 sjdl1.ReplaceAll("{", "{\n ");
1926 sjdl1.ReplaceAll("};", "\n};");
1927 sjdl1.ReplaceAll("{\n \n", "{\n");
1928 sjdl1.ReplaceAll("\n\n", "\n");
1929 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1930 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1931 sjdl2.ReplaceAll("(member", "\n (member");
1932 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1933 sjdl2.ReplaceAll("{", "{\n ");
1934 sjdl2.ReplaceAll("};", "\n};");
1935 sjdl2.ReplaceAll("{\n \n", "{\n");
1936 sjdl2.ReplaceAll("\n\n", "\n");
1937 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1938 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1939 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1940 index = sjdl.Index("JDLVariables");
1941 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1942 sjdl += "Workdirectorysize = {\"5000MB\"};";
1943 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1944 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1945 index = fJobTag.Index(":");
1946 if (index < 0) index = fJobTag.Length();
1947 TString jobTag = fJobTag;
1948 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1949 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1950 if (fProductionMode) {
1951 sjdl1.Prepend("# Generated merging jdl (production mode) \
1952 \n# $1 = full alien path to output directory to be merged \
1953 \n# $2 = train number \
1954 \n# $3 = production (like LHC10b) \
1955 \n# $4 = merging stage \
1956 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1957 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1958 sjdl2.Prepend("# Generated merging jdl \
1959 \n# $1 = full alien path to output directory to be merged \
1960 \n# $2 = train number \
1961 \n# $3 = production (like LHC10b) \
1962 \n# $4 = merging stage \
1963 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1965 sjdl1.Prepend("# Generated merging jdl \
1966 \n# $1 = full alien path to output directory to be merged \
1967 \n# $2 = merging stage \
1968 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1969 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1970 sjdl2.Prepend("# Generated merging jdl \
1971 \n# $1 = full alien path to output directory to be merged \
1972 \n# $2 = merging stage \
1973 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1975 index = sjdl1.Index("JDLVariables");
1976 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1977 index = sjdl2.Index("JDLVariables");
1978 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1979 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1980 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1981 index = sjdl2.Index("Split =");
1983 index1 = sjdl2.Index("\n", index);
1984 sjdl2.Remove(index, index1-index+1);
1986 index = sjdl2.Index("SplitMaxInputFileNumber");
1988 index1 = sjdl2.Index("\n", index);
1989 sjdl2.Remove(index, index1-index+1);
1991 index = sjdl2.Index("InputDataCollection");
1993 index1 = sjdl2.Index(";", index);
1994 sjdl2.Remove(index, index1-index+1);
1996 index = sjdl2.Index("InputDataListFormat");
1998 index1 = sjdl2.Index("\n", index);
1999 sjdl2.Remove(index, index1-index+1);
2001 index = sjdl2.Index("InputDataList");
2003 index1 = sjdl2.Index("\n", index);
2004 sjdl2.Remove(index, index1-index+1);
2006 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
2007 // Write jdl to file
2009 out.open(fJDLName.Data(), ios::out);
2011 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2014 out << sjdl << endl;
2016 TString mergeJDLName = fExecutable;
2017 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2020 out1.open(mergeJDLName.Data(), ios::out);
2022 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2025 out1 << sjdl1 << endl;
2028 TString finalJDL = mergeJDLName;
2029 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2030 out2.open(finalJDL.Data(), ios::out);
2032 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2035 out2 << sjdl2 << endl;
2039 // Copy jdl to grid workspace
2041 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2043 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2044 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2045 TString finalJDL = mergeJDLName;
2046 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2047 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2048 if (fProductionMode) {
2049 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2050 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2051 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2053 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2054 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2055 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2056 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2057 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2058 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2059 Fatal("","Terminating");
2061 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2062 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2063 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2064 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2065 Fatal("","Terminating");
2066 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2067 Fatal("","Terminating");
2073 //______________________________________________________________________________
2074 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2076 // Returns true if file exists.
2077 if (!gGrid) return kFALSE;
2079 slfn.ReplaceAll("alien://","");
2080 TGridResult *res = gGrid->Ls(slfn);
2081 if (!res) return kFALSE;
2082 TMap *map = dynamic_cast<TMap*>(res->At(0));
2087 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2088 if (!objs || !objs->GetString().Length()) {
2096 //______________________________________________________________________________
2097 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2099 // Returns true if directory exists. Can be also a path.
2100 if (!gGrid) return kFALSE;
2101 // Check if dirname is a path
2102 TString dirstripped = dirname;
2103 dirstripped = dirstripped.Strip();
2104 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2105 TString dir = gSystem->BaseName(dirstripped);
2107 TString path = gSystem->DirName(dirstripped);
2108 TGridResult *res = gGrid->Ls(path, "-F");
2109 if (!res) return kFALSE;
2113 while ((map=dynamic_cast<TMap*>(next()))) {
2114 obj = map->GetValue("name");
2116 if (dir == obj->GetName()) {
2125 //______________________________________________________________________________
2126 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2128 // Check input data type.
2129 isCollection = kFALSE;
2133 Error("CheckDataType", "No connection to grid");
2136 isCollection = IsCollection(lfn);
2137 TString msg = "\n##### file: ";
2140 msg += " type: raw_collection;";
2141 // special treatment for collections
2143 // check for tag files in the collection
2144 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2146 msg += " using_tags: No (unknown)";
2147 Info("CheckDataType", "%s", msg.Data());
2150 const char* typeStr = res->GetKey(0, "origLFN");
2151 if (!typeStr || !strlen(typeStr)) {
2152 msg += " using_tags: No (unknown)";
2153 Info("CheckDataType", "%s", msg.Data());
2156 TString file = typeStr;
2157 useTags = file.Contains(".tag");
2158 if (useTags) msg += " using_tags: Yes";
2159 else msg += " using_tags: No";
2160 Info("CheckDataType", "%s", msg.Data());
2165 isXml = slfn.Contains(".xml");
2167 // Open xml collection and check if there are tag files inside
2168 msg += " type: xml_collection;";
2169 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2171 msg += " using_tags: No (unknown)";
2172 Info("CheckDataType", "%s", msg.Data());
2175 TMap *map = coll->Next();
2177 msg += " using_tags: No (unknown)";
2178 Info("CheckDataType", "%s", msg.Data());
2181 map = (TMap*)map->GetValue("");
2183 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2184 useTags = file.Contains(".tag");
2186 if (useTags) msg += " using_tags: Yes";
2187 else msg += " using_tags: No";
2188 Info("CheckDataType", "%s", msg.Data());
2191 useTags = slfn.Contains(".tag");
2192 if (slfn.Contains(".root")) msg += " type: root file;";
2193 else msg += " type: unknown file;";
2194 if (useTags) msg += " using_tags: Yes";
2195 else msg += " using_tags: No";
2196 Info("CheckDataType", "%s", msg.Data());
2199 //______________________________________________________________________________
2200 void AliAnalysisAlien::EnablePackage(const char *package)
2202 // Enables a par file supposed to exist in the current directory.
2203 TString pkg(package);
2204 pkg.ReplaceAll(".par", "");
2206 if (gSystem->AccessPathName(pkg)) {
2207 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2210 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2211 Info("EnablePackage", "AliEn plugin will use .par packages");
2212 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2214 fPackages = new TObjArray();
2215 fPackages->SetOwner();
2217 fPackages->Add(new TObjString(pkg));
2220 //______________________________________________________________________________
2221 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2223 // Make a tree from files having the location specified in fFileForTestMode.
2224 // Inspired from JF's CreateESDChain.
2225 if (fFileForTestMode.IsNull()) {
2226 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2229 if (gSystem->AccessPathName(fFileForTestMode)) {
2230 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2235 in.open(fFileForTestMode);
2237 // Read the input list of files and add them to the chain
2239 TChain *chain = new TChain(treeName);
2240 TChain *chainFriend = 0;
2241 if (!fFriendChainName.IsNull()) chainFriend = new TChain(treeName);
2245 if (line.IsNull()) continue;
2246 if (count++ == fNtestFiles) break;
2247 TString esdFile(line);
2248 TFile *file = TFile::Open(esdFile);
2249 if (file && !file->IsZombie()) {
2250 chain->Add(esdFile);
2252 if (!fFriendChainName.IsNull()) {
2253 if (esdFile.Index("#") > -1)
2254 esdFile.Remove(esdFile.Index("#"));
2255 esdFile = gSystem->DirName(esdFile);
2256 esdFile += "/" + fFriendChainName;
2257 file = TFile::Open(esdFile);
2258 if (file && !file->IsZombie()) {
2260 chainFriend->Add(esdFile);
2262 Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2267 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2271 if (!chain->GetListOfFiles()->GetEntries()) {
2272 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2278 if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2282 //______________________________________________________________________________
2283 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2285 // Get job status for all jobs with jobid>jobidstart.
2286 static char mstatus[20];
2292 TGridJobStatusList *list = gGrid->Ps("");
2293 if (!list) return mstatus;
2294 Int_t nentries = list->GetSize();
2295 TGridJobStatus *status;
2297 for (Int_t ijob=0; ijob<nentries; ijob++) {
2298 status = (TGridJobStatus *)list->At(ijob);
2299 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2300 if (pid<jobidstart) continue;
2301 if (pid == lastid) {
2302 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2304 switch (status->GetStatus()) {
2305 case TGridJobStatus::kWAITING:
2307 case TGridJobStatus::kRUNNING:
2309 case TGridJobStatus::kABORTED:
2310 case TGridJobStatus::kFAIL:
2311 case TGridJobStatus::kUNKNOWN:
2313 case TGridJobStatus::kDONE:
2322 //______________________________________________________________________________
2323 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2325 // Returns true if file is a collection. Functionality duplicated from
2326 // TAlien::Type() because we don't want to directly depend on TAlien.
2328 Error("IsCollection", "No connection to grid");
2331 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2332 if (!res) return kFALSE;
2333 const char* typeStr = res->GetKey(0, "type");
2334 if (!typeStr || !strlen(typeStr)) return kFALSE;
2335 if (!strcmp(typeStr, "collection")) return kTRUE;
2340 //______________________________________________________________________________
2341 Bool_t AliAnalysisAlien::IsSingleOutput() const
2343 // Check if single-ouput option is on.
2344 return (!fOutputSingle.IsNull());
2347 //______________________________________________________________________________
2348 void AliAnalysisAlien::Print(Option_t *) const
2350 // Print current plugin settings.
2351 printf("### AliEn analysis plugin current settings ###\n");
2352 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2353 if (mgr && mgr->IsProofMode()) {
2354 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2355 if (TestBit(AliAnalysisGrid::kTest))
2356 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2357 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2358 if (!fProofDataSet.IsNull())
2359 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2361 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2363 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2364 if (!fRootVersionForProof.IsNull())
2365 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2367 printf("= ROOT version requested________________________ default\n");
2368 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2369 if (!fAliRootMode.IsNull())
2370 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2372 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2373 if (fNproofWorkersPerSlave)
2374 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2375 if (TestSpecialBit(kClearPackages))
2376 printf("= ClearPackages requested...\n");
2377 if (fIncludePath.Data())
2378 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2379 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2380 if (fPackages && fPackages->GetEntries()) {
2381 TIter next(fPackages);
2384 while ((obj=next())) list += obj->GetName();
2385 printf("= Par files to be used: ________________________ %s\n", list.Data());
2387 if (TestSpecialBit(kProofConnectGrid))
2388 printf("= Requested PROOF connection to grid\n");
2391 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2392 if (fOverwriteMode) {
2393 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2394 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2396 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2397 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2398 printf("= Production mode:______________________________ %d\n", fProductionMode);
2399 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2400 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2401 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2403 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2404 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2405 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2406 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2407 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2408 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2409 if (fRunNumbers.Length())
2410 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2412 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2413 if (!fRunRange[0] && !fRunNumbers.Length()) {
2414 TIter next(fInputFiles);
2417 while ((obj=next())) list += obj->GetName();
2418 printf("= Input files to be processed: _________________ %s\n", list.Data());
2420 if (TestBit(AliAnalysisGrid::kTest))
2421 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2422 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2423 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2424 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2425 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2426 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2427 printf("=====================================================================\n");
2428 printf("= Job price: ___________________________________ %d\n", fPrice);
2429 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2430 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2431 if (fMaxInitFailed>0)
2432 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2433 if (fMasterResubmitThreshold>0)
2434 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2435 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2436 if (fNrunsPerMaster>0)
2437 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2438 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2439 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2440 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2441 if (fArguments.Length())
2442 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2443 if (fExecutableArgs.Length())
2444 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2445 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2446 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2447 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2448 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2450 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2451 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2452 if (fIncludePath.Data())
2453 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2454 if (fCloseSE.Length())
2455 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2456 if (fFriendChainName.Length())
2457 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2458 if (fPackages && fPackages->GetEntries()) {
2459 TIter next(fPackages);
2462 while ((obj=next())) list += obj->GetName();
2463 printf("= Par files to be used: ________________________ %s\n", list.Data());
2467 //______________________________________________________________________________
2468 void AliAnalysisAlien::SetDefaults()
2470 // Set default values for everything. What cannot be filled will be left empty.
2471 if (fGridJDL) delete fGridJDL;
2472 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2473 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2476 fSplitMaxInputFileNumber = 100;
2478 fMasterResubmitThreshold = 0;
2484 fNrunsPerMaster = 1;
2485 fMaxMergeFiles = 100;
2487 fExecutable = "analysis.sh";
2488 fExecutableCommand = "root -b -q";
2490 fExecutableArgs = "";
2491 fAnalysisMacro = "myAnalysis.C";
2492 fAnalysisSource = "";
2493 fAdditionalLibs = "";
2497 fAliROOTVersion = "";
2498 fUser = ""; // Your alien user name
2499 fGridWorkingDir = "";
2500 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2501 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2502 fFriendChainName = "";
2503 fGridOutputDir = "output";
2504 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2505 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2506 fInputFormat = "xml-single";
2507 fJDLName = "analysis.jdl";
2508 fJobTag = "Automatically generated analysis JDL";
2509 fMergeExcludes = "";
2512 SetCheckCopy(kTRUE);
2513 SetDefaultOutputs(kTRUE);
2517 //______________________________________________________________________________
2518 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2520 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2521 // First check if the result is already in the output directory.
2522 if (FileExists(Form("%s/%s",aliendir,filename))) {
2523 printf("Final merged results found. Not merging again.\n");
2526 // Now check the last stage done.
2529 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2532 // Next stage of merging
2534 TString pattern = "*root_archive.zip";
2535 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2536 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2537 if (res) delete res;
2538 // Write standard output to file
2539 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2540 // Count the number of files inside
2542 ifile.open(Form("Stage_%d.xml",stage));
2543 if (!ifile.good()) {
2544 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2549 while (!ifile.eof()) {
2551 if (line.Contains("/event")) nfiles++;
2555 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2558 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2560 // Copy the file in the output directory
2561 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2562 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2563 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2564 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2565 // Check if this is the last stage to be done.
2566 Bool_t laststage = (nfiles<nperchunk);
2567 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2569 printf("### Submiting final merging stage %d\n", stage);
2570 TString finalJDL = jdl;
2571 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2572 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2573 Int_t jobId = SubmitSingleJob(query);
2574 if (!jobId) return kFALSE;
2576 printf("### Submiting merging stage %d\n", stage);
2577 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2578 Int_t jobId = SubmitSingleJob(query);
2579 if (!jobId) return kFALSE;
2584 //______________________________________________________________________________
2585 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2587 // Loat the analysis manager from a file.
2588 TFile *file = TFile::Open(fname);
2590 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2593 TIter nextkey(file->GetListOfKeys());
2594 AliAnalysisManager *mgr = 0;
2596 while ((key=(TKey*)nextkey())) {
2597 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2598 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2601 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2605 //______________________________________________________________________________
2606 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2608 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2609 if (!gGrid) return 0;
2610 printf("=> %s ------> ",query);
2611 TGridResult *res = gGrid->Command(query);
2613 TString jobId = res->GetKey(0,"jobId");
2615 if (jobId.IsNull()) {
2616 printf("submission failed. Reason:\n");
2619 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2622 printf(" Job id: %s\n", jobId.Data());
2626 //______________________________________________________________________________
2627 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2629 // Merge given output files from basedir. Basedir can be an alien output directory
2630 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2631 // files in a group (ignored for xml input). Merging can be done in stages:
2632 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2633 // stage=1 : works with an xml of all root_archive.zip in the output directory
2634 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2635 TString outputFile = output;
2637 TString outputChunk;
2638 TString previousChunk = "";
2639 TObjArray *listoffiles = new TObjArray();
2640 // listoffiles->SetOwner();
2641 Int_t countChunk = 0;
2642 Int_t countZero = nmaxmerge;
2643 Bool_t merged = kTRUE;
2644 Int_t index = outputFile.Index("@");
2645 if (index > 0) outputFile.Remove(index);
2646 TString inputFile = outputFile;
2647 TString sbasedir = basedir;
2648 if (sbasedir.Contains(".xml")) {
2649 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2650 nmaxmerge = 9999999;
2651 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2653 ::Error("MergeOutput", "Input XML collection empty.");
2656 // Iterate grid collection
2657 while (coll->Next()) {
2658 TString fname = gSystem->DirName(coll->GetTURL());
2661 listoffiles->Add(new TNamed(fname.Data(),""));
2664 command = Form("find %s/ *%s", basedir, inputFile.Data());
2665 printf("command: %s\n", command.Data());
2666 TGridResult *res = gGrid->Command(command);
2668 ::Error("MergeOutput","No result for the find command\n");
2674 while ((map=(TMap*)nextmap())) {
2675 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2676 if (!objs || !objs->GetString().Length()) {
2677 // Nothing found - skip this output
2682 listoffiles->Add(new TNamed(objs->GetName(),""));
2686 if (!listoffiles->GetEntries()) {
2687 ::Error("MergeOutput","No result for the find command\n");
2692 TFileMerger *fm = 0;
2693 TIter next0(listoffiles);
2694 TObjArray *listoffilestmp = new TObjArray();
2695 listoffilestmp->SetOwner();
2698 // Keep only the files at upper level
2699 Int_t countChar = 0;
2700 while ((nextfile=next0())) {
2701 snextfile = nextfile->GetName();
2702 Int_t crtCount = snextfile.CountChar('/');
2703 if (nextfile == listoffiles->First()) countChar = crtCount;
2704 if (crtCount < countChar) countChar = crtCount;
2707 while ((nextfile=next0())) {
2708 snextfile = nextfile->GetName();
2709 Int_t crtCount = snextfile.CountChar('/');
2710 if (crtCount > countChar) {
2714 listoffilestmp->Add(nextfile);
2717 listoffiles = listoffilestmp; // Now contains 'good' files
2718 listoffiles->Print();
2719 TIter next(listoffiles);
2720 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2721 outputChunk = outputFile;
2722 outputChunk.ReplaceAll(".root", "_*.root");
2723 // Check for existent temporary merge files
2724 // Check overwrite mode and remove previous partial results if needed
2725 // Preserve old merging functionality for stage 0.
2727 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2729 // Skip as many input files as in a chunk
2730 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2733 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2737 snextfile = nextfile->GetName();
2739 outputChunk = outputFile;
2740 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2742 if (gSystem->AccessPathName(outputChunk)) continue;
2743 // Merged file with chunks up to <countChunk> found
2744 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2745 previousChunk = outputChunk;
2749 countZero = nmaxmerge;
2751 while ((nextfile=next())) {
2752 snextfile = nextfile->GetName();
2753 // Loop 'find' results and get next LFN
2754 if (countZero == nmaxmerge) {
2755 // First file in chunk - create file merger and add previous chunk if any.
2756 fm = new TFileMerger(kTRUE);
2757 fm->SetFastMethod(kTRUE);
2758 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2759 outputChunk = outputFile;
2760 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2762 // If last file found, put merged results in the output file
2763 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2764 // Add file to be merged and decrement chunk counter.
2765 fm->AddFile(snextfile);
2767 if (countZero==0 || nextfile == listoffiles->Last()) {
2768 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2769 // Nothing found - skip this output
2770 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2774 fm->OutputFile(outputChunk);
2775 // Merge the outputs, then go to next chunk
2777 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2781 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2782 gSystem->Unlink(previousChunk);
2784 if (nextfile == listoffiles->Last()) break;
2786 countZero = nmaxmerge;
2787 previousChunk = outputChunk;
2794 // Merging stage different than 0.
2795 // Move to the begining of the requested chunk.
2796 fm = new TFileMerger(kTRUE);
2797 fm->SetFastMethod(kTRUE);
2798 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2800 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2801 // Nothing found - skip this output
2802 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2806 fm->OutputFile(outputFile);
2807 // Merge the outputs
2809 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2813 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2819 //______________________________________________________________________________
2820 Bool_t AliAnalysisAlien::MergeOutputs()
2822 // Merge analysis outputs existing in the AliEn space.
2823 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2824 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2826 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2830 if (!TestBit(AliAnalysisGrid::kMerge)) {
2831 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2834 if (fProductionMode) {
2835 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2838 Info("MergeOutputs", "Submitting merging JDL");
2839 if (!SubmitMerging()) return kFALSE;
2840 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2841 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2844 // Get the output path
2845 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2846 if (!DirectoryExists(fGridOutputDir)) {
2847 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2850 if (!fOutputFiles.Length()) {
2851 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2854 // Check if fast read option was requested
2855 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2856 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2857 if (fFastReadOption) {
2858 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2859 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2860 gEnv->SetValue("XNet.ConnectTimeout",50);
2861 gEnv->SetValue("XNet.RequestTimeout",50);
2862 gEnv->SetValue("XNet.MaxRedirectCount",2);
2863 gEnv->SetValue("XNet.ReconnectTimeout",50);
2864 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2866 // Make sure we change the temporary directory
2867 gSystem->Setenv("TMPDIR", gSystem->pwd());
2868 // Set temporary compilation directory to current one
2869 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2870 TObjArray *list = fOutputFiles.Tokenize(",");
2874 Bool_t merged = kTRUE;
2875 while((str=(TObjString*)next())) {
2876 outputFile = str->GetString();
2877 Int_t index = outputFile.Index("@");
2878 if (index > 0) outputFile.Remove(index);
2879 TString outputChunk = outputFile;
2880 outputChunk.ReplaceAll(".root", "_*.root");
2881 // Skip already merged outputs
2882 if (!gSystem->AccessPathName(outputFile)) {
2883 if (fOverwriteMode) {
2884 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2885 gSystem->Unlink(outputFile);
2886 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2887 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2888 outputChunk.Data());
2889 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2892 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2896 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2897 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2898 outputChunk.Data());
2899 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2902 if (fMergeExcludes.Contains(outputFile.Data()) ||
2903 fRegisterExcludes.Contains(outputFile.Data())) continue;
2904 // Perform a 'find' command in the output directory, looking for registered outputs
2905 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2907 Error("MergeOutputs", "Terminate() will NOT be executed");
2910 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2911 if (fileOpened) fileOpened->Close();
2916 //______________________________________________________________________________
2917 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2919 // Use the output files connected to output containers from the analysis manager
2920 // rather than the files defined by SetOutputFiles
2921 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2922 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2923 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2926 //______________________________________________________________________________
2927 void AliAnalysisAlien::SetOutputFiles(const char *list)
2929 // Manually set the output files list.
2930 // Removes duplicates. Not allowed if default outputs are not disabled.
2931 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2932 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2935 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2937 TString slist = list;
2938 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2939 TObjArray *arr = slist.Tokenize(" ");
2943 while ((os=(TObjString*)next())) {
2944 sout = os->GetString();
2945 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2946 if (fOutputFiles.Contains(sout)) continue;
2947 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2948 fOutputFiles += sout;
2953 //______________________________________________________________________________
2954 void AliAnalysisAlien::SetOutputArchive(const char *list)
2956 // Manually set the output archive list. Free text - you are on your own...
2957 // Not allowed if default outputs are not disabled.
2958 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2959 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2962 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2963 fOutputArchive = list;
2966 //______________________________________________________________________________
2967 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2969 // Setting a prefered output SE is not allowed anymore.
2970 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2973 //______________________________________________________________________________
2974 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2976 // Set some PROOF special parameter.
2977 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2979 TObject *old = pair->Key();
2980 TObject *val = pair->Value();
2981 fProofParam.Remove(old);
2985 fProofParam.Add(new TObjString(pname), new TObjString(value));
2988 //______________________________________________________________________________
2989 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2991 // Returns a special PROOF parameter.
2992 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2993 if (!pair) return 0;
2994 return pair->Value()->GetName();
2997 //______________________________________________________________________________
2998 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
3000 // Start remote grid analysis.
3001 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3002 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
3003 if (!mgr || !mgr->IsInitialized()) {
3004 Error("StartAnalysis", "You need an initialized analysis manager for this");
3007 // Are we in PROOF mode ?
3008 if (mgr->IsProofMode()) {
3009 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
3010 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3011 if (fProofCluster.IsNull()) {
3012 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3015 if (fProofDataSet.IsNull() && !testMode) {
3016 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3019 // Set the needed environment
3020 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3021 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3022 if (fProofReset && !testMode) {
3023 if (fProofReset==1) {
3024 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3025 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3027 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3028 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3030 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3035 // Check if there is an old active session
3036 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3038 Error("StartAnalysis","You have to reset your old session first\n");
3042 // Do we need to change the ROOT version ? The success of this cannot be checked.
3043 if (!fRootVersionForProof.IsNull() && !testMode) {
3044 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
3045 fProofCluster.Data(), fRootVersionForProof.Data()));
3047 // Connect to PROOF and check the status
3050 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3051 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3053 if (!sworkers.IsNull())
3054 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3056 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3058 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3060 Error("StartAnalysis", "Could not start PROOF in test mode");
3065 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3068 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3069 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3070 // Set proof special parameters if any
3071 TIter nextpp(&fProofParam);
3072 TObject *proofparam;
3073 while ((proofparam=nextpp())) {
3074 TString svalue = GetProofParameter(proofparam->GetName());
3075 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3077 // Is dataset existing ?
3079 TString dataset = fProofDataSet;
3080 Int_t index = dataset.Index("#");
3081 if (index>=0) dataset.Remove(index);
3082 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3083 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3086 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3088 // Is ClearPackages() needed ?
3089 if (TestSpecialBit(kClearPackages)) {
3090 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3091 gROOT->ProcessLine("gProof->ClearPackages();");
3093 // Is a given aliroot mode requested ?
3096 if (!fAliRootMode.IsNull()) {
3097 TString alirootMode = fAliRootMode;
3098 if (alirootMode == "default") alirootMode = "";
3099 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3100 optionsList.SetOwner();
3101 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3102 // Check the additional libs to be loaded
3104 Bool_t parMode = kFALSE;
3105 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3106 // Parse the extra libs for .so
3107 if (fAdditionalLibs.Length()) {
3108 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3111 while((str=(TObjString*)next())) {
3112 if (str->GetString().Contains(".so")) {
3114 Warning("StartAnalysis", "Plugin does not support loading libs after par files in PROOF mode. Library %s and following will not load on workers", str->GetName());
3117 TString stmp = str->GetName();
3118 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3119 stmp.ReplaceAll(".so","");
3120 if (!extraLibs.IsNull()) extraLibs += ":";
3124 if (str->GetString().Contains(".par")) {
3125 // The first par file found in the list will not allow any further .so
3127 if (!parLibs.IsNull()) parLibs += ":";
3128 parLibs += str->GetName();
3132 if (list) delete list;
3134 if (!extraLibs.IsNull()) {
3135 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3136 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3138 // Check extra includes
3139 if (!fIncludePath.IsNull()) {
3140 TString includePath = fIncludePath;
3141 includePath.ReplaceAll(" ",":");
3142 includePath.ReplaceAll("$ALICE_ROOT/","");
3143 includePath.ReplaceAll("${ALICE_ROOT}/","");
3144 includePath.ReplaceAll("-I","");
3145 includePath.Remove(TString::kTrailing, ':');
3146 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3147 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3149 // Check if connection to grid is requested
3150 if (TestSpecialBit(kProofConnectGrid))
3151 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3152 // Enable AliRoot par
3154 // Enable proof lite package
3155 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3156 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3157 TNamed *obj = (TNamed*)optionsList.At(i);
3158 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3160 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3161 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3162 Info("StartAnalysis", "AliRootProofLite enabled");
3164 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3168 if ( ! fAliROOTVersion.IsNull() ) {
3169 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3170 fAliROOTVersion.Data(), &optionsList))) {
3171 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3176 // Enable first par files from fAdditionalLibs
3177 if (!parLibs.IsNull()) {
3178 TObjArray *list = parLibs.Tokenize(":");
3180 TObjString *package;
3181 while((package=(TObjString*)next())) {
3182 TString spkg = package->GetName();
3183 spkg.ReplaceAll(".par", "");
3184 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3185 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3186 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3187 if (gROOT->ProcessLine(enablePackage)) {
3188 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3192 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3196 if (list) delete list;
3199 if (fAdditionalLibs.Contains(".so") && !testMode) {
3200 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3201 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3205 // Enable par files if requested
3206 if (fPackages && fPackages->GetEntries()) {
3207 TIter next(fPackages);
3209 while ((package=next())) {
3210 // Skip packages already enabled
3211 if (parLibs.Contains(package->GetName())) continue;
3212 TString spkg = package->GetName();
3213 spkg.ReplaceAll(".par", "");
3214 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3215 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3216 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3217 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3221 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3226 // Do we need to load analysis source files ?
3227 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3228 if (fAnalysisSource.Length()) {
3229 TObjArray *list = fAnalysisSource.Tokenize(" ");
3232 while((str=(TObjString*)next())) {
3233 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3235 if (list) delete list;
3238 // Register dataset to proof lite.
3239 if (fFileForTestMode.IsNull()) {
3240 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3243 if (gSystem->AccessPathName(fFileForTestMode)) {
3244 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3247 TFileCollection *coll = new TFileCollection();
3248 coll->AddFromFile(fFileForTestMode);
3249 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3250 gROOT->ProcessLine("gProof->ShowDataSets()");
3255 // Check if output files have to be taken from the analysis manager
3256 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3257 // Add output files and AOD files
3258 fOutputFiles = GetListOfFiles("outaod");
3259 // Add extra files registered to the analysis manager
3260 TString extra = GetListOfFiles("ext");
3261 if (!extra.IsNull()) {
3262 extra.ReplaceAll(".root", "*.root");
3263 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3264 fOutputFiles += extra;
3266 // Compose the output archive.
3267 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3268 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3270 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3271 if (TestBit(AliAnalysisGrid::kOffline)) {
3272 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3273 \n there nor any job run. You can revise the JDL and analysis \
3274 \n macro then run the same in \"submit\" mode.");
3275 } else if (TestBit(AliAnalysisGrid::kTest)) {
3276 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3278 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3279 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3280 \n space and job submitted.");
3281 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3282 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3283 if (fMergeViaJDL) CheckInputData();
3286 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3291 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3294 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3295 if (!CheckInputData()) {
3296 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3299 if (!CreateDataset(fDataPattern)) {
3301 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3302 if (fRunNumbers.Length()) serror = "run numbers";
3303 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3304 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3305 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3308 WriteAnalysisFile();
3309 WriteAnalysisMacro();
3311 WriteValidationScript();
3313 WriteMergingMacro();
3314 WriteMergeExecutable();
3315 WriteValidationScript(kTRUE);
3317 if (!CreateJDL()) return kFALSE;
3318 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3320 // Locally testing the analysis
3321 Info("StartAnalysis", "\n_______________________________________________________________________ \
3322 \n Running analysis script in a daughter shell as on a worker node \
3323 \n_______________________________________________________________________");
3324 TObjArray *list = fOutputFiles.Tokenize(",");
3328 while((str=(TObjString*)next())) {
3329 outputFile = str->GetString();
3330 Int_t index = outputFile.Index("@");
3331 if (index > 0) outputFile.Remove(index);
3332 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3335 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3336 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3337 // gSystem->Exec("cat stdout");
3340 // Check if submitting is managed by LPM manager
3341 if (fProductionMode) {
3342 //TString prodfile = fJDLName;
3343 //prodfile.ReplaceAll(".jdl", ".prod");
3344 //WriteProductionFile(prodfile);
3345 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3348 // Submit AliEn job(s)
3349 gGrid->Cd(fGridOutputDir);
3352 if (!fRunNumbers.Length() && !fRunRange[0]) {
3353 // Submit a given xml or a set of runs
3354 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3355 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3357 const char *cjobId = res->GetKey(0,"jobId");
3361 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3364 Info("StartAnalysis", "\n_______________________________________________________________________ \
3365 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3366 \n_______________________________________________________________________",
3367 fJDLName.Data(), cjobId);
3372 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3376 // Submit for a range of enumeration of runs.
3377 if (!Submit()) return kFALSE;
3380 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3381 \n You may exit at any time and terminate the job later using the option <terminate> \
3382 \n ##################################################################################", jobID.Data());
3383 gSystem->Exec("aliensh");
3387 //______________________________________________________________________________
3388 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3390 // Get a comma-separated list of output files of the requested type.
3391 // Type can be (case unsensitive):
3392 // aod - list of aod files (std, extensions and filters)
3393 // out - list of output files connected to containers (but not aod's or extras)
3394 // ext - list of extra files registered to the manager
3395 // ter - list of files produced in terminate
3396 static TString files;
3398 TString stype = type;
3400 TString aodfiles, extra;
3401 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3403 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3404 return files.Data();
3406 if (mgr->GetOutputEventHandler()) {
3407 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3408 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3409 if (!extraaod.IsNull()) {
3411 aodfiles += extraaod;
3414 if (stype.Contains("aod")) {
3416 if (stype == "aod") return files.Data();
3418 // Add output files that are not in the list of AOD files
3419 TString outputfiles = "";
3420 TIter next(mgr->GetOutputs());
3421 AliAnalysisDataContainer *output;
3422 const char *filename = 0;
3423 while ((output=(AliAnalysisDataContainer*)next())) {
3424 filename = output->GetFileName();
3425 if (!(strcmp(filename, "default"))) continue;
3426 if (outputfiles.Contains(filename)) continue;
3427 if (aodfiles.Contains(filename)) continue;
3428 if (!outputfiles.IsNull()) outputfiles += ",";
3429 outputfiles += filename;
3431 if (stype.Contains("out")) {
3432 if (!files.IsNull()) files += ",";
3433 files += outputfiles;
3434 if (stype == "out") return files.Data();
3436 // Add extra files registered to the analysis manager
3438 extra = mgr->GetExtraFiles();
3439 if (!extra.IsNull()) {
3441 extra.ReplaceAll(" ", ",");
3442 TObjArray *fextra = extra.Tokenize(",");
3443 TIter nextx(fextra);
3445 while ((obj=nextx())) {
3446 if (aodfiles.Contains(obj->GetName())) continue;
3447 if (outputfiles.Contains(obj->GetName())) continue;
3448 if (sextra.Contains(obj->GetName())) continue;
3449 if (!sextra.IsNull()) sextra += ",";
3450 sextra += obj->GetName();
3453 if (stype.Contains("ext")) {
3454 if (!files.IsNull()) files += ",";
3458 if (stype == "ext") return files.Data();
3460 if (!fTerminateFiles.IsNull()) {
3461 fTerminateFiles.Strip();
3462 fTerminateFiles.ReplaceAll(" ",",");
3463 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3464 TIter nextx(fextra);
3466 while ((obj=nextx())) {
3467 if (aodfiles.Contains(obj->GetName())) continue;
3468 if (outputfiles.Contains(obj->GetName())) continue;
3469 if (termfiles.Contains(obj->GetName())) continue;
3470 if (sextra.Contains(obj->GetName())) continue;
3471 if (!termfiles.IsNull()) termfiles += ",";
3472 termfiles += obj->GetName();
3476 if (stype.Contains("ter")) {
3477 if (!files.IsNull() && !termfiles.IsNull()) {
3482 return files.Data();
3485 //______________________________________________________________________________
3486 Bool_t AliAnalysisAlien::Submit()
3488 // Submit all master jobs.
3489 Int_t nmasterjobs = fInputFiles->GetEntries();
3490 Long_t tshoot = gSystem->Now();
3491 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3492 while (fNsubmitted < nmasterjobs) {
3493 Long_t now = gSystem->Now();
3494 if ((now-tshoot)>30000) {
3496 if (!SubmitNext()) return kFALSE;
3502 //______________________________________________________________________________
3503 Bool_t AliAnalysisAlien::SubmitMerging()
3505 // Submit all merging jobs.
3506 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3507 gGrid->Cd(fGridOutputDir);
3508 TString mergeJDLName = fExecutable;
3509 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3511 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3514 Int_t ntosubmit = fInputFiles->GetEntries();
3515 for (Int_t i=0; i<ntosubmit; i++) {
3516 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3517 runOutDir.ReplaceAll(".xml", "");
3518 if (fOutputToRunNo) {
3519 // The output directory is the run number
3520 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3521 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3523 if (!fRunNumbers.Length() && !fRunRange[0]) {
3524 // The output directory is the grid outdir
3525 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3526 runOutDir = fGridOutputDir;
3528 // The output directory is the master number in 3 digits format
3529 printf("### Submitting merging job for master <%03d>\n", i);
3530 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3533 // Check now the number of merging stages.
3534 TObjArray *list = fOutputFiles.Tokenize(",");
3538 while((str=(TObjString*)next())) {
3539 outputFile = str->GetString();
3540 Int_t index = outputFile.Index("@");
3541 if (index > 0) outputFile.Remove(index);
3542 if (!fMergeExcludes.Contains(outputFile) &&
3543 !fRegisterExcludes.Contains(outputFile)) break;
3546 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3547 if (!done && (i==ntosubmit-1)) return kFALSE;
3548 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3550 if (!ntosubmit) return kTRUE;
3551 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3552 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3553 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3554 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3555 \n ################################################################################################################");
3556 gSystem->Exec("aliensh");
3560 //______________________________________________________________________________
3561 Bool_t AliAnalysisAlien::SubmitNext()
3563 // Submit next bunch of master jobs if the queue is free. The first master job is
3564 // submitted right away, while the next will not be unless the previous was split.
3565 // The plugin will not submit new master jobs if there are more that 500 jobs in
3567 static Bool_t iscalled = kFALSE;
3568 static Int_t firstmaster = 0;
3569 static Int_t lastmaster = 0;
3570 static Int_t npermaster = 0;
3571 if (iscalled) return kTRUE;
3573 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3574 Int_t ntosubmit = 0;
3577 Int_t nmasterjobs = fInputFiles->GetEntries();
3580 if (!IsUseSubmitPolicy()) {
3582 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3583 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3584 ntosubmit = nmasterjobs;
3587 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3588 printf("=== master %d: %s\n", lastmaster, status.Data());
3589 // If last master not split, just return
3590 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3591 // No more than 100 waiting jobs
3592 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3593 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3594 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3595 if (!ntosubmit) ntosubmit = 1;
3596 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3597 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3599 for (Int_t i=0; i<ntosubmit; i++) {
3600 // Submit for a range of enumeration of runs.
3601 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3603 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3604 runOutDir.ReplaceAll(".xml", "");
3606 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3608 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3609 printf("********* %s\n",query.Data());
3610 res = gGrid->Command(query);
3612 TString cjobId1 = res->GetKey(0,"jobId");
3613 if (!cjobId1.Length()) {
3617 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3620 Info("StartAnalysis", "\n_______________________________________________________________________ \
3621 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3622 \n_______________________________________________________________________",
3623 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3626 lastmaster = cjobId1.Atoi();
3627 if (!firstmaster) firstmaster = lastmaster;
3632 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3640 //______________________________________________________________________________
3641 void AliAnalysisAlien::WriteAnalysisFile()
3643 // Write current analysis manager into the file <analysisFile>
3644 TString analysisFile = fExecutable;
3645 analysisFile.ReplaceAll(".sh", ".root");
3646 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3647 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3648 if (!mgr || !mgr->IsInitialized()) {
3649 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3652 // Check analysis type
3654 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3655 handler = (TObject*)mgr->GetInputEventHandler();
3657 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3658 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3659 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3660 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3662 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3663 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3666 TDirectory *cdir = gDirectory;
3667 TFile *file = TFile::Open(analysisFile, "RECREATE");
3669 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3670 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3671 // Unless merging makes no sense
3672 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3675 // Enable termination for local jobs
3676 mgr->SetSkipTerminate(kFALSE);
3678 if (cdir) cdir->cd();
3679 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3681 Bool_t copy = kTRUE;
3682 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3685 TString workdir = gGrid->GetHomeDirectory();
3686 workdir += fGridWorkingDir;
3687 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3688 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3689 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3690 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3694 //______________________________________________________________________________
3695 void AliAnalysisAlien::WriteAnalysisMacro()
3697 // Write the analysis macro that will steer the analysis in grid mode.
3698 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3700 out.open(fAnalysisMacro.Data(), ios::out);
3702 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3705 Bool_t hasSTEERBase = kFALSE;
3706 Bool_t hasESD = kFALSE;
3707 Bool_t hasAOD = kFALSE;
3708 Bool_t hasANALYSIS = kFALSE;
3709 Bool_t hasOADB = kFALSE;
3710 Bool_t hasANALYSISalice = kFALSE;
3711 Bool_t hasCORRFW = kFALSE;
3712 TString func = fAnalysisMacro;
3713 TString type = "ESD";
3714 TString comment = "// Analysis using ";
3715 if (IsUseMCchain()) {
3719 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3720 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3725 if (type!="AOD" && fFriendChainName!="") {
3726 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3729 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3730 else comment += " data";
3731 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3732 func.ReplaceAll(".C", "");
3733 out << "void " << func.Data() << "()" << endl;
3735 out << comment.Data() << endl;
3736 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3737 out << " TStopwatch timer;" << endl;
3738 out << " timer.Start();" << endl << endl;
3739 // Change temp directory to current one
3740 out << "// Set temporary merging directory to current one" << endl;
3741 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3742 out << "// Set temporary compilation directory to current one" << endl;
3743 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3744 // Reset existing include path
3745 out << "// Reset existing include path and add current directory first in the search" << endl;
3746 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3747 if (!fExecutableCommand.Contains("aliroot")) {
3748 out << "// load base root libraries" << endl;
3749 out << " gSystem->Load(\"libTree\");" << endl;
3750 out << " gSystem->Load(\"libGeom\");" << endl;
3751 out << " gSystem->Load(\"libVMC\");" << endl;
3752 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3753 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3755 if (fAdditionalRootLibs.Length()) {
3756 // in principle libtree /lib geom libvmc etc. can go into this list, too
3757 out << "// Add aditional libraries" << endl;
3758 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3761 while((str=(TObjString*)next())) {
3762 if (str->GetString().Contains(".so"))
3763 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3765 if (list) delete list;
3767 out << "// Load analysis framework libraries" << endl;
3768 TString setupPar = "AliAnalysisAlien::SetupPar";
3770 if (!fExecutableCommand.Contains("aliroot")) {
3771 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3772 out << " gSystem->Load(\"libESD\");" << endl;
3773 out << " gSystem->Load(\"libAOD\");" << endl;
3775 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3776 out << " gSystem->Load(\"libOADB\");" << endl;
3777 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3778 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3780 TIter next(fPackages);
3783 while ((obj=next())) {
3784 pkgname = obj->GetName();
3785 if (pkgname == "STEERBase" ||
3786 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3787 if (pkgname == "ESD" ||
3788 pkgname == "ESD.par") hasESD = kTRUE;
3789 if (pkgname == "AOD" ||
3790 pkgname == "AOD.par") hasAOD = kTRUE;
3791 if (pkgname == "ANALYSIS" ||
3792 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3793 if (pkgname == "OADB" ||
3794 pkgname == "OADB.par") hasOADB = kTRUE;
3795 if (pkgname == "ANALYSISalice" ||
3796 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3797 if (pkgname == "CORRFW" ||
3798 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3800 if (hasANALYSISalice) setupPar = "SetupPar";
3801 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3802 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3803 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3804 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3805 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3806 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3807 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3808 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3809 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3810 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3811 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3812 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3813 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3814 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3815 out << "// Compile other par packages" << endl;
3817 while ((obj=next())) {
3818 pkgname = obj->GetName();
3819 if (pkgname == "STEERBase" ||
3820 pkgname == "STEERBase.par" ||
3822 pkgname == "ESD.par" ||
3824 pkgname == "AOD.par" ||
3825 pkgname == "ANALYSIS" ||
3826 pkgname == "ANALYSIS.par" ||
3827 pkgname == "OADB" ||
3828 pkgname == "OADB.par" ||
3829 pkgname == "ANALYSISalice" ||
3830 pkgname == "ANALYSISalice.par" ||
3831 pkgname == "CORRFW" ||
3832 pkgname == "CORRFW.par") continue;
3833 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3836 out << "// include path" << endl;
3837 // Get the include path from the interpreter and remove entries pointing to AliRoot
3838 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3839 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3840 out << " TIter nextpath(listpaths);" << endl;
3841 out << " TObjString *pname;" << endl;
3842 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3843 out << " TString current = pname->GetName();" << endl;
3844 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3845 out << " gSystem->AddIncludePath(current);" << endl;
3846 out << " }" << endl;
3847 out << " if (listpaths) delete listpaths;" << endl;
3848 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3849 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3850 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3851 if (fAdditionalLibs.Length()) {
3852 out << "// Add aditional AliRoot libraries" << endl;
3853 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3856 while((str=(TObjString*)next())) {
3857 if (str->GetString().Contains(".so"))
3858 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3859 if (str->GetString().Contains(".par"))
3860 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3862 if (list) delete list;
3865 out << "// analysis source to be compiled at runtime (if any)" << endl;
3866 if (fAnalysisSource.Length()) {
3867 TObjArray *list = fAnalysisSource.Tokenize(" ");
3870 while((str=(TObjString*)next())) {
3871 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3873 if (list) delete list;
3876 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3877 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3878 if (fFastReadOption) {
3879 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. This may skip some files that could be accessed !!! \
3880 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3881 out << "// fast xrootd reading enabled" << endl;
3882 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3883 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3884 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3885 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3886 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3887 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3889 if (!IsLocalTest()) {
3890 out << "// connect to AliEn and make the chain" << endl;
3891 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3893 out << "// read the analysis manager from file" << endl;
3894 TString analysisFile = fExecutable;
3895 analysisFile.ReplaceAll(".sh", ".root");
3896 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3897 << analysisFile << "\");" << endl;
3898 out << " if (!mgr) return;" << endl;
3899 if (IsLocalTest()) {
3900 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3901 out << " plugin->SetRunMode(\"test\");" << endl;
3902 if (fFileForTestMode.IsNull())
3903 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3905 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3906 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3907 if (!fFriendChainName.IsNull())
3908 out << " plugin->SetFriendChainName(\"" << fFriendChainName << "\");" << endl;
3909 out << " mgr->SetGridHandler(plugin);" << endl;
3910 if (AliAnalysisManager::GetAnalysisManager()) {
3911 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3912 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3914 out << " mgr->SetDebugLevel(10);" << endl;
3915 out << " mgr->SetNSysInfo(100);" << endl;
3918 out << " mgr->PrintStatus();" << endl;
3919 if (AliAnalysisManager::GetAnalysisManager()) {
3920 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3921 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3923 if (TestBit(AliAnalysisGrid::kTest))
3924 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3926 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3929 if (!IsLocalTest()) {
3930 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3931 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3933 out << " mgr->StartAnalysis(\"localfile\");" << endl;
3935 out << " timer.Stop();" << endl;
3936 out << " timer.Print();" << endl;
3937 out << "}" << endl << endl;
3938 if (!IsLocalTest()) {
3939 out <<"//________________________________________________________________________________" << endl;
3940 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3942 out << "// Create a chain using url's from xml file" << endl;
3943 out << " TString filename;" << endl;
3944 out << " Int_t run = 0;" << endl;
3945 if (IsUseMCchain()) {
3946 out << " TString treename = \"TE\";" << endl;
3948 out << " TString treename = type;" << endl;
3949 out << " treename.ToLower();" << endl;
3950 out << " treename += \"Tree\";" << endl;
3952 out << " printf(\"***************************************\\n\");" << endl;
3953 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3954 out << " printf(\"***************************************\\n\");" << endl;
3955 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3956 out << " if (!coll) {" << endl;
3957 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3958 out << " return NULL;" << endl;
3959 out << " }" << endl;
3960 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3961 out << " TChain *chain = new TChain(treename);" << endl;
3962 if(fFriendChainName!="") {
3963 out << " TChain *chainFriend = new TChain(treename);" << endl;
3965 out << " coll->Reset();" << endl;
3966 out << " while (coll->Next()) {" << endl;
3967 out << " filename = coll->GetTURL("");" << endl;
3968 out << " if (mgr) {" << endl;
3969 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3970 out << " if (nrun && nrun != run) {" << endl;
3971 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3972 out << " mgr->SetRunFromPath(nrun);" << endl;
3973 out << " run = nrun;" << endl;
3974 out << " }" << endl;
3975 out << " }" << endl;
3976 out << " chain->Add(filename);" << endl;
3977 if(fFriendChainName!="") {
3978 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3979 out << " if (fileFriend.Index(\"#\") > -1) fileFriend.Remove(fileFriend.Index(\"#\"));" << endl;
3980 out << " fileFriend = gSystem->DirName(fileFriend);" << endl;
3981 out << " fileFriend += \"/\";" << endl;
3982 out << " fileFriend += \"" << fFriendChainName << "\";";
3983 out << " TFile *file = TFile::Open(fileFriend);" << endl;
3984 out << " if (file) {" << endl;
3985 out << " file->Close();" << endl;
3986 out << " chainFriend->Add(fileFriend.Data());" << endl;
3987 out << " } else {" << endl;
3988 out << " ::Fatal(\"CreateChain\", \"Cannot open friend file: %s\", fileFriend.Data());" << endl;
3989 out << " return 0;" << endl;
3990 out << " }" << endl;
3992 out << " }" << endl;
3993 out << " if (!chain->GetNtrees()) {" << endl;
3994 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3995 out << " return NULL;" << endl;
3996 out << " }" << endl;
3997 if(fFriendChainName!="") {
3998 out << " chain->AddFriend(chainFriend);" << endl;
4000 out << " return chain;" << endl;
4001 out << "}" << endl << endl;
4003 if (hasANALYSISalice) {
4004 out <<"//________________________________________________________________________________" << endl;
4005 out << "Bool_t SetupPar(const char *package) {" << endl;
4006 out << "// Compile the package and set it up." << endl;
4007 out << " TString pkgdir = package;" << endl;
4008 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4009 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4010 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4011 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4012 out << " // Check for BUILD.sh and execute" << endl;
4013 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4014 out << " printf(\"*******************************\\n\");" << endl;
4015 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4016 out << " printf(\"*******************************\\n\");" << endl;
4017 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4018 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4019 out << " gSystem->ChangeDirectory(cdir);" << endl;
4020 out << " return kFALSE;" << endl;
4021 out << " }" << endl;
4022 out << " } else {" << endl;
4023 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4024 out << " gSystem->ChangeDirectory(cdir);" << endl;
4025 out << " return kFALSE;" << endl;
4026 out << " }" << endl;
4027 out << " // Check for SETUP.C and execute" << endl;
4028 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4029 out << " printf(\"*******************************\\n\");" << endl;
4030 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4031 out << " printf(\"*******************************\\n\");" << endl;
4032 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4033 out << " } else {" << endl;
4034 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4035 out << " gSystem->ChangeDirectory(cdir);" << endl;
4036 out << " return kFALSE;" << endl;
4037 out << " }" << endl;
4038 out << " // Restore original workdir" << endl;
4039 out << " gSystem->ChangeDirectory(cdir);" << endl;
4040 out << " return kTRUE;" << endl;
4043 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4045 Bool_t copy = kTRUE;
4046 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4049 TString workdir = gGrid->GetHomeDirectory();
4050 workdir += fGridWorkingDir;
4051 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4052 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4053 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4054 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4055 Form("alien://%s/%s", workdir.Data(),
4056 fAnalysisMacro.Data()))) Fatal("","Terminating");
4060 //______________________________________________________________________________
4061 void AliAnalysisAlien::WriteMergingMacro()
4063 // Write a macro to merge the outputs per master job.
4064 if (!fMergeViaJDL) return;
4065 if (!fOutputFiles.Length()) {
4066 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4069 TString mergingMacro = fExecutable;
4070 mergingMacro.ReplaceAll(".sh","_merge.C");
4071 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4072 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4074 out.open(mergingMacro.Data(), ios::out);
4076 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4079 Bool_t hasSTEERBase = kFALSE;
4080 Bool_t hasESD = kFALSE;
4081 Bool_t hasAOD = kFALSE;
4082 Bool_t hasANALYSIS = kFALSE;
4083 Bool_t hasOADB = kFALSE;
4084 Bool_t hasANALYSISalice = kFALSE;
4085 Bool_t hasCORRFW = kFALSE;
4086 TString func = mergingMacro;
4088 func.ReplaceAll(".C", "");
4089 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4091 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4092 out << " TStopwatch timer;" << endl;
4093 out << " timer.Start();" << endl << endl;
4094 // Reset existing include path
4095 out << "// Reset existing include path and add current directory first in the search" << endl;
4096 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4097 if (!fExecutableCommand.Contains("aliroot")) {
4098 out << "// load base root libraries" << endl;
4099 out << " gSystem->Load(\"libTree\");" << endl;
4100 out << " gSystem->Load(\"libGeom\");" << endl;
4101 out << " gSystem->Load(\"libVMC\");" << endl;
4102 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4103 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4105 if (fAdditionalRootLibs.Length()) {
4106 // in principle libtree /lib geom libvmc etc. can go into this list, too
4107 out << "// Add aditional libraries" << endl;
4108 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4111 while((str=(TObjString*)next())) {
4112 if (str->GetString().Contains(".so"))
4113 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4115 if (list) delete list;
4117 out << "// Load analysis framework libraries" << endl;
4119 if (!fExecutableCommand.Contains("aliroot")) {
4120 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4121 out << " gSystem->Load(\"libESD\");" << endl;
4122 out << " gSystem->Load(\"libAOD\");" << endl;
4124 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4125 out << " gSystem->Load(\"libOADB\");" << endl;
4126 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4127 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4129 TIter next(fPackages);
4132 TString setupPar = "AliAnalysisAlien::SetupPar";
4133 while ((obj=next())) {
4134 pkgname = obj->GetName();
4135 if (pkgname == "STEERBase" ||
4136 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4137 if (pkgname == "ESD" ||
4138 pkgname == "ESD.par") hasESD = kTRUE;
4139 if (pkgname == "AOD" ||
4140 pkgname == "AOD.par") hasAOD = kTRUE;
4141 if (pkgname == "ANALYSIS" ||
4142 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4143 if (pkgname == "OADB" ||
4144 pkgname == "OADB.par") hasOADB = kTRUE;
4145 if (pkgname == "ANALYSISalice" ||
4146 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4147 if (pkgname == "CORRFW" ||
4148 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4150 if (hasANALYSISalice) setupPar = "SetupPar";
4151 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4152 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4153 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4154 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4155 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4156 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4157 out << " gSystem->Load(\"libOADB\");" << endl;
4158 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4159 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4160 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4161 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4162 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4163 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4164 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4165 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4166 out << "// Compile other par packages" << endl;
4168 while ((obj=next())) {
4169 pkgname = obj->GetName();
4170 if (pkgname == "STEERBase" ||
4171 pkgname == "STEERBase.par" ||
4173 pkgname == "ESD.par" ||
4175 pkgname == "AOD.par" ||
4176 pkgname == "ANALYSIS" ||
4177 pkgname == "ANALYSIS.par" ||
4178 pkgname == "OADB" ||
4179 pkgname == "OADB.par" ||
4180 pkgname == "ANALYSISalice" ||
4181 pkgname == "ANALYSISalice.par" ||
4182 pkgname == "CORRFW" ||
4183 pkgname == "CORRFW.par") continue;
4184 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4187 out << "// include path" << endl;
4188 // Get the include path from the interpreter and remove entries pointing to AliRoot
4189 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4190 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4191 out << " TIter nextpath(listpaths);" << endl;
4192 out << " TObjString *pname;" << endl;
4193 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4194 out << " TString current = pname->GetName();" << endl;
4195 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4196 out << " gSystem->AddIncludePath(current);" << endl;
4197 out << " }" << endl;
4198 out << " if (listpaths) delete listpaths;" << endl;
4199 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4200 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4201 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4202 if (fAdditionalLibs.Length()) {
4203 out << "// Add aditional AliRoot libraries" << endl;
4204 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4207 while((str=(TObjString*)next())) {
4208 if (str->GetString().Contains(".so"))
4209 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4211 if (list) delete list;
4214 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4215 if (fAnalysisSource.Length()) {
4216 TObjArray *list = fAnalysisSource.Tokenize(" ");
4219 while((str=(TObjString*)next())) {
4220 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4222 if (list) delete list;
4226 if (fFastReadOption) {
4227 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 !!!");
4228 out << "// fast xrootd reading enabled" << endl;
4229 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4230 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4231 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4232 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4233 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4234 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4236 // Change temp directory to current one
4237 out << "// Set temporary merging directory to current one" << endl;
4238 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4239 out << "// Set temporary compilation directory to current one" << endl;
4240 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4241 out << "// Connect to AliEn" << endl;
4242 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4243 out << " TString outputDir = dir;" << endl;
4244 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4245 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4246 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4247 out << " TIter *iter = new TIter(list);" << endl;
4248 out << " TObjString *str;" << endl;
4249 out << " TString outputFile;" << endl;
4250 out << " Bool_t merged = kTRUE;" << endl;
4251 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4252 out << " outputFile = str->GetString();" << endl;
4253 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4254 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4255 out << " if (index > 0) outputFile.Remove(index);" << endl;
4256 out << " // Skip already merged outputs" << endl;
4257 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4258 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4259 out << " continue;" << endl;
4260 out << " }" << endl;
4261 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4262 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4263 out << " if (!merged) {" << endl;
4264 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4265 out << " return;" << endl;
4266 out << " }" << endl;
4267 out << " }" << endl;
4268 out << " // all outputs merged, validate" << endl;
4269 out << " ofstream out;" << endl;
4270 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4271 out << " out.close();" << endl;
4272 out << " // read the analysis manager from file" << endl;
4273 TString analysisFile = fExecutable;
4274 analysisFile.ReplaceAll(".sh", ".root");
4275 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4276 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4277 << analysisFile << "\");" << endl;
4278 out << " if (!mgr) return;" << endl;
4279 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4280 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4281 out << " mgr->PrintStatus();" << endl;
4282 if (AliAnalysisManager::GetAnalysisManager()) {
4283 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4284 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4286 if (TestBit(AliAnalysisGrid::kTest))
4287 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4289 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4292 out << " TTree *tree = NULL;" << endl;
4293 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4294 out << "}" << endl << endl;
4295 if (hasANALYSISalice) {
4296 out <<"//________________________________________________________________________________" << endl;
4297 out << "Bool_t SetupPar(const char *package) {" << endl;
4298 out << "// Compile the package and set it up." << endl;
4299 out << " TString pkgdir = package;" << endl;
4300 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4301 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4302 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4303 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4304 out << " // Check for BUILD.sh and execute" << endl;
4305 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4306 out << " printf(\"*******************************\\n\");" << endl;
4307 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4308 out << " printf(\"*******************************\\n\");" << endl;
4309 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4310 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4311 out << " gSystem->ChangeDirectory(cdir);" << endl;
4312 out << " return kFALSE;" << endl;
4313 out << " }" << endl;
4314 out << " } else {" << endl;
4315 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4316 out << " gSystem->ChangeDirectory(cdir);" << endl;
4317 out << " return kFALSE;" << endl;
4318 out << " }" << endl;
4319 out << " // Check for SETUP.C and execute" << endl;
4320 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4321 out << " printf(\"*******************************\\n\");" << endl;
4322 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4323 out << " printf(\"*******************************\\n\");" << endl;
4324 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4325 out << " } else {" << endl;
4326 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4327 out << " gSystem->ChangeDirectory(cdir);" << endl;
4328 out << " return kFALSE;" << endl;
4329 out << " }" << endl;
4330 out << " // Restore original workdir" << endl;
4331 out << " gSystem->ChangeDirectory(cdir);" << endl;
4332 out << " return kTRUE;" << endl;
4336 Bool_t copy = kTRUE;
4337 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4340 TString workdir = gGrid->GetHomeDirectory();
4341 workdir += fGridWorkingDir;
4342 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4343 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4344 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4345 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4346 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4350 //______________________________________________________________________________
4351 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4353 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4354 // Note that for loading the compiled library. The current directory should have precedence in
4356 TString pkgdir = package;
4357 pkgdir.ReplaceAll(".par","");
4358 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4359 TString cdir = gSystem->WorkingDirectory();
4360 gSystem->ChangeDirectory(pkgdir);
4361 // Check for BUILD.sh and execute
4362 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4363 printf("**************************************************\n");
4364 printf("*** Building PAR archive %s\n", package);
4365 printf("**************************************************\n");
4366 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4367 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4368 gSystem->ChangeDirectory(cdir);
4372 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4373 gSystem->ChangeDirectory(cdir);
4376 // Check for SETUP.C and execute
4377 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4378 printf("**************************************************\n");
4379 printf("*** Setup PAR archive %s\n", package);
4380 printf("**************************************************\n");
4381 gROOT->Macro("PROOF-INF/SETUP.C");
4382 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4384 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4385 gSystem->ChangeDirectory(cdir);
4388 // Restore original workdir
4389 gSystem->ChangeDirectory(cdir);
4393 //______________________________________________________________________________
4394 void AliAnalysisAlien::WriteExecutable()
4396 // Generate the alien executable script.
4397 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4399 out.open(fExecutable.Data(), ios::out);
4401 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4404 out << "#!/bin/bash" << endl;
4405 // Make sure we can properly compile par files
4406 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4407 out << "echo \"=========================================\"" << endl;
4408 out << "echo \"############## PATH : ##############\"" << endl;
4409 out << "echo $PATH" << endl;
4410 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4411 out << "echo $LD_LIBRARY_PATH" << endl;
4412 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4413 out << "echo $ROOTSYS" << endl;
4414 out << "echo \"############## which root : ##############\"" << endl;
4415 out << "which root" << endl;
4416 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4417 out << "echo $ALICE_ROOT" << endl;
4418 out << "echo \"############## which aliroot : ##############\"" << endl;
4419 out << "which aliroot" << endl;
4420 out << "echo \"############## system limits : ##############\"" << endl;
4421 out << "ulimit -a" << endl;
4422 out << "echo \"############## memory : ##############\"" << endl;
4423 out << "free -m" << endl;
4424 out << "echo \"=========================================\"" << endl << endl;
4425 out << fExecutableCommand << " ";
4426 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4427 out << "RET=$?" << endl;
4428 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4429 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4430 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4431 out << " let sig=\"$RET - 128\""<<endl;
4432 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4433 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4434 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4435 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4436 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4437 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4439 out << " exit $RET"<< endl;
4440 out << "fi" << endl << endl ;
4441 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4442 out << "echo \"############## memory after: ##############\"" << endl;
4443 out << "free -m" << endl;
4445 Bool_t copy = kTRUE;
4446 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4449 TString workdir = gGrid->GetHomeDirectory();
4450 TString bindir = Form("%s/bin", workdir.Data());
4451 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4452 workdir += fGridWorkingDir;
4453 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4454 if (FileExists(executable)) gGrid->Rm(executable);
4455 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4456 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4457 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4458 executable.Data())) Fatal("","Terminating");
4462 //______________________________________________________________________________
4463 void AliAnalysisAlien::WriteMergeExecutable()
4465 // Generate the alien executable script for the merging job.
4466 if (!fMergeViaJDL) return;
4467 TString mergeExec = fExecutable;
4468 mergeExec.ReplaceAll(".sh", "_merge.sh");
4469 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4471 out.open(mergeExec.Data(), ios::out);
4473 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4476 out << "#!/bin/bash" << endl;
4477 // Make sure we can properly compile par files
4478 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4479 out << "echo \"=========================================\"" << endl;
4480 out << "echo \"############## PATH : ##############\"" << endl;
4481 out << "echo $PATH" << endl;
4482 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4483 out << "echo $LD_LIBRARY_PATH" << endl;
4484 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4485 out << "echo $ROOTSYS" << endl;
4486 out << "echo \"############## which root : ##############\"" << endl;
4487 out << "which root" << endl;
4488 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4489 out << "echo $ALICE_ROOT" << endl;
4490 out << "echo \"############## which aliroot : ##############\"" << endl;
4491 out << "which aliroot" << endl;
4492 out << "echo \"############## system limits : ##############\"" << endl;
4493 out << "ulimit -a" << endl;
4494 out << "echo \"############## memory : ##############\"" << endl;
4495 out << "free -m" << endl;
4496 out << "echo \"=========================================\"" << endl << endl;
4497 TString mergeMacro = fExecutable;
4498 mergeMacro.ReplaceAll(".sh", "_merge.C");
4499 if (IsOneStageMerging())
4500 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4502 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4503 out << fExecutableCommand << " " << "$ARG" << endl;
4504 out << "RET=$?" << endl;
4505 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4506 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4507 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4508 out << " let sig=\"$RET - 128\""<<endl;
4509 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4510 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4511 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4512 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4513 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4514 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4516 out << " exit $RET"<< endl;
4517 out << "fi" << endl << endl ;
4518 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4519 out << "echo \"############## memory after: ##############\"" << endl;
4520 out << "free -m" << endl;
4522 Bool_t copy = kTRUE;
4523 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4526 TString workdir = gGrid->GetHomeDirectory();
4527 TString bindir = Form("%s/bin", workdir.Data());
4528 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4529 workdir += fGridWorkingDir;
4530 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4531 if (FileExists(executable)) gGrid->Rm(executable);
4532 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4533 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4534 if (!copyLocal2Alien("WriteMergeExecutable",
4535 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4539 //______________________________________________________________________________
4540 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4542 // Write the production file to be submitted by LPM manager. The format is:
4543 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4544 // Next lines: full_path_to_dataset XXX (XXX is a string)
4545 // To submit, one has to: submit jdl XXX for all lines
4547 out.open(filename, ios::out);
4549 Error("WriteProductionFile", "Bad file name: %s", filename);
4553 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4554 workdir = gGrid->GetHomeDirectory();
4555 workdir += fGridWorkingDir;
4556 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4557 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4558 out << locjdl << " " << njobspermaster << endl;
4559 Int_t nmasterjobs = fInputFiles->GetEntries();
4560 for (Int_t i=0; i<nmasterjobs; i++) {
4561 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4562 runOutDir.ReplaceAll(".xml", "");
4564 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4566 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4569 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4570 if (FileExists(filename)) gGrid->Rm(filename);
4571 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4572 if (!copyLocal2Alien("WriteProductionFile", filename,
4573 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4577 //______________________________________________________________________________
4578 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4580 // Generate the alien validation script.
4581 // Generate the validation script
4583 if (fValidationScript.IsNull()) {
4584 fValidationScript = fExecutable;
4585 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4587 TString validationScript = fValidationScript;
4588 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4590 Error("WriteValidationScript", "Alien connection required");
4593 if (!fTerminateFiles.IsNull()) {
4594 fTerminateFiles.Strip();
4595 fTerminateFiles.ReplaceAll(" ",",");
4597 TString outStream = "";
4598 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4599 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4601 out.open(validationScript, ios::out);
4602 out << "#!/bin/bash" << endl;
4603 out << "##################################################" << endl;
4604 out << "validateout=`dirname $0`" << endl;
4605 out << "validatetime=`date`" << endl;
4606 out << "validated=\"0\";" << endl;
4607 out << "error=0" << endl;
4608 out << "if [ -z $validateout ]" << endl;
4609 out << "then" << endl;
4610 out << " validateout=\".\"" << endl;
4611 out << "fi" << endl << endl;
4612 out << "cd $validateout;" << endl;
4613 out << "validateworkdir=`pwd`;" << endl << endl;
4614 out << "echo \"*******************************************************\"" << outStream << endl;
4615 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4617 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4618 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4619 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4620 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4621 out << "ls -la ./" << outStream << endl;
4622 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4623 out << "##################################################" << endl;
4626 out << "if [ ! -f stderr ] ; then" << endl;
4627 out << " error=1" << endl;
4628 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4629 out << " echo \"Error = $error\" " << outStream << endl;
4630 out << "fi" << endl;
4632 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4633 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4634 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4635 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4638 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4639 out << " error=1" << endl;
4640 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4641 out << " echo \"$parArch\" " << outStream << endl;
4642 out << " echo \"Error = $error\" " << outStream << endl;
4643 out << "fi" << endl;
4645 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4646 out << " error=1" << endl;
4647 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4648 out << " echo \"$segViol\" " << outStream << endl;
4649 out << " echo \"Error = $error\" " << outStream << endl;
4650 out << "fi" << endl;
4652 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4653 out << " error=1" << endl;
4654 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4655 out << " echo \"$segFault\" " << outStream << endl;
4656 out << " echo \"Error = $error\" " << outStream << endl;
4657 out << "fi" << endl;
4659 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4660 out << " error=1" << endl;
4661 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4662 out << " echo \"$glibcErr\" " << outStream << endl;
4663 out << " echo \"Error = $error\" " << outStream << endl;
4664 out << "fi" << endl;
4666 // Part dedicated to the specific analyses running into the train
4668 TString outputFiles = fOutputFiles;
4669 if (merge && !fTerminateFiles.IsNull()) {
4671 outputFiles += fTerminateFiles;
4673 TObjArray *arr = outputFiles.Tokenize(",");
4676 while (!merge && (os=(TObjString*)next1())) {
4677 // No need to validate outputs produced by merging since the merging macro does this
4678 outputFile = os->GetString();
4679 Int_t index = outputFile.Index("@");
4680 if (index > 0) outputFile.Remove(index);
4681 if (fTerminateFiles.Contains(outputFile)) continue;
4682 if (outputFile.Contains("*")) continue;
4683 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4684 out << " error=1" << endl;
4685 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4686 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4687 out << "fi" << endl;
4690 out << "if ! [ -f outputs_valid ] ; then" << endl;
4691 out << " error=1" << endl;
4692 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4693 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4694 out << "fi" << endl;
4696 out << "if [ $error = 0 ] ; then" << endl;
4697 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4698 if (!IsKeepLogs()) {
4699 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4701 out << " rm -f std*" << endl;
4703 out << "fi" << endl;
4705 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4706 out << "echo \"*******************************************************\"" << outStream << endl;
4707 out << "cd -" << endl;
4708 out << "exit $error" << endl;
4710 Bool_t copy = kTRUE;
4711 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4714 TString workdir = gGrid->GetHomeDirectory();
4715 workdir += fGridWorkingDir;
4716 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4717 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4718 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4719 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4720 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");