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"
55 ClassImp(AliAnalysisAlien)
61 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
63 TString sl(Form("file:%s", loc));
64 TString sr(Form("alien://%s", rem));
65 Bool_t ret = TFile::Cp(sl, sr);
67 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
73 //______________________________________________________________________________
74 AliAnalysisAlien::AliAnalysisAlien()
80 fSplitMaxInputFileNumber(0),
82 fMasterResubmitThreshold(0),
95 fNproofWorkersPerSlave(0),
105 fAdditionalRootLibs(),
134 fRootVersionForProof(),
146 //______________________________________________________________________________
147 AliAnalysisAlien::AliAnalysisAlien(const char *name)
148 :AliAnalysisGrid(name),
153 fSplitMaxInputFileNumber(0),
155 fMasterResubmitThreshold(0),
168 fNproofWorkersPerSlave(0),
172 fExecutableCommand(),
178 fAdditionalRootLibs(),
207 fRootVersionForProof(),
219 //______________________________________________________________________________
220 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
221 :AliAnalysisGrid(other),
224 fPrice(other.fPrice),
226 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
227 fMaxInitFailed(other.fMaxInitFailed),
228 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
229 fNtestFiles(other.fNtestFiles),
230 fNrunsPerMaster(other.fNrunsPerMaster),
231 fMaxMergeFiles(other.fMaxMergeFiles),
232 fMaxMergeStages(other.fMaxMergeStages),
233 fNsubmitted(other.fNsubmitted),
234 fProductionMode(other.fProductionMode),
235 fOutputToRunNo(other.fOutputToRunNo),
236 fMergeViaJDL(other.fMergeViaJDL),
237 fFastReadOption(other.fFastReadOption),
238 fOverwriteMode(other.fOverwriteMode),
239 fNreplicas(other.fNreplicas),
240 fNproofWorkers(other.fNproofWorkers),
241 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
242 fProofReset(other.fProofReset),
243 fRunNumbers(other.fRunNumbers),
244 fExecutable(other.fExecutable),
245 fExecutableCommand(other.fExecutableCommand),
246 fArguments(other.fArguments),
247 fExecutableArgs(other.fExecutableArgs),
248 fAnalysisMacro(other.fAnalysisMacro),
249 fAnalysisSource(other.fAnalysisSource),
250 fValidationScript(other.fValidationScript),
251 fAdditionalRootLibs(other.fAdditionalRootLibs),
252 fAdditionalLibs(other.fAdditionalLibs),
253 fSplitMode(other.fSplitMode),
254 fAPIVersion(other.fAPIVersion),
255 fROOTVersion(other.fROOTVersion),
256 fAliROOTVersion(other.fAliROOTVersion),
257 fExternalPackages(other.fExternalPackages),
259 fGridWorkingDir(other.fGridWorkingDir),
260 fGridDataDir(other.fGridDataDir),
261 fDataPattern(other.fDataPattern),
262 fGridOutputDir(other.fGridOutputDir),
263 fOutputArchive(other.fOutputArchive),
264 fOutputFiles(other.fOutputFiles),
265 fInputFormat(other.fInputFormat),
266 fDatasetName(other.fDatasetName),
267 fJDLName(other.fJDLName),
268 fTerminateFiles(other.fTerminateFiles),
269 fMergeExcludes(other.fMergeExcludes),
270 fRegisterExcludes(other.fRegisterExcludes),
271 fIncludePath(other.fIncludePath),
272 fCloseSE(other.fCloseSE),
273 fFriendChainName(other.fFriendChainName),
274 fJobTag(other.fJobTag),
275 fOutputSingle(other.fOutputSingle),
276 fRunPrefix(other.fRunPrefix),
277 fProofCluster(other.fProofCluster),
278 fProofDataSet(other.fProofDataSet),
279 fFileForTestMode(other.fFileForTestMode),
280 fRootVersionForProof(other.fRootVersionForProof),
281 fAliRootMode(other.fAliRootMode),
282 fMergeDirName(other.fMergeDirName),
289 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
290 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
291 fRunRange[0] = other.fRunRange[0];
292 fRunRange[1] = other.fRunRange[1];
293 if (other.fInputFiles) {
294 fInputFiles = new TObjArray();
295 TIter next(other.fInputFiles);
297 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
298 fInputFiles->SetOwner();
300 if (other.fPackages) {
301 fPackages = new TObjArray();
302 TIter next(other.fPackages);
304 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
305 fPackages->SetOwner();
307 if (other.fModules) {
308 fModules = new TObjArray();
309 fModules->SetOwner();
310 TIter next(other.fModules);
311 AliAnalysisTaskCfg *mod, *crt;
312 while ((crt=(AliAnalysisTaskCfg*)next())) {
313 mod = new AliAnalysisTaskCfg(*crt);
319 //______________________________________________________________________________
320 AliAnalysisAlien::~AliAnalysisAlien()
328 fProofParam.DeleteAll();
331 //______________________________________________________________________________
332 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
335 if (this != &other) {
336 AliAnalysisGrid::operator=(other);
337 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
338 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
339 fPrice = other.fPrice;
341 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
342 fMaxInitFailed = other.fMaxInitFailed;
343 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
344 fNtestFiles = other.fNtestFiles;
345 fNrunsPerMaster = other.fNrunsPerMaster;
346 fMaxMergeFiles = other.fMaxMergeFiles;
347 fMaxMergeStages = other.fMaxMergeStages;
348 fNsubmitted = other.fNsubmitted;
349 fProductionMode = other.fProductionMode;
350 fOutputToRunNo = other.fOutputToRunNo;
351 fMergeViaJDL = other.fMergeViaJDL;
352 fFastReadOption = other.fFastReadOption;
353 fOverwriteMode = other.fOverwriteMode;
354 fNreplicas = other.fNreplicas;
355 fNproofWorkers = other.fNproofWorkers;
356 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
357 fProofReset = other.fProofReset;
358 fRunNumbers = other.fRunNumbers;
359 fExecutable = other.fExecutable;
360 fExecutableCommand = other.fExecutableCommand;
361 fArguments = other.fArguments;
362 fExecutableArgs = other.fExecutableArgs;
363 fAnalysisMacro = other.fAnalysisMacro;
364 fAnalysisSource = other.fAnalysisSource;
365 fValidationScript = other.fValidationScript;
366 fAdditionalRootLibs = other.fAdditionalRootLibs;
367 fAdditionalLibs = other.fAdditionalLibs;
368 fSplitMode = other.fSplitMode;
369 fAPIVersion = other.fAPIVersion;
370 fROOTVersion = other.fROOTVersion;
371 fAliROOTVersion = other.fAliROOTVersion;
372 fExternalPackages = other.fExternalPackages;
374 fGridWorkingDir = other.fGridWorkingDir;
375 fGridDataDir = other.fGridDataDir;
376 fDataPattern = other.fDataPattern;
377 fGridOutputDir = other.fGridOutputDir;
378 fOutputArchive = other.fOutputArchive;
379 fOutputFiles = other.fOutputFiles;
380 fInputFormat = other.fInputFormat;
381 fDatasetName = other.fDatasetName;
382 fJDLName = other.fJDLName;
383 fTerminateFiles = other.fTerminateFiles;
384 fMergeExcludes = other.fMergeExcludes;
385 fRegisterExcludes = other.fRegisterExcludes;
386 fIncludePath = other.fIncludePath;
387 fCloseSE = other.fCloseSE;
388 fFriendChainName = other.fFriendChainName;
389 fJobTag = other.fJobTag;
390 fOutputSingle = other.fOutputSingle;
391 fRunPrefix = other.fRunPrefix;
392 fProofCluster = other.fProofCluster;
393 fProofDataSet = other.fProofDataSet;
394 fFileForTestMode = other.fFileForTestMode;
395 fRootVersionForProof = other.fRootVersionForProof;
396 fAliRootMode = other.fAliRootMode;
397 fMergeDirName = other.fMergeDirName;
398 if (other.fInputFiles) {
399 fInputFiles = new TObjArray();
400 TIter next(other.fInputFiles);
402 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
403 fInputFiles->SetOwner();
405 if (other.fPackages) {
406 fPackages = new TObjArray();
407 TIter next(other.fPackages);
409 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
410 fPackages->SetOwner();
412 if (other.fModules) {
413 fModules = new TObjArray();
414 fModules->SetOwner();
415 TIter next(other.fModules);
416 AliAnalysisTaskCfg *mod, *crt;
417 while ((crt=(AliAnalysisTaskCfg*)next())) {
418 mod = new AliAnalysisTaskCfg(*crt);
426 //______________________________________________________________________________
427 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
429 // Add a single additional library to be loaded. Extension must be present.
431 if (!lib.Contains(".")) {
432 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
435 if (fAdditionalLibs.Contains(name)) {
436 Warning("AddAdditionalLibrary", "Library %s already added.", name);
439 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
440 fAdditionalLibs += lib;
443 //______________________________________________________________________________
444 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
446 // Adding a module. Checks if already existing. Becomes owned by this.
448 if (GetModule(module->GetName())) {
449 Error("AddModule", "A module having the same name %s already added", module->GetName());
453 fModules = new TObjArray();
454 fModules->SetOwner();
456 fModules->Add(module);
459 //______________________________________________________________________________
460 void AliAnalysisAlien::AddModules(TObjArray *list)
462 // Adding a list of modules. Checks if already existing. Becomes owned by this.
464 AliAnalysisTaskCfg *module;
465 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
468 //______________________________________________________________________________
469 Bool_t AliAnalysisAlien::CheckDependencies()
471 // Check if all dependencies are satisfied. Reorder modules if needed.
472 Int_t nmodules = GetNmodules();
474 Warning("CheckDependencies", "No modules added yet to check their dependencies");
477 AliAnalysisTaskCfg *mod = 0;
478 AliAnalysisTaskCfg *dep = 0;
481 for (i=0; i<nmodules; i++) {
482 mod = (AliAnalysisTaskCfg*) fModules->At(i);
483 Int_t ndeps = mod->GetNdeps();
485 for (j=0; j<ndeps; j++) {
486 depname = mod->GetDependency(j);
487 dep = GetModule(depname);
489 Error("CheckDependencies","Dependency %s not added for module %s",
490 depname.Data(), mod->GetName());
493 if (dep->NeedsDependency(mod->GetName())) {
494 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
495 mod->GetName(), dep->GetName());
498 Int_t idep = fModules->IndexOf(dep);
499 // The dependency task must come first
501 // Remove at idep and move all objects below up one slot
502 // down to index i included.
503 fModules->RemoveAt(idep);
504 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
505 fModules->AddAt(dep, i++);
507 //Redo from istart if dependencies were inserted
508 if (i>istart) i=istart-1;
514 //______________________________________________________________________________
515 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
517 // Create the analysis manager and optionally execute the macro in filename.
518 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
520 mgr = new AliAnalysisManager(name);
521 mgr->SetGridHandler((AliAnalysisGrid*)this);
522 if (strlen(filename)) {
523 TString line = gSystem->ExpandPathName(filename);
525 gROOT->ProcessLine(line.Data());
530 //______________________________________________________________________________
531 Int_t AliAnalysisAlien::GetNmodules() const
533 // Get number of modules.
534 if (!fModules) return 0;
535 return fModules->GetEntries();
538 //______________________________________________________________________________
539 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
541 // Get a module by name.
542 if (!fModules) return 0;
543 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
546 //______________________________________________________________________________
547 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
549 // Load a given module.
550 if (mod->IsLoaded()) return kTRUE;
551 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
553 Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
556 Int_t ndeps = mod->GetNdeps();
558 for (Int_t j=0; j<ndeps; j++) {
559 depname = mod->GetDependency(j);
560 AliAnalysisTaskCfg *dep = GetModule(depname);
562 Error("LoadModule","Dependency %s not existing for module %s",
563 depname.Data(), mod->GetName());
566 if (!LoadModule(dep)) {
567 Error("LoadModule","Dependency %s for module %s could not be loaded",
568 depname.Data(), mod->GetName());
572 // Load libraries for the module
573 if (!mod->CheckLoadLibraries()) {
574 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
577 // Check if a custom file name was requested
578 if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
580 // Check if a custom terminate file name was requested
581 if (strlen(mod->GetTerminateFileName())) {
582 if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
583 fTerminateFiles += mod->GetTerminateFileName();
587 if (mod->ExecuteMacro()<0) {
588 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
589 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
592 // Configure dependencies
593 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
594 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
595 mod->GetConfigMacro()->GetTitle(), mod->GetName());
598 // Adjust extra libraries
599 Int_t nlibs = mod->GetNlibs();
601 for (Int_t i=0; i<nlibs; i++) {
602 lib = mod->GetLibrary(i);
603 lib = Form("lib%s.so", lib.Data());
604 if (fAdditionalLibs.Contains(lib)) continue;
605 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
606 fAdditionalLibs += lib;
611 //______________________________________________________________________________
612 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
614 // Generate the full train.
615 fAdditionalLibs = "";
616 if (!LoadModules()) return kFALSE;
617 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
618 if (!mgr->InitAnalysis()) return kFALSE;
621 Int_t productionMode = fProductionMode;
623 TString macro = fAnalysisMacro;
624 TString executable = fExecutable;
625 TString validation = fValidationScript;
626 TString execCommand = fExecutableCommand;
627 SetAnalysisMacro(Form("%s.C", name));
628 SetExecutable(Form("%s.sh", name));
629 // SetExecutableCommand("aliroot -b -q ");
630 SetValidationScript(Form("%s_validation.sh", name));
632 SetProductionMode(productionMode);
633 fAnalysisMacro = macro;
634 fExecutable = executable;
635 fExecutableCommand = execCommand;
636 fValidationScript = validation;
640 //______________________________________________________________________________
641 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
643 // Generate test macros for a single module or for the full train.
644 fAdditionalLibs = "";
645 if (strlen(modname)) {
646 if (!CheckDependencies()) return kFALSE;
647 AliAnalysisTaskCfg *mod = GetModule(modname);
649 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
652 if (!LoadModule(mod)) return kFALSE;
653 } else if (!LoadModules()) return kFALSE;
654 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
655 if (!mgr->InitAnalysis()) return kFALSE;
659 Int_t productionMode = fProductionMode;
661 TString macro = fAnalysisMacro;
662 TString executable = fExecutable;
663 TString validation = fValidationScript;
664 TString execCommand = fExecutableCommand;
665 SetAnalysisMacro(Form("%s.C", name));
666 SetExecutable(Form("%s.sh", name));
667 // SetExecutableCommand("aliroot -b -q ");
668 SetValidationScript(Form("%s_validation.sh", name));
670 WriteAnalysisMacro();
672 WriteValidationScript();
673 SetLocalTest(kFALSE);
674 SetProductionMode(productionMode);
675 fAnalysisMacro = macro;
676 fExecutable = executable;
677 fExecutableCommand = execCommand;
678 fValidationScript = validation;
682 //______________________________________________________________________________
683 Bool_t AliAnalysisAlien::LoadModules()
685 // Load all modules by executing the AddTask macros. Checks first the dependencies.
686 fAdditionalLibs = "";
687 Int_t nmodules = GetNmodules();
689 Warning("LoadModules", "No module to be loaded");
692 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
694 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
697 if (!CheckDependencies()) return kFALSE;
698 nmodules = GetNmodules();
699 AliAnalysisTaskCfg *mod;
700 for (Int_t imod=0; imod<nmodules; imod++) {
701 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
702 if (!LoadModule(mod)) return kFALSE;
707 //______________________________________________________________________________
708 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
710 // Set the run number format. Can be a prefix or a format like "%09d"
712 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
715 //______________________________________________________________________________
716 void AliAnalysisAlien::AddIncludePath(const char *path)
718 // Add include path in the remote analysis macro.
720 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
721 else fIncludePath += Form("-I%s ", path);
724 //______________________________________________________________________________
725 void AliAnalysisAlien::AddRunNumber(Int_t run)
727 // Add a run number to the list of runs to be processed.
728 if (fRunNumbers.Length()) fRunNumbers += " ";
729 fRunNumbers += Form(fRunPrefix.Data(), run);
732 //______________________________________________________________________________
733 void AliAnalysisAlien::AddRunList(const char* runList)
735 // Add several runs into the list of runs; they are expected to be separated by a blank character.
736 TString sList = runList;
737 TObjArray *list = sList.Tokenize(" ");
738 Int_t n = list->GetEntries();
739 for (Int_t i = 0; i < n; i++) {
740 TObjString *os = (TObjString*)list->At(i);
741 AddRunNumber(os->GetString().Atoi());
746 //______________________________________________________________________________
747 void AliAnalysisAlien::AddRunNumber(const char* run)
749 // Add a run number to the list of runs to be processed.
752 TObjArray *arr = runs.Tokenize(" ");
755 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
756 while ((os=(TObjString*)next())){
757 if (fRunNumbers.Length()) fRunNumbers += " ";
758 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
763 //______________________________________________________________________________
764 void AliAnalysisAlien::AddDataFile(const char *lfn)
766 // Adds a data file to the input to be analysed. The file should be a valid LFN
767 // or point to an existing file in the alien workdir.
768 if (!fInputFiles) fInputFiles = new TObjArray();
769 fInputFiles->Add(new TObjString(lfn));
772 //______________________________________________________________________________
773 void AliAnalysisAlien::AddExternalPackage(const char *package)
775 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
776 if (fExternalPackages) fExternalPackages += " ";
777 fExternalPackages += package;
780 //______________________________________________________________________________
781 Bool_t AliAnalysisAlien::Connect()
783 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
784 if (gGrid && gGrid->IsConnected()) return kTRUE;
785 if (fProductionMode) return kTRUE;
787 Info("Connect", "Trying to connect to AliEn ...");
788 TGrid::Connect("alien://");
790 if (!gGrid || !gGrid->IsConnected()) {
791 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
794 fUser = gGrid->GetUser();
795 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
799 //______________________________________________________________________________
800 void AliAnalysisAlien::CdWork()
802 // Check validity of alien workspace. Create directory if possible.
804 Error("CdWork", "Alien connection required");
807 TString homedir = gGrid->GetHomeDirectory();
808 TString workdir = homedir + fGridWorkingDir;
809 if (DirectoryExists(workdir)) {
813 // Work directory not existing - create it
815 if (gGrid->Mkdir(workdir, "-p")) {
816 gGrid->Cd(fGridWorkingDir);
817 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
819 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
820 workdir.Data(), homedir.Data());
821 fGridWorkingDir = "";
825 //______________________________________________________________________________
826 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
828 // Check if file copying is possible.
829 if (fProductionMode) return kTRUE;
830 TString salienpath(alienpath);
831 if (salienpath.Contains(" ")) {
832 Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
836 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
839 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
840 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
841 // Check if alien_CLOSE_SE is defined
842 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
843 if (!closeSE.IsNull()) {
844 Info("CheckFileCopy", "Your current close storage is pointing to: \
845 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
847 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
849 // Check if grid directory exists.
850 if (!DirectoryExists(alienpath)) {
851 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
854 TString stest = "plugin_test_copy";
855 TFile f(stest, "RECREATE");
856 // User may not have write permissions to current directory
858 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
859 gSystem->WorkingDirectory());
863 if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
864 if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
865 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
866 \n# 1. Make sure you have write permissions there. If this is the case: \
867 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
868 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
869 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
870 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
871 gSystem->Unlink(stest.Data());
874 gSystem->Unlink(stest.Data());
875 gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
876 Info("CheckFileCopy", "### ...SUCCESS ###");
880 //______________________________________________________________________________
881 Bool_t AliAnalysisAlien::CheckInputData()
883 // Check validity of input data. If necessary, create xml files.
884 if (fProductionMode) return kTRUE;
885 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
886 if (!fGridDataDir.Length()) {
887 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
891 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
894 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
895 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
896 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
899 // Process declared files
900 Bool_t isCollection = kFALSE;
901 Bool_t isXml = kFALSE;
902 Bool_t useTags = kFALSE;
903 Bool_t checked = kFALSE;
904 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
906 TString workdir = gGrid->GetHomeDirectory();
907 workdir += fGridWorkingDir;
910 TIter next(fInputFiles);
911 while ((objstr=(TObjString*)next())) {
914 file += objstr->GetString();
915 // Store full lfn path
916 if (FileExists(file)) objstr->SetString(file);
918 file = objstr->GetName();
919 if (!FileExists(objstr->GetName())) {
920 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
921 objstr->GetName(), workdir.Data());
925 Bool_t iscoll, isxml, usetags;
926 CheckDataType(file, iscoll, isxml, usetags);
929 isCollection = iscoll;
932 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
934 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
935 Error("CheckInputData", "Some conflict was found in the types of inputs");
941 // Process requested run numbers
942 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
943 // Check validity of alien data directory
944 if (!fGridDataDir.Length()) {
945 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
948 if (!DirectoryExists(fGridDataDir)) {
949 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
953 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
957 if (checked && !isXml) {
958 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
961 // Check validity of run number(s)
966 TString schunk, schunk2;
970 useTags = fDataPattern.Contains("tag");
971 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
973 if (useTags != fDataPattern.Contains("tag")) {
974 Error("CheckInputData", "Cannot mix input files using/not using tags");
977 if (fRunNumbers.Length()) {
978 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
979 arr = fRunNumbers.Tokenize(" ");
981 while ((os=(TObjString*)next())) {
982 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
983 if (!DirectoryExists(path)) {
984 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
987 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
988 TString msg = "\n##### file: ";
990 msg += " type: xml_collection;";
991 if (useTags) msg += " using_tags: Yes";
992 else msg += " using_tags: No";
993 Info("CheckDataType", "%s", msg.Data());
994 if (fNrunsPerMaster<2) {
995 AddDataFile(Form("%s.xml", os->GetString().Data()));
998 if (((nruns-1)%fNrunsPerMaster) == 0) {
999 schunk = os->GetString();
1001 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
1002 schunk += Form("_%s.xml", os->GetString().Data());
1003 AddDataFile(schunk);
1008 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1009 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1010 format = Form("%%s/%s ", fRunPrefix.Data());
1011 path = Form(format.Data(), fGridDataDir.Data(), irun);
1012 if (!DirectoryExists(path)) {
1015 format = Form("%%s/%s.xml", fRunPrefix.Data());
1016 path = Form(format.Data(), workdir.Data(),irun);
1017 TString msg = "\n##### file: ";
1019 msg += " type: xml_collection;";
1020 if (useTags) msg += " using_tags: Yes";
1021 else msg += " using_tags: No";
1022 Info("CheckDataType", "%s", msg.Data());
1023 if (fNrunsPerMaster<2) {
1024 format = Form("%s.xml", fRunPrefix.Data());
1025 AddDataFile(Form(format.Data(),irun));
1028 if (((nruns-1)%fNrunsPerMaster) == 0) {
1029 schunk = Form(fRunPrefix.Data(),irun);
1031 format = Form("_%s.xml", fRunPrefix.Data());
1032 schunk2 = Form(format.Data(), irun);
1033 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1035 AddDataFile(schunk);
1040 AddDataFile(schunk);
1046 //______________________________________________________________________________
1047 Bool_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1049 // Copy data from the given grid directory according a pattern and make a local
1051 // 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
1053 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1056 if (!DirectoryExists(griddir)) {
1057 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1060 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1061 printf("Running command: %s\n", command.Data());
1062 TGridResult *res = gGrid->Command(command);
1063 Int_t nfound = res->GetEntries();
1065 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1068 printf("... found %d files. Copying locally ...\n", nfound);
1071 TObjArray* additionalArchives = 0;
1072 if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1073 additionalArchives = TString(archivefile).Tokenize(";");
1074 archivefile = additionalArchives->At(0)->GetName();
1075 additionalArchives->RemoveAt(0);
1076 additionalArchives->Compress();
1079 // Copy files locally
1081 out.open(output, ios::out);
1083 TString turl, dirname, filename, temp;
1084 TString cdir = gSystem->WorkingDirectory();
1085 gSystem->MakeDirectory(outputdir);
1086 gSystem->ChangeDirectory(outputdir);
1087 for (Int_t i=0; i<nfound; i++) {
1088 map = (TMap*)res->At(i);
1089 turl = map->GetValue("turl")->GetName();
1090 filename = gSystem->BaseName(turl.Data());
1091 dirname = gSystem->DirName(turl.Data());
1092 dirname = gSystem->BaseName(dirname.Data());
1093 gSystem->MakeDirectory(dirname);
1095 TString source(turl);
1096 TString targetFileName(filename);
1098 if (strlen(archivefile) > 0) {
1099 // TODO here the archive in which the file resides should be determined
1100 // however whereis returns only a guid, and guid2lfn does not work
1101 // Therefore we use the one provided as argument for now
1102 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1103 targetFileName = archivefile;
1105 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1106 Bool_t success = kTRUE;
1107 if (additionalArchives)
1108 for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++)
1111 target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1112 gSystem->MakeDirectory(gSystem->DirName(target));
1113 success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1117 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1118 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1122 gSystem->ChangeDirectory(cdir);
1124 if (additionalArchives)
1125 delete additionalArchives;
1129 //______________________________________________________________________________
1130 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1132 // Create dataset for the grid data directory + run number.
1133 const Int_t gMaxEntries = 15000;
1134 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1136 Error("CreateDataset", "Cannot create dataset with no grid connection");
1141 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1142 TString workdir = gGrid->GetHomeDirectory();
1143 workdir += fGridWorkingDir;
1145 // Compose the 'find' command arguments
1148 TString options = "-x collection ";
1149 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1150 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1151 TString conditions = "";
1158 TString schunk, schunk2;
1159 TGridCollection *cbase=0, *cadd=0;
1160 if (!fRunNumbers.Length() && !fRunRange[0]) {
1161 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1162 // Make a single data collection from data directory.
1163 path = fGridDataDir;
1164 if (!DirectoryExists(path)) {
1165 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1169 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1170 else file = Form("%s.xml", gSystem->BaseName(path));
1174 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1176 command += Form("%s -o %d ",options.Data(), nstart);
1180 command += conditions;
1181 printf("command: %s\n", command.Data());
1182 TGridResult *res = gGrid->Command(command);
1183 if (res) delete res;
1184 // Write standard output to file
1185 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1186 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1187 Bool_t nullFile = kFALSE;
1189 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1191 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1193 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1194 gSystem->Exec("rm -f __tmp*");
1202 gSystem->Exec("rm -f __tmp__");
1203 ncount = line.Atoi();
1206 if (ncount == gMaxEntries) {
1207 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1208 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1209 if (!cbase) cbase = cadd;
1217 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1218 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1221 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1222 delete cbase; cbase = 0;
1224 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1226 gSystem->Exec("rm -f __tmp*");
1227 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1231 Bool_t fileExists = FileExists(file);
1232 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1233 // Copy xml file to alien space
1234 if (fileExists) gGrid->Rm(file);
1235 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1236 if (!FileExists(file)) {
1237 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1240 // Update list of files to be processed.
1242 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1246 Bool_t nullResult = kTRUE;
1247 if (fRunNumbers.Length()) {
1248 TObjArray *arr = fRunNumbers.Tokenize(" ");
1251 while ((os=(TObjString*)next())) {
1254 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
1255 if (!DirectoryExists(path)) continue;
1257 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1258 else file = Form("%s.xml", os->GetString().Data());
1259 // If local collection file does not exist, create it via 'find' command.
1263 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1265 command += Form("%s -o %d ",options.Data(), nstart);
1268 command += conditions;
1269 TGridResult *res = gGrid->Command(command);
1270 if (res) delete res;
1271 // Write standard output to file
1272 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1273 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1274 Bool_t nullFile = kFALSE;
1276 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1278 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1280 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1281 gSystem->Exec("rm -f __tmp*");
1282 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1290 gSystem->Exec("rm -f __tmp__");
1291 ncount = line.Atoi();
1293 nullResult = kFALSE;
1295 if (ncount == gMaxEntries) {
1296 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1297 if (fNrunsPerMaster > 1) {
1298 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1299 file.Data(),gMaxEntries);
1302 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1303 if (!cbase) cbase = cadd;
1310 if (cbase && fNrunsPerMaster<2) {
1311 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1312 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1315 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1316 delete cbase; cbase = 0;
1318 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1320 gSystem->Exec("rm -f __tmp*");
1321 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1325 if (TestBit(AliAnalysisGrid::kTest)) break;
1326 // Check if there is one run per master job.
1327 if (fNrunsPerMaster<2) {
1328 if (FileExists(file)) {
1329 if (fOverwriteMode) gGrid->Rm(file);
1331 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1335 // Copy xml file to alien space
1336 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1337 if (!FileExists(file)) {
1338 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1344 if (((nruns-1)%fNrunsPerMaster) == 0) {
1345 schunk = os->GetString();
1346 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1348 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1349 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1353 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1356 schunk += Form("_%s.xml", os->GetString().Data());
1357 if (FileExists(schunk)) {
1358 if (fOverwriteMode) gGrid->Rm(file);
1360 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1364 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1365 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1366 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1367 if (!FileExists(schunk)) {
1368 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1376 Error("CreateDataset", "No valid dataset corresponding to the query!");
1380 // Process a full run range.
1381 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1382 format = Form("%%s/%s ", fRunPrefix.Data());
1385 path = Form(format.Data(), fGridDataDir.Data(), irun);
1386 if (!DirectoryExists(path)) continue;
1388 format = Form("%s.xml", fRunPrefix.Data());
1389 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1390 else file = Form(format.Data(), irun);
1391 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1392 if (fOverwriteMode) gGrid->Rm(file);
1394 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1398 // If local collection file does not exist, create it via 'find' command.
1402 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1404 command += Form("%s -o %d ",options.Data(), nstart);
1407 command += conditions;
1408 TGridResult *res = gGrid->Command(command);
1409 if (res) delete res;
1410 // Write standard output to file
1411 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1412 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1413 Bool_t nullFile = kFALSE;
1415 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1417 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1419 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1420 gSystem->Exec("rm -f __tmp*");
1428 gSystem->Exec("rm -f __tmp__");
1429 ncount = line.Atoi();
1431 nullResult = kFALSE;
1433 if (ncount == gMaxEntries) {
1434 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1435 if (fNrunsPerMaster > 1) {
1436 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1437 file.Data(),gMaxEntries);
1440 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1441 if (!cbase) cbase = cadd;
1448 if (cbase && fNrunsPerMaster<2) {
1449 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1450 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1453 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1454 delete cbase; cbase = 0;
1456 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1458 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1462 if (TestBit(AliAnalysisGrid::kTest)) break;
1463 // Check if there is one run per master job.
1464 if (fNrunsPerMaster<2) {
1465 if (FileExists(file)) {
1466 if (fOverwriteMode) gGrid->Rm(file);
1468 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1472 // Copy xml file to alien space
1473 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1474 if (!FileExists(file)) {
1475 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1480 // Check if the collection for the chunk exist locally.
1481 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1482 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1483 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1486 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1487 if (((nruns-1)%fNrunsPerMaster) == 0) {
1488 schunk = Form(fRunPrefix.Data(), irun);
1489 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1491 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1495 format = Form("%%s_%s.xml", fRunPrefix.Data());
1496 schunk2 = Form(format.Data(), schunk.Data(), irun);
1497 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1501 if (FileExists(schunk)) {
1502 if (fOverwriteMode) gGrid->Rm(schunk);
1504 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1508 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1509 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1510 if (FileExists(schunk)) {
1511 if (fOverwriteMode) gGrid->Rm(schunk);
1513 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1517 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1518 if (!FileExists(schunk)) {
1519 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1525 Error("CreateDataset", "No valid dataset corresponding to the query!");
1532 //______________________________________________________________________________
1533 Bool_t AliAnalysisAlien::CreateJDL()
1535 // Generate a JDL file according to current settings. The name of the file is
1536 // specified by fJDLName.
1537 Bool_t error = kFALSE;
1539 Bool_t copy = kTRUE;
1540 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1541 Bool_t generate = kTRUE;
1542 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1544 Error("CreateJDL", "Alien connection required");
1547 // Check validity of alien workspace
1549 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1550 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1551 workdir += fGridWorkingDir;
1555 Error("CreateJDL()", "Define some input files for your analysis.");
1558 // Compose list of input files
1559 // Check if output files were defined
1560 if (!fOutputFiles.Length()) {
1561 Error("CreateJDL", "You must define at least one output file");
1564 // Check if an output directory was defined and valid
1565 if (!fGridOutputDir.Length()) {
1566 Error("CreateJDL", "You must define AliEn output directory");
1569 if (!fProductionMode) {
1570 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1571 if (!DirectoryExists(fGridOutputDir)) {
1572 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1573 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1575 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1579 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1584 // Exit if any error up to now
1585 if (error) return kFALSE;
1587 if (!fUser.IsNull()) {
1588 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1589 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1591 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1592 TString mergeExec = fExecutable;
1593 mergeExec.ReplaceAll(".sh", "_merge.sh");
1594 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1595 mergeExec.ReplaceAll(".sh", ".C");
1596 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1597 if (!fArguments.IsNull())
1598 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1599 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1601 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1602 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1605 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1606 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1607 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1608 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1610 if (fMaxInitFailed > 0) {
1611 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1612 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1614 if (fSplitMaxInputFileNumber > 0) {
1615 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1616 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1618 if (!IsOneStageMerging()) {
1619 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1620 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1622 if (fSplitMode.Length()) {
1623 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1624 fGridJDL->SetDescription("Split", "We split per SE or file");
1626 fMergingJDL->SetValue("Split", "\"se\"");
1627 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1628 if (!fAliROOTVersion.IsNull()) {
1629 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1630 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1632 if (!fROOTVersion.IsNull()) {
1633 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1634 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1636 if (!fAPIVersion.IsNull()) {
1637 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1638 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1640 if (!fExternalPackages.IsNull()) {
1641 arr = fExternalPackages.Tokenize(" ");
1643 while ((os=(TObjString*)next())) {
1644 TString pkgname = os->GetString();
1645 Int_t index = pkgname.Index("::");
1646 TString pkgversion = pkgname(index+2, pkgname.Length());
1647 pkgname.Remove(index);
1648 fGridJDL->AddToPackages(pkgname, pkgversion);
1649 fMergingJDL->AddToPackages(pkgname, pkgversion);
1653 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1654 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1655 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1656 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1657 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1658 TString analysisFile = fExecutable;
1659 analysisFile.ReplaceAll(".sh", ".root");
1660 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1661 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1662 if (fAdditionalLibs.Length()) {
1663 arr = fAdditionalLibs.Tokenize(" ");
1665 while ((os=(TObjString*)next())) {
1666 if (os->GetString().Contains(".so")) continue;
1667 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1668 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1673 TIter next(fPackages);
1675 while ((obj=next())) {
1676 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1677 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1680 if (fOutputArchive.Length()) {
1681 TString outputArchive = fOutputArchive;
1682 if (!fRegisterExcludes.IsNull()) {
1683 arr = fRegisterExcludes.Tokenize(" ");
1685 while ((os=(TObjString*)next1())) {
1686 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1687 outputArchive.ReplaceAll(os->GetString(),"");
1691 arr = outputArchive.Tokenize(" ");
1693 Bool_t first = kTRUE;
1694 const char *comment = "Files to be archived";
1695 const char *comment1 = comment;
1696 while ((os=(TObjString*)next())) {
1697 if (!first) comment = NULL;
1698 if (!os->GetString().Contains("@") && fCloseSE.Length())
1699 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1701 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1705 // Output archive for the merging jdl
1706 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1707 outputArchive = "log_archive.zip:std*@disk=1 ";
1708 // Add normal output files, extra files + terminate files
1709 TString files = GetListOfFiles("outextter");
1710 // Do not register files in fRegisterExcludes
1711 if (!fRegisterExcludes.IsNull()) {
1712 arr = fRegisterExcludes.Tokenize(" ");
1714 while ((os=(TObjString*)next1())) {
1715 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1716 files.ReplaceAll(os->GetString(),"");
1720 files.ReplaceAll(".root", "*.root");
1721 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1723 TString files = fOutputArchive;
1724 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1725 outputArchive = files;
1727 arr = outputArchive.Tokenize(" ");
1731 while ((os=(TObjString*)next2())) {
1732 if (!first) comment = NULL;
1733 TString currentfile = os->GetString();
1734 if (!currentfile.Contains("@") && fCloseSE.Length())
1735 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1737 fMergingJDL->AddToOutputArchive(currentfile, comment);
1742 arr = fOutputFiles.Tokenize(",");
1744 Bool_t first = kTRUE;
1745 const char *comment = "Files to be saved";
1746 while ((os=(TObjString*)next())) {
1747 // Ignore ouputs in jdl that are also in outputarchive
1748 TString sout = os->GetString();
1749 sout.ReplaceAll("*", "");
1750 sout.ReplaceAll(".root", "");
1751 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1752 if (fOutputArchive.Contains(sout)) continue;
1753 // Ignore fRegisterExcludes
1754 if (fRegisterExcludes.Contains(sout)) continue;
1755 if (!first) comment = NULL;
1756 if (!os->GetString().Contains("@") && fCloseSE.Length())
1757 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1759 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1761 if (fMergeExcludes.Contains(sout)) continue;
1762 if (!os->GetString().Contains("@") && fCloseSE.Length())
1763 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1765 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1768 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1769 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1770 TString validationScript = fValidationScript;
1771 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1772 validationScript.ReplaceAll(".sh", "_merge.sh");
1773 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1774 if (fMasterResubmitThreshold) {
1775 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1776 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1778 // Write a jdl with 2 input parameters: collection name and output dir name.
1781 // Copy jdl to grid workspace
1783 // Check if an output directory was defined and valid
1784 if (!fGridOutputDir.Length()) {
1785 Error("CreateJDL", "You must define AliEn output directory");
1788 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1789 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1790 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1791 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1793 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1799 if (TestBit(AliAnalysisGrid::kSubmit)) {
1800 TString mergeJDLName = fExecutable;
1801 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1802 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1803 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1804 if (fProductionMode) {
1805 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1806 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1808 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1809 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1810 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1811 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1812 Fatal("","Terminating");
1813 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1815 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1816 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1817 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1818 Fatal("","Terminating");
1821 if (fAdditionalLibs.Length()) {
1822 arr = fAdditionalLibs.Tokenize(" ");
1825 while ((os=(TObjString*)next())) {
1826 if (os->GetString().Contains(".so")) continue;
1827 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1828 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1829 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1830 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1831 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1832 Fatal("","Terminating");
1837 TIter next(fPackages);
1839 while ((obj=next())) {
1840 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1841 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1842 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1843 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1844 Form("%s/%s", workdir.Data(), obj->GetName())))
1845 Fatal("","Terminating");
1852 //______________________________________________________________________________
1853 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1855 // Writes one or more JDL's corresponding to findex. If findex is negative,
1856 // all run numbers are considered in one go (jdl). For non-negative indices
1857 // they correspond to the indices in the array fInputFiles.
1858 if (!fInputFiles) return kFALSE;
1861 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1862 workdir += fGridWorkingDir;
1863 TString stageName = "$2";
1864 if (fProductionMode) stageName = "$4";
1865 if (!fMergeDirName.IsNull()) {
1866 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1867 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1869 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1870 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1872 if (fProductionMode) {
1873 TIter next(fInputFiles);
1874 while ((os=next())) {
1875 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1877 if (!fOutputToRunNo)
1878 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1880 fGridJDL->SetOutputDirectory(fGridOutputDir);
1882 if (!fRunNumbers.Length() && !fRunRange[0]) {
1883 // One jdl with no parameters in case input data is specified by name.
1884 TIter next(fInputFiles);
1886 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1887 if (!fOutputSingle.IsNull())
1888 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1890 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1891 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1894 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1895 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1896 if (!fOutputSingle.IsNull()) {
1897 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1898 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1900 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1905 // Generate the JDL as a string
1906 TString sjdl = fGridJDL->Generate();
1907 TString sjdl1 = fMergingJDL->Generate();
1909 if (!fMergeDirName.IsNull()) {
1910 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1911 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1913 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1914 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1916 TString sjdl2 = fMergingJDL->Generate();
1917 Int_t index, index1;
1918 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1919 sjdl.ReplaceAll("(member", "\n (member");
1920 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1921 sjdl.ReplaceAll("{", "{\n ");
1922 sjdl.ReplaceAll("};", "\n};");
1923 sjdl.ReplaceAll("{\n \n", "{\n");
1924 sjdl.ReplaceAll("\n\n", "\n");
1925 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1926 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1927 sjdl1.ReplaceAll("(member", "\n (member");
1928 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1929 sjdl1.ReplaceAll("{", "{\n ");
1930 sjdl1.ReplaceAll("};", "\n};");
1931 sjdl1.ReplaceAll("{\n \n", "{\n");
1932 sjdl1.ReplaceAll("\n\n", "\n");
1933 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1934 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1935 sjdl2.ReplaceAll("(member", "\n (member");
1936 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1937 sjdl2.ReplaceAll("{", "{\n ");
1938 sjdl2.ReplaceAll("};", "\n};");
1939 sjdl2.ReplaceAll("{\n \n", "{\n");
1940 sjdl2.ReplaceAll("\n\n", "\n");
1941 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1942 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1943 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1944 index = sjdl.Index("JDLVariables");
1945 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1946 sjdl += "Workdirectorysize = {\"5000MB\"};";
1947 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1948 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1949 index = fJobTag.Index(":");
1950 if (index < 0) index = fJobTag.Length();
1951 TString jobTag = fJobTag;
1952 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1953 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1954 if (fProductionMode) {
1955 sjdl1.Prepend("# Generated merging jdl (production mode) \
1956 \n# $1 = full alien path to output directory to be merged \
1957 \n# $2 = train number \
1958 \n# $3 = production (like LHC10b) \
1959 \n# $4 = merging stage \
1960 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1961 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1962 sjdl2.Prepend("# Generated merging jdl \
1963 \n# $1 = full alien path to output directory to be merged \
1964 \n# $2 = train number \
1965 \n# $3 = production (like LHC10b) \
1966 \n# $4 = merging stage \
1967 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1969 sjdl1.Prepend("# Generated merging jdl \
1970 \n# $1 = full alien path to output directory to be merged \
1971 \n# $2 = merging stage \
1972 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1973 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1974 sjdl2.Prepend("# Generated merging jdl \
1975 \n# $1 = full alien path to output directory to be merged \
1976 \n# $2 = merging stage \
1977 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1979 index = sjdl1.Index("JDLVariables");
1980 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1981 index = sjdl2.Index("JDLVariables");
1982 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1983 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1984 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1985 index = sjdl2.Index("Split =");
1987 index1 = sjdl2.Index("\n", index);
1988 sjdl2.Remove(index, index1-index+1);
1990 index = sjdl2.Index("SplitMaxInputFileNumber");
1992 index1 = sjdl2.Index("\n", index);
1993 sjdl2.Remove(index, index1-index+1);
1995 index = sjdl2.Index("InputDataCollection");
1997 index1 = sjdl2.Index(";", index);
1998 sjdl2.Remove(index, index1-index+1);
2000 index = sjdl2.Index("InputDataListFormat");
2002 index1 = sjdl2.Index("\n", index);
2003 sjdl2.Remove(index, index1-index+1);
2005 index = sjdl2.Index("InputDataList");
2007 index1 = sjdl2.Index("\n", index);
2008 sjdl2.Remove(index, index1-index+1);
2010 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
2011 // Write jdl to file
2013 out.open(fJDLName.Data(), ios::out);
2015 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2018 out << sjdl << endl;
2020 TString mergeJDLName = fExecutable;
2021 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2024 out1.open(mergeJDLName.Data(), ios::out);
2026 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2029 out1 << sjdl1 << endl;
2032 TString finalJDL = mergeJDLName;
2033 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2034 out2.open(finalJDL.Data(), ios::out);
2036 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2039 out2 << sjdl2 << endl;
2043 // Copy jdl to grid workspace
2045 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2047 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2048 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2049 TString finalJDL = mergeJDLName;
2050 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2051 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2052 if (fProductionMode) {
2053 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2054 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2055 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2057 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2058 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2059 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2060 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2061 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2062 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2063 Fatal("","Terminating");
2065 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2066 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2067 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2068 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2069 Fatal("","Terminating");
2070 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2071 Fatal("","Terminating");
2077 //______________________________________________________________________________
2078 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2080 // Returns true if file exists.
2081 if (!gGrid) return kFALSE;
2083 slfn.ReplaceAll("alien://","");
2084 TGridResult *res = gGrid->Ls(slfn);
2085 if (!res) return kFALSE;
2086 TMap *map = dynamic_cast<TMap*>(res->At(0));
2091 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2092 if (!objs || !objs->GetString().Length()) {
2100 //______________________________________________________________________________
2101 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2103 // Returns true if directory exists. Can be also a path.
2104 if (!gGrid) return kFALSE;
2105 // Check if dirname is a path
2106 TString dirstripped = dirname;
2107 dirstripped = dirstripped.Strip();
2108 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2109 TString dir = gSystem->BaseName(dirstripped);
2111 TString path = gSystem->DirName(dirstripped);
2112 TGridResult *res = gGrid->Ls(path, "-F");
2113 if (!res) return kFALSE;
2117 while ((map=dynamic_cast<TMap*>(next()))) {
2118 obj = map->GetValue("name");
2120 if (dir == obj->GetName()) {
2129 //______________________________________________________________________________
2130 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2132 // Check input data type.
2133 isCollection = kFALSE;
2137 Error("CheckDataType", "No connection to grid");
2140 isCollection = IsCollection(lfn);
2141 TString msg = "\n##### file: ";
2144 msg += " type: raw_collection;";
2145 // special treatment for collections
2147 // check for tag files in the collection
2148 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2150 msg += " using_tags: No (unknown)";
2151 Info("CheckDataType", "%s", msg.Data());
2154 const char* typeStr = res->GetKey(0, "origLFN");
2155 if (!typeStr || !strlen(typeStr)) {
2156 msg += " using_tags: No (unknown)";
2157 Info("CheckDataType", "%s", msg.Data());
2160 TString file = typeStr;
2161 useTags = file.Contains(".tag");
2162 if (useTags) msg += " using_tags: Yes";
2163 else msg += " using_tags: No";
2164 Info("CheckDataType", "%s", msg.Data());
2169 isXml = slfn.Contains(".xml");
2171 // Open xml collection and check if there are tag files inside
2172 msg += " type: xml_collection;";
2173 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2175 msg += " using_tags: No (unknown)";
2176 Info("CheckDataType", "%s", msg.Data());
2179 TMap *map = coll->Next();
2181 msg += " using_tags: No (unknown)";
2182 Info("CheckDataType", "%s", msg.Data());
2185 map = (TMap*)map->GetValue("");
2187 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2188 useTags = file.Contains(".tag");
2190 if (useTags) msg += " using_tags: Yes";
2191 else msg += " using_tags: No";
2192 Info("CheckDataType", "%s", msg.Data());
2195 useTags = slfn.Contains(".tag");
2196 if (slfn.Contains(".root")) msg += " type: root file;";
2197 else msg += " type: unknown file;";
2198 if (useTags) msg += " using_tags: Yes";
2199 else msg += " using_tags: No";
2200 Info("CheckDataType", "%s", msg.Data());
2203 //______________________________________________________________________________
2204 void AliAnalysisAlien::EnablePackage(const char *package)
2206 // Enables a par file supposed to exist in the current directory.
2207 TString pkg(package);
2208 pkg.ReplaceAll(".par", "");
2210 if (gSystem->AccessPathName(pkg)) {
2211 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2214 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2215 Info("EnablePackage", "AliEn plugin will use .par packages");
2216 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2218 fPackages = new TObjArray();
2219 fPackages->SetOwner();
2221 fPackages->Add(new TObjString(pkg));
2224 //______________________________________________________________________________
2225 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2227 // Make a tree from files having the location specified in fFileForTestMode.
2228 // Inspired from JF's CreateESDChain.
2229 if (fFileForTestMode.IsNull()) {
2230 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2233 if (gSystem->AccessPathName(fFileForTestMode)) {
2234 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2239 in.open(fFileForTestMode);
2241 // Read the input list of files and add them to the chain
2243 TString streeName(treeName);
2244 if (IsUseMCchain()) streeName = "TE";
2245 TChain *chain = new TChain(streeName);
2246 TChain *chainFriend = 0;
2247 if (!fFriendChainName.IsNull()) chainFriend = new TChain(streeName);
2251 if (line.IsNull()) continue;
2252 if (count++ == fNtestFiles) break;
2253 TString esdFile(line);
2254 TFile *file = TFile::Open(esdFile);
2255 if (file && !file->IsZombie()) {
2256 chain->Add(esdFile);
2258 if (!fFriendChainName.IsNull()) {
2259 if (esdFile.Index("#") > -1)
2260 esdFile.Remove(esdFile.Index("#"));
2261 esdFile = gSystem->DirName(esdFile);
2262 esdFile += "/" + fFriendChainName;
2263 file = TFile::Open(esdFile);
2264 if (file && !file->IsZombie()) {
2266 chainFriend->Add(esdFile);
2268 Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2273 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2277 if (!chain->GetListOfFiles()->GetEntries()) {
2278 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2284 if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2288 //______________________________________________________________________________
2289 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2291 // Get job status for all jobs with jobid>jobidstart.
2292 static char mstatus[20];
2298 TGridJobStatusList *list = gGrid->Ps("");
2299 if (!list) return mstatus;
2300 Int_t nentries = list->GetSize();
2301 TGridJobStatus *status;
2303 for (Int_t ijob=0; ijob<nentries; ijob++) {
2304 status = (TGridJobStatus *)list->At(ijob);
2305 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2306 if (pid<jobidstart) continue;
2307 if (pid == lastid) {
2308 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2310 switch (status->GetStatus()) {
2311 case TGridJobStatus::kWAITING:
2313 case TGridJobStatus::kRUNNING:
2315 case TGridJobStatus::kABORTED:
2316 case TGridJobStatus::kFAIL:
2317 case TGridJobStatus::kUNKNOWN:
2319 case TGridJobStatus::kDONE:
2328 //______________________________________________________________________________
2329 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2331 // Returns true if file is a collection. Functionality duplicated from
2332 // TAlien::Type() because we don't want to directly depend on TAlien.
2334 Error("IsCollection", "No connection to grid");
2337 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2338 if (!res) return kFALSE;
2339 const char* typeStr = res->GetKey(0, "type");
2340 if (!typeStr || !strlen(typeStr)) return kFALSE;
2341 if (!strcmp(typeStr, "collection")) return kTRUE;
2346 //______________________________________________________________________________
2347 Bool_t AliAnalysisAlien::IsSingleOutput() const
2349 // Check if single-ouput option is on.
2350 return (!fOutputSingle.IsNull());
2353 //______________________________________________________________________________
2354 void AliAnalysisAlien::Print(Option_t *) const
2356 // Print current plugin settings.
2357 printf("### AliEn analysis plugin current settings ###\n");
2358 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2359 if (mgr && mgr->IsProofMode()) {
2360 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2361 if (TestBit(AliAnalysisGrid::kTest))
2362 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2363 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2364 if (!fProofDataSet.IsNull())
2365 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2367 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2369 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2370 if (!fRootVersionForProof.IsNull())
2371 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2373 printf("= ROOT version requested________________________ default\n");
2374 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2375 if (!fAliRootMode.IsNull())
2376 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2378 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2379 if (fNproofWorkersPerSlave)
2380 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2381 if (TestSpecialBit(kClearPackages))
2382 printf("= ClearPackages requested...\n");
2383 if (fIncludePath.Data())
2384 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2385 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2386 if (fPackages && fPackages->GetEntries()) {
2387 TIter next(fPackages);
2390 while ((obj=next())) list += obj->GetName();
2391 printf("= Par files to be used: ________________________ %s\n", list.Data());
2393 if (TestSpecialBit(kProofConnectGrid))
2394 printf("= Requested PROOF connection to grid\n");
2397 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2398 if (fOverwriteMode) {
2399 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2400 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2402 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2403 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2404 printf("= Production mode:______________________________ %d\n", fProductionMode);
2405 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2406 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2407 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2409 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2410 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2411 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2412 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2413 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2414 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2415 if (fRunNumbers.Length())
2416 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2418 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2419 if (!fRunRange[0] && !fRunNumbers.Length()) {
2420 TIter next(fInputFiles);
2423 while ((obj=next())) list += obj->GetName();
2424 printf("= Input files to be processed: _________________ %s\n", list.Data());
2426 if (TestBit(AliAnalysisGrid::kTest))
2427 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2428 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2429 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2430 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2431 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2432 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2433 printf("=====================================================================\n");
2434 printf("= Job price: ___________________________________ %d\n", fPrice);
2435 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2436 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2437 if (fMaxInitFailed>0)
2438 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2439 if (fMasterResubmitThreshold>0)
2440 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2441 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2442 if (fNrunsPerMaster>0)
2443 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2444 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2445 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2446 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2447 if (fArguments.Length())
2448 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2449 if (fExecutableArgs.Length())
2450 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2451 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2452 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2453 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2454 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2456 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2457 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2458 if (fIncludePath.Data())
2459 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2460 if (fCloseSE.Length())
2461 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2462 if (fFriendChainName.Length())
2463 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2464 if (fPackages && fPackages->GetEntries()) {
2465 TIter next(fPackages);
2468 while ((obj=next())) list += obj->GetName();
2469 printf("= Par files to be used: ________________________ %s\n", list.Data());
2473 //______________________________________________________________________________
2474 void AliAnalysisAlien::SetDefaults()
2476 // Set default values for everything. What cannot be filled will be left empty.
2477 if (fGridJDL) delete fGridJDL;
2478 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2479 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2482 fSplitMaxInputFileNumber = 100;
2484 fMasterResubmitThreshold = 0;
2490 fNrunsPerMaster = 1;
2491 fMaxMergeFiles = 100;
2493 fExecutable = "analysis.sh";
2494 fExecutableCommand = "root -b -q";
2496 fExecutableArgs = "";
2497 fAnalysisMacro = "myAnalysis.C";
2498 fAnalysisSource = "";
2499 fAdditionalLibs = "";
2503 fAliROOTVersion = "";
2504 fUser = ""; // Your alien user name
2505 fGridWorkingDir = "";
2506 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2507 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2508 fFriendChainName = "";
2509 fGridOutputDir = "output";
2510 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2511 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2512 fInputFormat = "xml-single";
2513 fJDLName = "analysis.jdl";
2514 fJobTag = "Automatically generated analysis JDL";
2515 fMergeExcludes = "";
2518 SetCheckCopy(kTRUE);
2519 SetDefaultOutputs(kTRUE);
2523 //______________________________________________________________________________
2524 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2526 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2527 // First check if the result is already in the output directory.
2528 if (FileExists(Form("%s/%s",aliendir,filename))) {
2529 printf("Final merged results found. Not merging again.\n");
2532 // Now check the last stage done.
2535 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2538 // Next stage of merging
2540 TString pattern = "*root_archive.zip";
2541 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2542 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2543 if (res) delete res;
2544 // Write standard output to file
2545 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2546 // Count the number of files inside
2548 ifile.open(Form("Stage_%d.xml",stage));
2549 if (!ifile.good()) {
2550 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2555 while (!ifile.eof()) {
2557 if (line.Contains("/event")) nfiles++;
2561 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2564 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2566 // Copy the file in the output directory
2567 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2568 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2569 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2570 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2571 // Check if this is the last stage to be done.
2572 Bool_t laststage = (nfiles<nperchunk);
2573 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2575 printf("### Submiting final merging stage %d\n", stage);
2576 TString finalJDL = jdl;
2577 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2578 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2579 Int_t jobId = SubmitSingleJob(query);
2580 if (!jobId) return kFALSE;
2582 printf("### Submiting merging stage %d\n", stage);
2583 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2584 Int_t jobId = SubmitSingleJob(query);
2585 if (!jobId) return kFALSE;
2590 //______________________________________________________________________________
2591 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2593 // Loat the analysis manager from a file.
2594 TFile *file = TFile::Open(fname);
2596 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2599 TIter nextkey(file->GetListOfKeys());
2600 AliAnalysisManager *mgr = 0;
2602 while ((key=(TKey*)nextkey())) {
2603 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2604 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2607 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2611 //______________________________________________________________________________
2612 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2614 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2615 if (!gGrid) return 0;
2616 printf("=> %s ------> ",query);
2617 TGridResult *res = gGrid->Command(query);
2619 TString jobId = res->GetKey(0,"jobId");
2621 if (jobId.IsNull()) {
2622 printf("submission failed. Reason:\n");
2625 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2628 printf(" Job id: %s\n", jobId.Data());
2632 //______________________________________________________________________________
2633 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2635 // Merge given output files from basedir. Basedir can be an alien output directory
2636 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2637 // files in a group (ignored for xml input). Merging can be done in stages:
2638 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2639 // stage=1 : works with an xml of all root_archive.zip in the output directory
2640 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2641 TString outputFile = output;
2643 TString outputChunk;
2644 TString previousChunk = "";
2645 TObjArray *listoffiles = new TObjArray();
2646 // listoffiles->SetOwner();
2647 Int_t countChunk = 0;
2648 Int_t countZero = nmaxmerge;
2649 Bool_t merged = kTRUE;
2650 Int_t index = outputFile.Index("@");
2651 if (index > 0) outputFile.Remove(index);
2652 TString inputFile = outputFile;
2653 TString sbasedir = basedir;
2654 if (sbasedir.Contains(".xml")) {
2655 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2656 nmaxmerge = 9999999;
2657 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2659 ::Error("MergeOutput", "Input XML collection empty.");
2662 // Iterate grid collection
2663 while (coll->Next()) {
2664 TString fname = gSystem->DirName(coll->GetTURL());
2667 listoffiles->Add(new TNamed(fname.Data(),""));
2670 command = Form("find %s/ *%s", basedir, inputFile.Data());
2671 printf("command: %s\n", command.Data());
2672 TGridResult *res = gGrid->Command(command);
2674 ::Error("MergeOutput","No result for the find command\n");
2680 while ((map=(TMap*)nextmap())) {
2681 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2682 if (!objs || !objs->GetString().Length()) {
2683 // Nothing found - skip this output
2688 listoffiles->Add(new TNamed(objs->GetName(),""));
2692 if (!listoffiles->GetEntries()) {
2693 ::Error("MergeOutput","No result for the find command\n");
2698 TFileMerger *fm = 0;
2699 TIter next0(listoffiles);
2700 TObjArray *listoffilestmp = new TObjArray();
2701 listoffilestmp->SetOwner();
2704 // Keep only the files at upper level
2705 Int_t countChar = 0;
2706 while ((nextfile=next0())) {
2707 snextfile = nextfile->GetName();
2708 Int_t crtCount = snextfile.CountChar('/');
2709 if (nextfile == listoffiles->First()) countChar = crtCount;
2710 if (crtCount < countChar) countChar = crtCount;
2713 while ((nextfile=next0())) {
2714 snextfile = nextfile->GetName();
2715 Int_t crtCount = snextfile.CountChar('/');
2716 if (crtCount > countChar) {
2720 listoffilestmp->Add(nextfile);
2723 listoffiles = listoffilestmp; // Now contains 'good' files
2724 listoffiles->Print();
2725 TIter next(listoffiles);
2726 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2727 outputChunk = outputFile;
2728 outputChunk.ReplaceAll(".root", "_*.root");
2729 // Check for existent temporary merge files
2730 // Check overwrite mode and remove previous partial results if needed
2731 // Preserve old merging functionality for stage 0.
2733 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2735 // Skip as many input files as in a chunk
2736 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2739 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2743 snextfile = nextfile->GetName();
2745 outputChunk = outputFile;
2746 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2748 if (gSystem->AccessPathName(outputChunk)) continue;
2749 // Merged file with chunks up to <countChunk> found
2750 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2751 previousChunk = outputChunk;
2755 countZero = nmaxmerge;
2757 while ((nextfile=next())) {
2758 snextfile = nextfile->GetName();
2759 // Loop 'find' results and get next LFN
2760 if (countZero == nmaxmerge) {
2761 // First file in chunk - create file merger and add previous chunk if any.
2762 fm = new TFileMerger(kTRUE);
2763 fm->SetFastMethod(kTRUE);
2764 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2765 outputChunk = outputFile;
2766 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2768 // If last file found, put merged results in the output file
2769 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2770 // Add file to be merged and decrement chunk counter.
2771 fm->AddFile(snextfile);
2773 if (countZero==0 || nextfile == listoffiles->Last()) {
2774 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2775 // Nothing found - skip this output
2776 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2780 fm->OutputFile(outputChunk);
2781 // Merge the outputs, then go to next chunk
2783 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2787 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2788 gSystem->Unlink(previousChunk);
2790 if (nextfile == listoffiles->Last()) break;
2792 countZero = nmaxmerge;
2793 previousChunk = outputChunk;
2800 // Merging stage different than 0.
2801 // Move to the begining of the requested chunk.
2802 fm = new TFileMerger(kTRUE);
2803 fm->SetFastMethod(kTRUE);
2804 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2806 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2807 // Nothing found - skip this output
2808 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2812 fm->OutputFile(outputFile);
2813 // Merge the outputs
2815 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2819 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2825 //______________________________________________________________________________
2826 Bool_t AliAnalysisAlien::MergeOutputs()
2828 // Merge analysis outputs existing in the AliEn space.
2829 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2830 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2832 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2836 if (!TestBit(AliAnalysisGrid::kMerge)) {
2837 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2840 if (fProductionMode) {
2841 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2844 Info("MergeOutputs", "Submitting merging JDL");
2845 if (!SubmitMerging()) return kFALSE;
2846 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2847 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2850 // Get the output path
2851 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2852 if (!DirectoryExists(fGridOutputDir)) {
2853 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2856 if (!fOutputFiles.Length()) {
2857 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2860 // Check if fast read option was requested
2861 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2862 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2863 if (fFastReadOption) {
2864 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2865 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2866 gEnv->SetValue("XNet.ConnectTimeout",50);
2867 gEnv->SetValue("XNet.RequestTimeout",50);
2868 gEnv->SetValue("XNet.MaxRedirectCount",2);
2869 gEnv->SetValue("XNet.ReconnectTimeout",50);
2870 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2872 // Make sure we change the temporary directory
2873 gSystem->Setenv("TMPDIR", gSystem->pwd());
2874 // Set temporary compilation directory to current one
2875 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2876 TObjArray *list = fOutputFiles.Tokenize(",");
2880 Bool_t merged = kTRUE;
2881 while((str=(TObjString*)next())) {
2882 outputFile = str->GetString();
2883 Int_t index = outputFile.Index("@");
2884 if (index > 0) outputFile.Remove(index);
2885 TString outputChunk = outputFile;
2886 outputChunk.ReplaceAll(".root", "_*.root");
2887 // Skip already merged outputs
2888 if (!gSystem->AccessPathName(outputFile)) {
2889 if (fOverwriteMode) {
2890 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2891 gSystem->Unlink(outputFile);
2892 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2893 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2894 outputChunk.Data());
2895 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2898 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2902 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2903 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2904 outputChunk.Data());
2905 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2908 if (fMergeExcludes.Contains(outputFile.Data()) ||
2909 fRegisterExcludes.Contains(outputFile.Data())) continue;
2910 // Perform a 'find' command in the output directory, looking for registered outputs
2911 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2913 Error("MergeOutputs", "Terminate() will NOT be executed");
2916 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2917 if (fileOpened) fileOpened->Close();
2922 //______________________________________________________________________________
2923 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2925 // Use the output files connected to output containers from the analysis manager
2926 // rather than the files defined by SetOutputFiles
2927 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2928 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2929 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2932 //______________________________________________________________________________
2933 void AliAnalysisAlien::SetOutputFiles(const char *list)
2935 // Manually set the output files list.
2936 // Removes duplicates. Not allowed if default outputs are not disabled.
2937 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2938 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2941 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2943 TString slist = list;
2944 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2945 TObjArray *arr = slist.Tokenize(" ");
2949 while ((os=(TObjString*)next())) {
2950 sout = os->GetString();
2951 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2952 if (fOutputFiles.Contains(sout)) continue;
2953 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2954 fOutputFiles += sout;
2959 //______________________________________________________________________________
2960 void AliAnalysisAlien::SetOutputArchive(const char *list)
2962 // Manually set the output archive list. Free text - you are on your own...
2963 // Not allowed if default outputs are not disabled.
2964 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2965 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2968 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2969 fOutputArchive = list;
2972 //______________________________________________________________________________
2973 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2975 // Setting a prefered output SE is not allowed anymore.
2976 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2979 //______________________________________________________________________________
2980 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2982 // Set some PROOF special parameter.
2983 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2985 TObject *old = pair->Key();
2986 TObject *val = pair->Value();
2987 fProofParam.Remove(old);
2991 fProofParam.Add(new TObjString(pname), new TObjString(value));
2994 //______________________________________________________________________________
2995 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2997 // Returns a special PROOF parameter.
2998 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2999 if (!pair) return 0;
3000 return pair->Value()->GetName();
3003 //______________________________________________________________________________
3004 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
3006 // Start remote grid analysis.
3007 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3008 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
3009 if (!mgr || !mgr->IsInitialized()) {
3010 Error("StartAnalysis", "You need an initialized analysis manager for this");
3013 // Are we in PROOF mode ?
3014 if (mgr->IsProofMode()) {
3015 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
3016 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3017 if (fProofCluster.IsNull()) {
3018 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3021 if (fProofDataSet.IsNull() && !testMode) {
3022 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3025 // Set the needed environment
3026 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3027 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3028 if (fProofReset && !testMode) {
3029 if (fProofReset==1) {
3030 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3031 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3033 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3034 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3036 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3041 // Check if there is an old active session
3042 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3044 Error("StartAnalysis","You have to reset your old session first\n");
3048 // Do we need to change the ROOT version ? The success of this cannot be checked.
3049 if (!fRootVersionForProof.IsNull() && !testMode) {
3050 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
3051 fProofCluster.Data(), fRootVersionForProof.Data()));
3053 // Connect to PROOF and check the status
3056 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3057 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3059 if (!sworkers.IsNull())
3060 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3062 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3064 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3066 Error("StartAnalysis", "Could not start PROOF in test mode");
3071 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3074 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3075 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3076 // Set proof special parameters if any
3077 TIter nextpp(&fProofParam);
3078 TObject *proofparam;
3079 while ((proofparam=nextpp())) {
3080 TString svalue = GetProofParameter(proofparam->GetName());
3081 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3083 // Is dataset existing ?
3085 TString dataset = fProofDataSet;
3086 Int_t index = dataset.Index("#");
3087 if (index>=0) dataset.Remove(index);
3088 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3089 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3092 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3094 // Is ClearPackages() needed ?
3095 if (TestSpecialBit(kClearPackages)) {
3096 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3097 gROOT->ProcessLine("gProof->ClearPackages();");
3099 // Is a given aliroot mode requested ?
3102 if (!fAliRootMode.IsNull()) {
3103 TString alirootMode = fAliRootMode;
3104 if (alirootMode == "default") alirootMode = "";
3105 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3106 optionsList.SetOwner();
3107 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3108 // Check the additional libs to be loaded
3110 Bool_t parMode = kFALSE;
3111 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3112 // Parse the extra libs for .so
3113 if (fAdditionalLibs.Length()) {
3114 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3117 while((str=(TObjString*)next())) {
3118 if (str->GetString().Contains(".so")) {
3120 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());
3123 TString stmp = str->GetName();
3124 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3125 stmp.ReplaceAll(".so","");
3126 if (!extraLibs.IsNull()) extraLibs += ":";
3130 if (str->GetString().Contains(".par")) {
3131 // The first par file found in the list will not allow any further .so
3133 if (!parLibs.IsNull()) parLibs += ":";
3134 parLibs += str->GetName();
3138 if (list) delete list;
3140 if (!extraLibs.IsNull()) {
3141 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3142 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3144 // Check extra includes
3145 if (!fIncludePath.IsNull()) {
3146 TString includePath = fIncludePath;
3147 includePath.ReplaceAll(" ",":");
3148 includePath.ReplaceAll("$ALICE_ROOT/","");
3149 includePath.ReplaceAll("${ALICE_ROOT}/","");
3150 includePath.ReplaceAll("-I","");
3151 includePath.Remove(TString::kTrailing, ':');
3152 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3153 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3155 // Check if connection to grid is requested
3156 if (TestSpecialBit(kProofConnectGrid))
3157 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3158 // Enable AliRoot par
3160 // Enable proof lite package
3161 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3162 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3163 TNamed *obj = (TNamed*)optionsList.At(i);
3164 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3166 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3167 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3168 Info("StartAnalysis", "AliRootProofLite enabled");
3170 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3174 if ( ! fAliROOTVersion.IsNull() ) {
3175 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3176 fAliROOTVersion.Data(), &optionsList))) {
3177 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3182 // Enable first par files from fAdditionalLibs
3183 if (!parLibs.IsNull()) {
3184 TObjArray *list = parLibs.Tokenize(":");
3186 TObjString *package;
3187 while((package=(TObjString*)next())) {
3188 TString spkg = package->GetName();
3189 spkg.ReplaceAll(".par", "");
3190 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3191 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3192 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3193 if (gROOT->ProcessLine(enablePackage)) {
3194 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3198 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3202 if (list) delete list;
3205 if (fAdditionalLibs.Contains(".so") && !testMode) {
3206 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3207 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3211 // Enable par files if requested
3212 if (fPackages && fPackages->GetEntries()) {
3213 TIter next(fPackages);
3215 while ((package=next())) {
3216 // Skip packages already enabled
3217 if (parLibs.Contains(package->GetName())) continue;
3218 TString spkg = package->GetName();
3219 spkg.ReplaceAll(".par", "");
3220 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3221 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3222 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3223 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3227 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3232 // Do we need to load analysis source files ?
3233 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3234 if (fAnalysisSource.Length()) {
3235 TObjArray *list = fAnalysisSource.Tokenize(" ");
3238 while((str=(TObjString*)next())) {
3239 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3241 if (list) delete list;
3244 // Register dataset to proof lite.
3245 if (fFileForTestMode.IsNull()) {
3246 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3249 if (gSystem->AccessPathName(fFileForTestMode)) {
3250 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3253 TFileCollection *coll = new TFileCollection();
3254 coll->AddFromFile(fFileForTestMode);
3255 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3256 gROOT->ProcessLine("gProof->ShowDataSets()");
3261 // Check if output files have to be taken from the analysis manager
3262 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3263 // Add output files and AOD files
3264 fOutputFiles = GetListOfFiles("outaod");
3265 // Add extra files registered to the analysis manager
3266 TString extra = GetListOfFiles("ext");
3267 if (!extra.IsNull()) {
3268 extra.ReplaceAll(".root", "*.root");
3269 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3270 fOutputFiles += extra;
3272 // Compose the output archive.
3273 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3274 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3276 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3277 if (TestBit(AliAnalysisGrid::kOffline)) {
3278 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3279 \n there nor any job run. You can revise the JDL and analysis \
3280 \n macro then run the same in \"submit\" mode.");
3281 } else if (TestBit(AliAnalysisGrid::kTest)) {
3282 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3284 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3285 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3286 \n space and job submitted.");
3287 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3288 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3289 if (fMergeViaJDL) CheckInputData();
3292 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3297 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3300 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3301 if (!CheckInputData()) {
3302 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3305 if (!CreateDataset(fDataPattern)) {
3307 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3308 if (fRunNumbers.Length()) serror = "run numbers";
3309 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3310 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3311 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3314 WriteAnalysisFile();
3315 WriteAnalysisMacro();
3317 WriteValidationScript();
3319 WriteMergingMacro();
3320 WriteMergeExecutable();
3321 WriteValidationScript(kTRUE);
3323 if (!CreateJDL()) return kFALSE;
3324 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3326 // Locally testing the analysis
3327 Info("StartAnalysis", "\n_______________________________________________________________________ \
3328 \n Running analysis script in a daughter shell as on a worker node \
3329 \n_______________________________________________________________________");
3330 TObjArray *list = fOutputFiles.Tokenize(",");
3334 while((str=(TObjString*)next())) {
3335 outputFile = str->GetString();
3336 Int_t index = outputFile.Index("@");
3337 if (index > 0) outputFile.Remove(index);
3338 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3341 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3342 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3343 // gSystem->Exec("cat stdout");
3346 // Check if submitting is managed by LPM manager
3347 if (fProductionMode) {
3348 //TString prodfile = fJDLName;
3349 //prodfile.ReplaceAll(".jdl", ".prod");
3350 //WriteProductionFile(prodfile);
3351 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3354 // Submit AliEn job(s)
3355 gGrid->Cd(fGridOutputDir);
3358 if (!fRunNumbers.Length() && !fRunRange[0]) {
3359 // Submit a given xml or a set of runs
3360 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3361 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3363 const char *cjobId = res->GetKey(0,"jobId");
3367 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3370 Info("StartAnalysis", "\n_______________________________________________________________________ \
3371 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3372 \n_______________________________________________________________________",
3373 fJDLName.Data(), cjobId);
3378 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3382 // Submit for a range of enumeration of runs.
3383 if (!Submit()) return kFALSE;
3386 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3387 \n You may exit at any time and terminate the job later using the option <terminate> \
3388 \n ##################################################################################", jobID.Data());
3389 gSystem->Exec("aliensh");
3393 //______________________________________________________________________________
3394 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3396 // Get a comma-separated list of output files of the requested type.
3397 // Type can be (case unsensitive):
3398 // aod - list of aod files (std, extensions and filters)
3399 // out - list of output files connected to containers (but not aod's or extras)
3400 // ext - list of extra files registered to the manager
3401 // ter - list of files produced in terminate
3402 static TString files;
3404 TString stype = type;
3406 TString aodfiles, extra;
3407 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3409 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3410 return files.Data();
3412 if (mgr->GetOutputEventHandler()) {
3413 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3414 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3415 if (!extraaod.IsNull()) {
3417 aodfiles += extraaod;
3420 if (stype.Contains("aod")) {
3422 if (stype == "aod") return files.Data();
3424 // Add output files that are not in the list of AOD files
3425 TString outputfiles = "";
3426 TIter next(mgr->GetOutputs());
3427 AliAnalysisDataContainer *output;
3428 const char *filename = 0;
3429 while ((output=(AliAnalysisDataContainer*)next())) {
3430 filename = output->GetFileName();
3431 if (!(strcmp(filename, "default"))) continue;
3432 if (outputfiles.Contains(filename)) continue;
3433 if (aodfiles.Contains(filename)) continue;
3434 if (!outputfiles.IsNull()) outputfiles += ",";
3435 outputfiles += filename;
3437 if (stype.Contains("out")) {
3438 if (!files.IsNull()) files += ",";
3439 files += outputfiles;
3440 if (stype == "out") return files.Data();
3442 // Add extra files registered to the analysis manager
3444 extra = mgr->GetExtraFiles();
3445 if (!extra.IsNull()) {
3447 extra.ReplaceAll(" ", ",");
3448 TObjArray *fextra = extra.Tokenize(",");
3449 TIter nextx(fextra);
3451 while ((obj=nextx())) {
3452 if (aodfiles.Contains(obj->GetName())) continue;
3453 if (outputfiles.Contains(obj->GetName())) continue;
3454 if (sextra.Contains(obj->GetName())) continue;
3455 if (!sextra.IsNull()) sextra += ",";
3456 sextra += obj->GetName();
3459 if (stype.Contains("ext")) {
3460 if (!files.IsNull()) files += ",";
3464 if (stype == "ext") return files.Data();
3466 if (!fTerminateFiles.IsNull()) {
3467 fTerminateFiles.Strip();
3468 fTerminateFiles.ReplaceAll(" ",",");
3469 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3470 TIter nextx(fextra);
3472 while ((obj=nextx())) {
3473 if (aodfiles.Contains(obj->GetName())) continue;
3474 if (outputfiles.Contains(obj->GetName())) continue;
3475 if (termfiles.Contains(obj->GetName())) continue;
3476 if (sextra.Contains(obj->GetName())) continue;
3477 if (!termfiles.IsNull()) termfiles += ",";
3478 termfiles += obj->GetName();
3482 if (stype.Contains("ter")) {
3483 if (!files.IsNull() && !termfiles.IsNull()) {
3488 return files.Data();
3491 //______________________________________________________________________________
3492 Bool_t AliAnalysisAlien::Submit()
3494 // Submit all master jobs.
3495 Int_t nmasterjobs = fInputFiles->GetEntries();
3496 Long_t tshoot = gSystem->Now();
3497 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3498 while (fNsubmitted < nmasterjobs) {
3499 Long_t now = gSystem->Now();
3500 if ((now-tshoot)>30000) {
3502 if (!SubmitNext()) return kFALSE;
3508 //______________________________________________________________________________
3509 Bool_t AliAnalysisAlien::SubmitMerging()
3511 // Submit all merging jobs.
3512 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3513 gGrid->Cd(fGridOutputDir);
3514 TString mergeJDLName = fExecutable;
3515 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3517 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3520 Int_t ntosubmit = fInputFiles->GetEntries();
3521 for (Int_t i=0; i<ntosubmit; i++) {
3522 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3523 runOutDir.ReplaceAll(".xml", "");
3524 if (fOutputToRunNo) {
3525 // The output directory is the run number
3526 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3527 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3529 if (!fRunNumbers.Length() && !fRunRange[0]) {
3530 // The output directory is the grid outdir
3531 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3532 runOutDir = fGridOutputDir;
3534 // The output directory is the master number in 3 digits format
3535 printf("### Submitting merging job for master <%03d>\n", i);
3536 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3539 // Check now the number of merging stages.
3540 TObjArray *list = fOutputFiles.Tokenize(",");
3544 while((str=(TObjString*)next())) {
3545 outputFile = str->GetString();
3546 Int_t index = outputFile.Index("@");
3547 if (index > 0) outputFile.Remove(index);
3548 if (!fMergeExcludes.Contains(outputFile) &&
3549 !fRegisterExcludes.Contains(outputFile)) break;
3552 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3553 if (!done && (i==ntosubmit-1)) return kFALSE;
3554 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3556 if (!ntosubmit) return kTRUE;
3557 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3558 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3559 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3560 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3561 \n ################################################################################################################");
3562 gSystem->Exec("aliensh");
3566 //______________________________________________________________________________
3567 Bool_t AliAnalysisAlien::SubmitNext()
3569 // Submit next bunch of master jobs if the queue is free. The first master job is
3570 // submitted right away, while the next will not be unless the previous was split.
3571 // The plugin will not submit new master jobs if there are more that 500 jobs in
3573 static Bool_t iscalled = kFALSE;
3574 static Int_t firstmaster = 0;
3575 static Int_t lastmaster = 0;
3576 static Int_t npermaster = 0;
3577 if (iscalled) return kTRUE;
3579 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3580 Int_t ntosubmit = 0;
3583 Int_t nmasterjobs = fInputFiles->GetEntries();
3586 if (!IsUseSubmitPolicy()) {
3588 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3589 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3590 ntosubmit = nmasterjobs;
3593 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3594 printf("=== master %d: %s\n", lastmaster, status.Data());
3595 // If last master not split, just return
3596 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3597 // No more than 100 waiting jobs
3598 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3599 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3600 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3601 if (!ntosubmit) ntosubmit = 1;
3602 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3603 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3605 for (Int_t i=0; i<ntosubmit; i++) {
3606 // Submit for a range of enumeration of runs.
3607 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3609 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3610 runOutDir.ReplaceAll(".xml", "");
3612 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3614 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3615 printf("********* %s\n",query.Data());
3616 res = gGrid->Command(query);
3618 TString cjobId1 = res->GetKey(0,"jobId");
3619 if (!cjobId1.Length()) {
3623 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3626 Info("StartAnalysis", "\n_______________________________________________________________________ \
3627 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3628 \n_______________________________________________________________________",
3629 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3632 lastmaster = cjobId1.Atoi();
3633 if (!firstmaster) firstmaster = lastmaster;
3638 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3646 //______________________________________________________________________________
3647 void AliAnalysisAlien::WriteAnalysisFile()
3649 // Write current analysis manager into the file <analysisFile>
3650 TString analysisFile = fExecutable;
3651 analysisFile.ReplaceAll(".sh", ".root");
3652 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3653 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3654 if (!mgr || !mgr->IsInitialized()) {
3655 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3658 // Check analysis type
3660 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3661 handler = (TObject*)mgr->GetInputEventHandler();
3663 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3664 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3665 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3666 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3668 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3669 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3672 TDirectory *cdir = gDirectory;
3673 TFile *file = TFile::Open(analysisFile, "RECREATE");
3675 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3676 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3677 // Unless merging makes no sense
3678 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3681 // Enable termination for local jobs
3682 mgr->SetSkipTerminate(kFALSE);
3684 if (cdir) cdir->cd();
3685 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3687 Bool_t copy = kTRUE;
3688 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3691 TString workdir = gGrid->GetHomeDirectory();
3692 workdir += fGridWorkingDir;
3693 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3694 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3695 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3696 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3700 //______________________________________________________________________________
3701 void AliAnalysisAlien::WriteAnalysisMacro()
3703 // Write the analysis macro that will steer the analysis in grid mode.
3704 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3706 out.open(fAnalysisMacro.Data(), ios::out);
3708 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3711 Bool_t hasSTEERBase = kFALSE;
3712 Bool_t hasESD = kFALSE;
3713 Bool_t hasAOD = kFALSE;
3714 Bool_t hasANALYSIS = kFALSE;
3715 Bool_t hasOADB = kFALSE;
3716 Bool_t hasANALYSISalice = kFALSE;
3717 Bool_t hasCORRFW = kFALSE;
3718 TString func = fAnalysisMacro;
3719 TString type = "ESD";
3720 TString comment = "// Analysis using ";
3721 if (IsUseMCchain()) {
3725 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3726 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3731 if (type!="AOD" && fFriendChainName!="") {
3732 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3735 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3736 else comment += " data";
3737 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3738 func.ReplaceAll(".C", "");
3739 out << "void " << func.Data() << "()" << endl;
3741 out << comment.Data() << endl;
3742 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3743 out << " TStopwatch timer;" << endl;
3744 out << " timer.Start();" << endl << endl;
3745 // Change temp directory to current one
3746 if (!IsLocalTest()) {
3747 out << "// connect to AliEn and make the chain" << endl;
3748 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3750 out << "// Set temporary merging directory to current one" << endl;
3751 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3752 out << "// Set temporary compilation directory to current one" << endl;
3753 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3754 // Reset existing include path
3755 out << "// Reset existing include path and add current directory first in the search" << endl;
3756 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3757 if (!fExecutableCommand.Contains("aliroot")) {
3758 out << "// load base root libraries" << endl;
3759 out << " gSystem->Load(\"libTree\");" << endl;
3760 out << " gSystem->Load(\"libGeom\");" << endl;
3761 out << " gSystem->Load(\"libVMC\");" << endl;
3762 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3763 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3765 if (fAdditionalRootLibs.Length()) {
3766 // in principle libtree /lib geom libvmc etc. can go into this list, too
3767 out << "// Add aditional libraries" << endl;
3768 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3771 while((str=(TObjString*)next())) {
3772 if (str->GetString().Contains(".so"))
3773 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3775 if (list) delete list;
3777 out << "// Load analysis framework libraries" << endl;
3778 TString setupPar = "AliAnalysisAlien::SetupPar";
3780 if (!fExecutableCommand.Contains("aliroot")) {
3781 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3782 out << " gSystem->Load(\"libESD\");" << endl;
3783 out << " gSystem->Load(\"libAOD\");" << endl;
3785 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3786 out << " gSystem->Load(\"libOADB\");" << endl;
3787 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3788 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3790 TIter next(fPackages);
3793 while ((obj=next())) {
3794 pkgname = obj->GetName();
3795 if (pkgname == "STEERBase" ||
3796 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3797 if (pkgname == "ESD" ||
3798 pkgname == "ESD.par") hasESD = kTRUE;
3799 if (pkgname == "AOD" ||
3800 pkgname == "AOD.par") hasAOD = kTRUE;
3801 if (pkgname == "ANALYSIS" ||
3802 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3803 if (pkgname == "OADB" ||
3804 pkgname == "OADB.par") hasOADB = kTRUE;
3805 if (pkgname == "ANALYSISalice" ||
3806 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3807 if (pkgname == "CORRFW" ||
3808 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3810 if (hasANALYSISalice) setupPar = "SetupPar";
3811 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3812 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3813 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3814 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3815 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3816 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3817 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3818 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3819 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3820 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3821 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3822 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3823 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3824 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3825 out << "// Compile other par packages" << endl;
3827 while ((obj=next())) {
3828 pkgname = obj->GetName();
3829 if (pkgname == "STEERBase" ||
3830 pkgname == "STEERBase.par" ||
3832 pkgname == "ESD.par" ||
3834 pkgname == "AOD.par" ||
3835 pkgname == "ANALYSIS" ||
3836 pkgname == "ANALYSIS.par" ||
3837 pkgname == "OADB" ||
3838 pkgname == "OADB.par" ||
3839 pkgname == "ANALYSISalice" ||
3840 pkgname == "ANALYSISalice.par" ||
3841 pkgname == "CORRFW" ||
3842 pkgname == "CORRFW.par") continue;
3843 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3846 out << "// include path" << endl;
3847 // Get the include path from the interpreter and remove entries pointing to AliRoot
3848 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3849 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3850 out << " TIter nextpath(listpaths);" << endl;
3851 out << " TObjString *pname;" << endl;
3852 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3853 out << " TString current = pname->GetName();" << endl;
3854 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3855 out << " gSystem->AddIncludePath(current);" << endl;
3856 out << " }" << endl;
3857 out << " if (listpaths) delete listpaths;" << endl;
3858 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3859 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3860 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3861 if (fAdditionalLibs.Length()) {
3862 out << "// Add aditional AliRoot libraries" << endl;
3863 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3866 while((str=(TObjString*)next())) {
3867 if (str->GetString().Contains(".so"))
3868 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3869 if (str->GetString().Contains(".par"))
3870 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3872 if (list) delete list;
3875 out << "// analysis source to be compiled at runtime (if any)" << endl;
3876 if (fAnalysisSource.Length()) {
3877 TObjArray *list = fAnalysisSource.Tokenize(" ");
3880 while((str=(TObjString*)next())) {
3881 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3883 if (list) delete list;
3886 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3887 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3888 if (fFastReadOption) {
3889 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 !!! \
3890 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3891 out << "// fast xrootd reading enabled" << endl;
3892 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3893 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3894 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3895 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3896 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3897 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3899 out << "// read the analysis manager from file" << endl;
3900 TString analysisFile = fExecutable;
3901 analysisFile.ReplaceAll(".sh", ".root");
3902 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3903 << analysisFile << "\");" << endl;
3904 out << " if (!mgr) return;" << endl;
3905 if (IsLocalTest()) {
3906 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3907 out << " plugin->SetRunMode(\"test\");" << endl;
3908 if (fFileForTestMode.IsNull())
3909 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3911 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3912 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3913 if (!fFriendChainName.IsNull())
3914 out << " plugin->SetFriendChainName(\"" << fFriendChainName << "\");" << endl;
3915 out << " mgr->SetGridHandler(plugin);" << endl;
3916 if (AliAnalysisManager::GetAnalysisManager()) {
3917 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3918 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3920 out << " mgr->SetDebugLevel(10);" << endl;
3921 out << " mgr->SetNSysInfo(100);" << endl;
3924 out << " mgr->PrintStatus();" << endl;
3925 if (AliAnalysisManager::GetAnalysisManager()) {
3926 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3927 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3929 if (TestBit(AliAnalysisGrid::kTest))
3930 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3932 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3935 if (!IsLocalTest()) {
3936 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3937 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3939 out << " mgr->StartAnalysis(\"localfile\");" << endl;
3941 out << " timer.Stop();" << endl;
3942 out << " timer.Print();" << endl;
3943 out << "}" << endl << endl;
3944 if (!IsLocalTest()) {
3945 out <<"//________________________________________________________________________________" << endl;
3946 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3948 out << "// Create a chain using url's from xml file" << endl;
3949 out << " TString filename;" << endl;
3950 out << " Int_t run = 0;" << endl;
3951 if (IsUseMCchain()) {
3952 out << " TString treename = \"TE\";" << endl;
3954 out << " TString treename = type;" << endl;
3955 out << " treename.ToLower();" << endl;
3956 out << " treename += \"Tree\";" << endl;
3958 out << " printf(\"***************************************\\n\");" << endl;
3959 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3960 out << " printf(\"***************************************\\n\");" << endl;
3961 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3962 out << " if (!coll) {" << endl;
3963 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3964 out << " return NULL;" << endl;
3965 out << " }" << endl;
3966 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3967 out << " TChain *chain = new TChain(treename);" << endl;
3968 if(fFriendChainName!="") {
3969 out << " TChain *chainFriend = new TChain(treename);" << endl;
3971 out << " coll->Reset();" << endl;
3972 out << " while (coll->Next()) {" << endl;
3973 out << " filename = coll->GetTURL("");" << endl;
3974 out << " if (mgr) {" << endl;
3975 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3976 out << " if (nrun && nrun != run) {" << endl;
3977 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3978 out << " mgr->SetRunFromPath(nrun);" << endl;
3979 out << " run = nrun;" << endl;
3980 out << " }" << endl;
3981 out << " }" << endl;
3982 out << " chain->Add(filename);" << endl;
3983 if(fFriendChainName!="") {
3984 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3985 out << " if (fileFriend.Index(\"#\") > -1) fileFriend.Remove(fileFriend.Index(\"#\"));" << endl;
3986 out << " fileFriend = gSystem->DirName(fileFriend);" << endl;
3987 out << " fileFriend += \"/\";" << endl;
3988 out << " fileFriend += \"" << fFriendChainName << "\";";
3989 out << " TFile *file = TFile::Open(fileFriend);" << endl;
3990 out << " if (file) {" << endl;
3991 out << " file->Close();" << endl;
3992 out << " chainFriend->Add(fileFriend.Data());" << endl;
3993 out << " } else {" << endl;
3994 out << " ::Fatal(\"CreateChain\", \"Cannot open friend file: %s\", fileFriend.Data());" << endl;
3995 out << " return 0;" << endl;
3996 out << " }" << endl;
3998 out << " }" << endl;
3999 out << " if (!chain->GetNtrees()) {" << endl;
4000 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
4001 out << " return NULL;" << endl;
4002 out << " }" << endl;
4003 if(fFriendChainName!="") {
4004 out << " chain->AddFriend(chainFriend);" << endl;
4006 out << " return chain;" << endl;
4007 out << "}" << endl << endl;
4009 if (hasANALYSISalice) {
4010 out <<"//________________________________________________________________________________" << endl;
4011 out << "Bool_t SetupPar(const char *package) {" << endl;
4012 out << "// Compile the package and set it up." << endl;
4013 out << " TString pkgdir = package;" << endl;
4014 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4015 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4016 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4017 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4018 out << " // Check for BUILD.sh and execute" << endl;
4019 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4020 out << " printf(\"*******************************\\n\");" << endl;
4021 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4022 out << " printf(\"*******************************\\n\");" << endl;
4023 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4024 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4025 out << " gSystem->ChangeDirectory(cdir);" << endl;
4026 out << " return kFALSE;" << endl;
4027 out << " }" << endl;
4028 out << " } else {" << endl;
4029 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4030 out << " gSystem->ChangeDirectory(cdir);" << endl;
4031 out << " return kFALSE;" << endl;
4032 out << " }" << endl;
4033 out << " // Check for SETUP.C and execute" << endl;
4034 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4035 out << " printf(\"*******************************\\n\");" << endl;
4036 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4037 out << " printf(\"*******************************\\n\");" << endl;
4038 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4039 out << " } else {" << endl;
4040 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4041 out << " gSystem->ChangeDirectory(cdir);" << endl;
4042 out << " return kFALSE;" << endl;
4043 out << " }" << endl;
4044 out << " // Restore original workdir" << endl;
4045 out << " gSystem->ChangeDirectory(cdir);" << endl;
4046 out << " return kTRUE;" << endl;
4049 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4051 Bool_t copy = kTRUE;
4052 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4055 TString workdir = gGrid->GetHomeDirectory();
4056 workdir += fGridWorkingDir;
4057 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4058 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4059 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4060 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4061 Form("alien://%s/%s", workdir.Data(),
4062 fAnalysisMacro.Data()))) Fatal("","Terminating");
4066 //______________________________________________________________________________
4067 void AliAnalysisAlien::WriteMergingMacro()
4069 // Write a macro to merge the outputs per master job.
4070 if (!fMergeViaJDL) return;
4071 if (!fOutputFiles.Length()) {
4072 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4075 TString mergingMacro = fExecutable;
4076 mergingMacro.ReplaceAll(".sh","_merge.C");
4077 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4078 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4080 out.open(mergingMacro.Data(), ios::out);
4082 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4085 Bool_t hasSTEERBase = kFALSE;
4086 Bool_t hasESD = kFALSE;
4087 Bool_t hasAOD = kFALSE;
4088 Bool_t hasANALYSIS = kFALSE;
4089 Bool_t hasOADB = kFALSE;
4090 Bool_t hasANALYSISalice = kFALSE;
4091 Bool_t hasCORRFW = kFALSE;
4092 TString func = mergingMacro;
4094 func.ReplaceAll(".C", "");
4095 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4097 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4098 out << " TStopwatch timer;" << endl;
4099 out << " timer.Start();" << endl << endl;
4100 // Reset existing include path
4101 out << "// Reset existing include path and add current directory first in the search" << endl;
4102 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4103 if (!fExecutableCommand.Contains("aliroot")) {
4104 out << "// load base root libraries" << endl;
4105 out << " gSystem->Load(\"libTree\");" << endl;
4106 out << " gSystem->Load(\"libGeom\");" << endl;
4107 out << " gSystem->Load(\"libVMC\");" << endl;
4108 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4109 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4111 if (fAdditionalRootLibs.Length()) {
4112 // in principle libtree /lib geom libvmc etc. can go into this list, too
4113 out << "// Add aditional libraries" << endl;
4114 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4117 while((str=(TObjString*)next())) {
4118 if (str->GetString().Contains(".so"))
4119 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4121 if (list) delete list;
4123 out << "// Load analysis framework libraries" << endl;
4125 if (!fExecutableCommand.Contains("aliroot")) {
4126 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4127 out << " gSystem->Load(\"libESD\");" << endl;
4128 out << " gSystem->Load(\"libAOD\");" << endl;
4130 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4131 out << " gSystem->Load(\"libOADB\");" << endl;
4132 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4133 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4135 TIter next(fPackages);
4138 TString setupPar = "AliAnalysisAlien::SetupPar";
4139 while ((obj=next())) {
4140 pkgname = obj->GetName();
4141 if (pkgname == "STEERBase" ||
4142 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4143 if (pkgname == "ESD" ||
4144 pkgname == "ESD.par") hasESD = kTRUE;
4145 if (pkgname == "AOD" ||
4146 pkgname == "AOD.par") hasAOD = kTRUE;
4147 if (pkgname == "ANALYSIS" ||
4148 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4149 if (pkgname == "OADB" ||
4150 pkgname == "OADB.par") hasOADB = kTRUE;
4151 if (pkgname == "ANALYSISalice" ||
4152 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4153 if (pkgname == "CORRFW" ||
4154 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4156 if (hasANALYSISalice) setupPar = "SetupPar";
4157 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4158 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4159 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4160 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4161 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4162 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4163 out << " gSystem->Load(\"libOADB\");" << endl;
4164 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4165 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4166 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4167 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4168 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4169 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4170 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4171 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4172 out << "// Compile other par packages" << endl;
4174 while ((obj=next())) {
4175 pkgname = obj->GetName();
4176 if (pkgname == "STEERBase" ||
4177 pkgname == "STEERBase.par" ||
4179 pkgname == "ESD.par" ||
4181 pkgname == "AOD.par" ||
4182 pkgname == "ANALYSIS" ||
4183 pkgname == "ANALYSIS.par" ||
4184 pkgname == "OADB" ||
4185 pkgname == "OADB.par" ||
4186 pkgname == "ANALYSISalice" ||
4187 pkgname == "ANALYSISalice.par" ||
4188 pkgname == "CORRFW" ||
4189 pkgname == "CORRFW.par") continue;
4190 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4193 out << "// include path" << endl;
4194 // Get the include path from the interpreter and remove entries pointing to AliRoot
4195 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4196 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4197 out << " TIter nextpath(listpaths);" << endl;
4198 out << " TObjString *pname;" << endl;
4199 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4200 out << " TString current = pname->GetName();" << endl;
4201 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4202 out << " gSystem->AddIncludePath(current);" << endl;
4203 out << " }" << endl;
4204 out << " if (listpaths) delete listpaths;" << endl;
4205 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4206 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4207 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4208 if (fAdditionalLibs.Length()) {
4209 out << "// Add aditional AliRoot libraries" << endl;
4210 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4213 while((str=(TObjString*)next())) {
4214 if (str->GetString().Contains(".so"))
4215 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4217 if (list) delete list;
4220 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4221 if (fAnalysisSource.Length()) {
4222 TObjArray *list = fAnalysisSource.Tokenize(" ");
4225 while((str=(TObjString*)next())) {
4226 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4228 if (list) delete list;
4232 if (fFastReadOption) {
4233 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 !!!");
4234 out << "// fast xrootd reading enabled" << endl;
4235 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4236 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4237 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4238 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4239 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4240 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4242 // Change temp directory to current one
4243 out << "// Connect to AliEn" << endl;
4244 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4245 out << "// Set temporary merging directory to current one" << endl;
4246 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4247 out << "// Set temporary compilation directory to current one" << endl;
4248 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4249 out << " TString outputDir = dir;" << endl;
4250 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4251 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4252 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4253 out << " TIter *iter = new TIter(list);" << endl;
4254 out << " TObjString *str;" << endl;
4255 out << " TString outputFile;" << endl;
4256 out << " Bool_t merged = kTRUE;" << endl;
4257 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4258 out << " outputFile = str->GetString();" << endl;
4259 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4260 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4261 out << " if (index > 0) outputFile.Remove(index);" << endl;
4262 out << " // Skip already merged outputs" << endl;
4263 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4264 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4265 out << " continue;" << endl;
4266 out << " }" << endl;
4267 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4268 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4269 out << " if (!merged) {" << endl;
4270 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4271 out << " return;" << endl;
4272 out << " }" << endl;
4273 out << " }" << endl;
4274 out << " // all outputs merged, validate" << endl;
4275 out << " ofstream out;" << endl;
4276 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4277 out << " out.close();" << endl;
4278 out << " // read the analysis manager from file" << endl;
4279 TString analysisFile = fExecutable;
4280 analysisFile.ReplaceAll(".sh", ".root");
4281 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4282 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4283 << analysisFile << "\");" << endl;
4284 out << " if (!mgr) return;" << endl;
4285 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4286 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4287 out << " mgr->PrintStatus();" << endl;
4288 if (AliAnalysisManager::GetAnalysisManager()) {
4289 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4290 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4292 if (TestBit(AliAnalysisGrid::kTest))
4293 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4295 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4298 out << " TTree *tree = NULL;" << endl;
4299 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4300 out << "}" << endl << endl;
4301 if (hasANALYSISalice) {
4302 out <<"//________________________________________________________________________________" << endl;
4303 out << "Bool_t SetupPar(const char *package) {" << endl;
4304 out << "// Compile the package and set it up." << endl;
4305 out << " TString pkgdir = package;" << endl;
4306 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4307 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4308 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4309 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4310 out << " // Check for BUILD.sh and execute" << endl;
4311 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4312 out << " printf(\"*******************************\\n\");" << endl;
4313 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4314 out << " printf(\"*******************************\\n\");" << endl;
4315 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4316 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4317 out << " gSystem->ChangeDirectory(cdir);" << endl;
4318 out << " return kFALSE;" << endl;
4319 out << " }" << endl;
4320 out << " } else {" << endl;
4321 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4322 out << " gSystem->ChangeDirectory(cdir);" << endl;
4323 out << " return kFALSE;" << endl;
4324 out << " }" << endl;
4325 out << " // Check for SETUP.C and execute" << endl;
4326 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4327 out << " printf(\"*******************************\\n\");" << endl;
4328 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4329 out << " printf(\"*******************************\\n\");" << endl;
4330 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4331 out << " } else {" << endl;
4332 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4333 out << " gSystem->ChangeDirectory(cdir);" << endl;
4334 out << " return kFALSE;" << endl;
4335 out << " }" << endl;
4336 out << " // Restore original workdir" << endl;
4337 out << " gSystem->ChangeDirectory(cdir);" << endl;
4338 out << " return kTRUE;" << endl;
4342 Bool_t copy = kTRUE;
4343 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4346 TString workdir = gGrid->GetHomeDirectory();
4347 workdir += fGridWorkingDir;
4348 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4349 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4350 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4351 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4352 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4356 //______________________________________________________________________________
4357 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4359 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4360 // Note that for loading the compiled library. The current directory should have precedence in
4362 TString pkgdir = package;
4363 pkgdir.ReplaceAll(".par","");
4364 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4365 TString cdir = gSystem->WorkingDirectory();
4366 gSystem->ChangeDirectory(pkgdir);
4367 // Check for BUILD.sh and execute
4368 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4369 printf("**************************************************\n");
4370 printf("*** Building PAR archive %s\n", package);
4371 printf("**************************************************\n");
4372 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4373 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4374 gSystem->ChangeDirectory(cdir);
4378 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4379 gSystem->ChangeDirectory(cdir);
4382 // Check for SETUP.C and execute
4383 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4384 printf("**************************************************\n");
4385 printf("*** Setup PAR archive %s\n", package);
4386 printf("**************************************************\n");
4387 gROOT->Macro("PROOF-INF/SETUP.C");
4388 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4390 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4391 gSystem->ChangeDirectory(cdir);
4394 // Restore original workdir
4395 gSystem->ChangeDirectory(cdir);
4399 //______________________________________________________________________________
4400 void AliAnalysisAlien::WriteExecutable()
4402 // Generate the alien executable script.
4403 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4405 out.open(fExecutable.Data(), ios::out);
4407 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4410 out << "#!/bin/bash" << endl;
4411 // Make sure we can properly compile par files
4412 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4413 out << "echo \"=========================================\"" << endl;
4414 out << "echo \"############## PATH : ##############\"" << endl;
4415 out << "echo $PATH" << endl;
4416 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4417 out << "echo $LD_LIBRARY_PATH" << endl;
4418 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4419 out << "echo $ROOTSYS" << endl;
4420 out << "echo \"############## which root : ##############\"" << endl;
4421 out << "which root" << endl;
4422 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4423 out << "echo $ALICE_ROOT" << endl;
4424 out << "echo \"############## which aliroot : ##############\"" << endl;
4425 out << "which aliroot" << endl;
4426 out << "echo \"############## system limits : ##############\"" << endl;
4427 out << "ulimit -a" << endl;
4428 out << "echo \"############## memory : ##############\"" << endl;
4429 out << "free -m" << endl;
4430 out << "echo \"=========================================\"" << endl << endl;
4431 out << fExecutableCommand << " ";
4432 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4433 out << "RET=$?" << endl;
4434 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4435 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4436 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4437 out << " let sig=\"$RET - 128\""<<endl;
4438 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4439 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4440 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4441 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4442 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4443 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4445 out << " exit $RET"<< endl;
4446 out << "fi" << endl << endl ;
4447 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4448 out << "echo \"############## memory after: ##############\"" << endl;
4449 out << "free -m" << endl;
4451 Bool_t copy = kTRUE;
4452 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4455 TString workdir = gGrid->GetHomeDirectory();
4456 TString bindir = Form("%s/bin", workdir.Data());
4457 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4458 workdir += fGridWorkingDir;
4459 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4460 if (FileExists(executable)) gGrid->Rm(executable);
4461 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4462 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4463 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4464 executable.Data())) Fatal("","Terminating");
4468 //______________________________________________________________________________
4469 void AliAnalysisAlien::WriteMergeExecutable()
4471 // Generate the alien executable script for the merging job.
4472 if (!fMergeViaJDL) return;
4473 TString mergeExec = fExecutable;
4474 mergeExec.ReplaceAll(".sh", "_merge.sh");
4475 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4477 out.open(mergeExec.Data(), ios::out);
4479 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4482 out << "#!/bin/bash" << endl;
4483 // Make sure we can properly compile par files
4484 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4485 out << "echo \"=========================================\"" << endl;
4486 out << "echo \"############## PATH : ##############\"" << endl;
4487 out << "echo $PATH" << endl;
4488 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4489 out << "echo $LD_LIBRARY_PATH" << endl;
4490 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4491 out << "echo $ROOTSYS" << endl;
4492 out << "echo \"############## which root : ##############\"" << endl;
4493 out << "which root" << endl;
4494 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4495 out << "echo $ALICE_ROOT" << endl;
4496 out << "echo \"############## which aliroot : ##############\"" << endl;
4497 out << "which aliroot" << endl;
4498 out << "echo \"############## system limits : ##############\"" << endl;
4499 out << "ulimit -a" << endl;
4500 out << "echo \"############## memory : ##############\"" << endl;
4501 out << "free -m" << endl;
4502 out << "echo \"=========================================\"" << endl << endl;
4503 TString mergeMacro = fExecutable;
4504 mergeMacro.ReplaceAll(".sh", "_merge.C");
4505 if (IsOneStageMerging())
4506 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4508 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4509 out << fExecutableCommand << " " << "$ARG" << endl;
4510 out << "RET=$?" << endl;
4511 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4512 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4513 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4514 out << " let sig=\"$RET - 128\""<<endl;
4515 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4516 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4517 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4518 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4519 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4520 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4522 out << " exit $RET"<< endl;
4523 out << "fi" << endl << endl ;
4524 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4525 out << "echo \"############## memory after: ##############\"" << endl;
4526 out << "free -m" << endl;
4528 Bool_t copy = kTRUE;
4529 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4532 TString workdir = gGrid->GetHomeDirectory();
4533 TString bindir = Form("%s/bin", workdir.Data());
4534 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4535 workdir += fGridWorkingDir;
4536 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4537 if (FileExists(executable)) gGrid->Rm(executable);
4538 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4539 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4540 if (!copyLocal2Alien("WriteMergeExecutable",
4541 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4545 //______________________________________________________________________________
4546 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4548 // Write the production file to be submitted by LPM manager. The format is:
4549 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4550 // Next lines: full_path_to_dataset XXX (XXX is a string)
4551 // To submit, one has to: submit jdl XXX for all lines
4553 out.open(filename, ios::out);
4555 Error("WriteProductionFile", "Bad file name: %s", filename);
4559 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4560 workdir = gGrid->GetHomeDirectory();
4561 workdir += fGridWorkingDir;
4562 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4563 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4564 out << locjdl << " " << njobspermaster << endl;
4565 Int_t nmasterjobs = fInputFiles->GetEntries();
4566 for (Int_t i=0; i<nmasterjobs; i++) {
4567 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4568 runOutDir.ReplaceAll(".xml", "");
4570 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4572 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4575 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4576 if (FileExists(filename)) gGrid->Rm(filename);
4577 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4578 if (!copyLocal2Alien("WriteProductionFile", filename,
4579 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4583 //______________________________________________________________________________
4584 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4586 // Generate the alien validation script.
4587 // Generate the validation script
4589 if (fValidationScript.IsNull()) {
4590 fValidationScript = fExecutable;
4591 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4593 TString validationScript = fValidationScript;
4594 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4596 Error("WriteValidationScript", "Alien connection required");
4599 if (!fTerminateFiles.IsNull()) {
4600 fTerminateFiles.Strip();
4601 fTerminateFiles.ReplaceAll(" ",",");
4603 TString outStream = "";
4604 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4605 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4607 out.open(validationScript, ios::out);
4608 out << "#!/bin/bash" << endl;
4609 out << "##################################################" << endl;
4610 out << "validateout=`dirname $0`" << endl;
4611 out << "validatetime=`date`" << endl;
4612 out << "validated=\"0\";" << endl;
4613 out << "error=0" << endl;
4614 out << "if [ -z $validateout ]" << endl;
4615 out << "then" << endl;
4616 out << " validateout=\".\"" << endl;
4617 out << "fi" << endl << endl;
4618 out << "cd $validateout;" << endl;
4619 out << "validateworkdir=`pwd`;" << endl << endl;
4620 out << "echo \"*******************************************************\"" << outStream << endl;
4621 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4623 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4624 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4625 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4626 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4627 out << "ls -la ./" << outStream << endl;
4628 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4629 out << "##################################################" << endl;
4632 out << "if [ ! -f stderr ] ; then" << endl;
4633 out << " error=1" << endl;
4634 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4635 out << " echo \"Error = $error\" " << outStream << endl;
4636 out << "fi" << endl;
4638 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4639 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4640 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4641 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4644 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4645 out << " error=1" << endl;
4646 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4647 out << " echo \"$parArch\" " << outStream << endl;
4648 out << " echo \"Error = $error\" " << outStream << endl;
4649 out << "fi" << endl;
4651 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4652 out << " error=1" << endl;
4653 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4654 out << " echo \"$segViol\" " << outStream << endl;
4655 out << " echo \"Error = $error\" " << outStream << endl;
4656 out << "fi" << endl;
4658 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4659 out << " error=1" << endl;
4660 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4661 out << " echo \"$segFault\" " << outStream << endl;
4662 out << " echo \"Error = $error\" " << outStream << endl;
4663 out << "fi" << endl;
4665 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4666 out << " error=1" << endl;
4667 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4668 out << " echo \"$glibcErr\" " << outStream << endl;
4669 out << " echo \"Error = $error\" " << outStream << endl;
4670 out << "fi" << endl;
4672 // Part dedicated to the specific analyses running into the train
4674 TString outputFiles = fOutputFiles;
4675 if (merge && !fTerminateFiles.IsNull()) {
4677 outputFiles += fTerminateFiles;
4679 TObjArray *arr = outputFiles.Tokenize(",");
4682 while (!merge && (os=(TObjString*)next1())) {
4683 // No need to validate outputs produced by merging since the merging macro does this
4684 outputFile = os->GetString();
4685 Int_t index = outputFile.Index("@");
4686 if (index > 0) outputFile.Remove(index);
4687 if (fTerminateFiles.Contains(outputFile)) continue;
4688 if (outputFile.Contains("*")) continue;
4689 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4690 out << " error=1" << endl;
4691 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4692 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4693 out << "fi" << endl;
4696 out << "if ! [ -f outputs_valid ] ; then" << endl;
4697 out << " error=1" << endl;
4698 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4699 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4700 out << "fi" << endl;
4702 out << "if [ $error = 0 ] ; then" << endl;
4703 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4704 if (!IsKeepLogs()) {
4705 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4707 out << " rm -f std*" << endl;
4709 out << "fi" << endl;
4711 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4712 out << "echo \"*******************************************************\"" << outStream << endl;
4713 out << "cd -" << endl;
4714 out << "exit $error" << endl;
4716 Bool_t copy = kTRUE;
4717 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4720 TString workdir = gGrid->GetHomeDirectory();
4721 workdir += fGridWorkingDir;
4722 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4723 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4724 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4725 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4726 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");