1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "AliAnalysisAlien.h"
25 #include "Riostream.h"
33 #include "TFileCollection.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
39 #include "TGridResult.h"
40 #include "TGridCollection.h"
42 #include "TGridJobStatusList.h"
43 #include "TGridJobStatus.h"
44 #include "TFileMerger.h"
45 #include "AliAnalysisManager.h"
46 #include "AliAnalysisTaskCfg.h"
47 #include "AliVEventHandler.h"
48 #include "AliAnalysisDataContainer.h"
49 #include "AliMultiInputEventHandler.h"
51 ClassImp(AliAnalysisAlien)
57 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
59 TString sl(Form("file:%s", loc));
60 TString sr(Form("alien://%s", rem));
61 Bool_t ret = TFile::Cp(sl, sr);
63 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
69 //______________________________________________________________________________
70 AliAnalysisAlien::AliAnalysisAlien()
76 fSplitMaxInputFileNumber(0),
78 fMasterResubmitThreshold(0),
91 fNproofWorkersPerSlave(0),
101 fAdditionalRootLibs(),
130 fRootVersionForProof(),
142 //______________________________________________________________________________
143 AliAnalysisAlien::AliAnalysisAlien(const char *name)
144 :AliAnalysisGrid(name),
149 fSplitMaxInputFileNumber(0),
151 fMasterResubmitThreshold(0),
164 fNproofWorkersPerSlave(0),
168 fExecutableCommand(),
174 fAdditionalRootLibs(),
203 fRootVersionForProof(),
215 //______________________________________________________________________________
216 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
217 :AliAnalysisGrid(other),
220 fPrice(other.fPrice),
222 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
223 fMaxInitFailed(other.fMaxInitFailed),
224 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
225 fNtestFiles(other.fNtestFiles),
226 fNrunsPerMaster(other.fNrunsPerMaster),
227 fMaxMergeFiles(other.fMaxMergeFiles),
228 fMaxMergeStages(other.fMaxMergeStages),
229 fNsubmitted(other.fNsubmitted),
230 fProductionMode(other.fProductionMode),
231 fOutputToRunNo(other.fOutputToRunNo),
232 fMergeViaJDL(other.fMergeViaJDL),
233 fFastReadOption(other.fFastReadOption),
234 fOverwriteMode(other.fOverwriteMode),
235 fNreplicas(other.fNreplicas),
236 fNproofWorkers(other.fNproofWorkers),
237 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
238 fProofReset(other.fProofReset),
239 fRunNumbers(other.fRunNumbers),
240 fExecutable(other.fExecutable),
241 fExecutableCommand(other.fExecutableCommand),
242 fArguments(other.fArguments),
243 fExecutableArgs(other.fExecutableArgs),
244 fAnalysisMacro(other.fAnalysisMacro),
245 fAnalysisSource(other.fAnalysisSource),
246 fValidationScript(other.fValidationScript),
247 fAdditionalRootLibs(other.fAdditionalRootLibs),
248 fAdditionalLibs(other.fAdditionalLibs),
249 fSplitMode(other.fSplitMode),
250 fAPIVersion(other.fAPIVersion),
251 fROOTVersion(other.fROOTVersion),
252 fAliROOTVersion(other.fAliROOTVersion),
253 fExternalPackages(other.fExternalPackages),
255 fGridWorkingDir(other.fGridWorkingDir),
256 fGridDataDir(other.fGridDataDir),
257 fDataPattern(other.fDataPattern),
258 fGridOutputDir(other.fGridOutputDir),
259 fOutputArchive(other.fOutputArchive),
260 fOutputFiles(other.fOutputFiles),
261 fInputFormat(other.fInputFormat),
262 fDatasetName(other.fDatasetName),
263 fJDLName(other.fJDLName),
264 fTerminateFiles(other.fTerminateFiles),
265 fMergeExcludes(other.fMergeExcludes),
266 fRegisterExcludes(other.fRegisterExcludes),
267 fIncludePath(other.fIncludePath),
268 fCloseSE(other.fCloseSE),
269 fFriendChainName(other.fFriendChainName),
270 fJobTag(other.fJobTag),
271 fOutputSingle(other.fOutputSingle),
272 fRunPrefix(other.fRunPrefix),
273 fProofCluster(other.fProofCluster),
274 fProofDataSet(other.fProofDataSet),
275 fFileForTestMode(other.fFileForTestMode),
276 fRootVersionForProof(other.fRootVersionForProof),
277 fAliRootMode(other.fAliRootMode),
278 fMergeDirName(other.fMergeDirName),
285 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
286 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
287 fRunRange[0] = other.fRunRange[0];
288 fRunRange[1] = other.fRunRange[1];
289 if (other.fInputFiles) {
290 fInputFiles = new TObjArray();
291 TIter next(other.fInputFiles);
293 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
294 fInputFiles->SetOwner();
296 if (other.fPackages) {
297 fPackages = new TObjArray();
298 TIter next(other.fPackages);
300 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
301 fPackages->SetOwner();
303 if (other.fModules) {
304 fModules = new TObjArray();
305 fModules->SetOwner();
306 TIter next(other.fModules);
307 AliAnalysisTaskCfg *mod, *crt;
308 while ((crt=(AliAnalysisTaskCfg*)next())) {
309 mod = new AliAnalysisTaskCfg(*crt);
315 //______________________________________________________________________________
316 AliAnalysisAlien::~AliAnalysisAlien()
324 fProofParam.DeleteAll();
327 //______________________________________________________________________________
328 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
331 if (this != &other) {
332 AliAnalysisGrid::operator=(other);
333 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
334 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
335 fPrice = other.fPrice;
337 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
338 fMaxInitFailed = other.fMaxInitFailed;
339 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
340 fNtestFiles = other.fNtestFiles;
341 fNrunsPerMaster = other.fNrunsPerMaster;
342 fMaxMergeFiles = other.fMaxMergeFiles;
343 fMaxMergeStages = other.fMaxMergeStages;
344 fNsubmitted = other.fNsubmitted;
345 fProductionMode = other.fProductionMode;
346 fOutputToRunNo = other.fOutputToRunNo;
347 fMergeViaJDL = other.fMergeViaJDL;
348 fFastReadOption = other.fFastReadOption;
349 fOverwriteMode = other.fOverwriteMode;
350 fNreplicas = other.fNreplicas;
351 fNproofWorkers = other.fNproofWorkers;
352 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
353 fProofReset = other.fProofReset;
354 fRunNumbers = other.fRunNumbers;
355 fExecutable = other.fExecutable;
356 fExecutableCommand = other.fExecutableCommand;
357 fArguments = other.fArguments;
358 fExecutableArgs = other.fExecutableArgs;
359 fAnalysisMacro = other.fAnalysisMacro;
360 fAnalysisSource = other.fAnalysisSource;
361 fValidationScript = other.fValidationScript;
362 fAdditionalRootLibs = other.fAdditionalRootLibs;
363 fAdditionalLibs = other.fAdditionalLibs;
364 fSplitMode = other.fSplitMode;
365 fAPIVersion = other.fAPIVersion;
366 fROOTVersion = other.fROOTVersion;
367 fAliROOTVersion = other.fAliROOTVersion;
368 fExternalPackages = other.fExternalPackages;
370 fGridWorkingDir = other.fGridWorkingDir;
371 fGridDataDir = other.fGridDataDir;
372 fDataPattern = other.fDataPattern;
373 fGridOutputDir = other.fGridOutputDir;
374 fOutputArchive = other.fOutputArchive;
375 fOutputFiles = other.fOutputFiles;
376 fInputFormat = other.fInputFormat;
377 fDatasetName = other.fDatasetName;
378 fJDLName = other.fJDLName;
379 fTerminateFiles = other.fTerminateFiles;
380 fMergeExcludes = other.fMergeExcludes;
381 fRegisterExcludes = other.fRegisterExcludes;
382 fIncludePath = other.fIncludePath;
383 fCloseSE = other.fCloseSE;
384 fFriendChainName = other.fFriendChainName;
385 fJobTag = other.fJobTag;
386 fOutputSingle = other.fOutputSingle;
387 fRunPrefix = other.fRunPrefix;
388 fProofCluster = other.fProofCluster;
389 fProofDataSet = other.fProofDataSet;
390 fFileForTestMode = other.fFileForTestMode;
391 fRootVersionForProof = other.fRootVersionForProof;
392 fAliRootMode = other.fAliRootMode;
393 fMergeDirName = other.fMergeDirName;
394 if (other.fInputFiles) {
395 fInputFiles = new TObjArray();
396 TIter next(other.fInputFiles);
398 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
399 fInputFiles->SetOwner();
401 if (other.fPackages) {
402 fPackages = new TObjArray();
403 TIter next(other.fPackages);
405 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
406 fPackages->SetOwner();
408 if (other.fModules) {
409 fModules = new TObjArray();
410 fModules->SetOwner();
411 TIter next(other.fModules);
412 AliAnalysisTaskCfg *mod, *crt;
413 while ((crt=(AliAnalysisTaskCfg*)next())) {
414 mod = new AliAnalysisTaskCfg(*crt);
422 //______________________________________________________________________________
423 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
425 // Add a single additional library to be loaded. Extension must be present.
427 if (!lib.Contains(".")) {
428 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
431 if (fAdditionalLibs.Contains(name)) {
432 Warning("AddAdditionalLibrary", "Library %s already added.", name);
435 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
436 fAdditionalLibs += lib;
439 //______________________________________________________________________________
440 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
442 // Adding a module. Checks if already existing. Becomes owned by this.
444 if (GetModule(module->GetName())) {
445 Error("AddModule", "A module having the same name %s already added", module->GetName());
449 fModules = new TObjArray();
450 fModules->SetOwner();
452 fModules->Add(module);
455 //______________________________________________________________________________
456 void AliAnalysisAlien::AddModules(TObjArray *list)
458 // Adding a list of modules. Checks if already existing. Becomes owned by this.
460 AliAnalysisTaskCfg *module;
461 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
464 //______________________________________________________________________________
465 Bool_t AliAnalysisAlien::CheckDependencies()
467 // Check if all dependencies are satisfied. Reorder modules if needed.
468 Int_t nmodules = GetNmodules();
470 Warning("CheckDependencies", "No modules added yet to check their dependencies");
473 AliAnalysisTaskCfg *mod = 0;
474 AliAnalysisTaskCfg *dep = 0;
477 for (i=0; i<nmodules; i++) {
478 mod = (AliAnalysisTaskCfg*) fModules->At(i);
479 Int_t ndeps = mod->GetNdeps();
481 for (j=0; j<ndeps; j++) {
482 depname = mod->GetDependency(j);
483 dep = GetModule(depname);
485 Error("CheckDependencies","Dependency %s not added for module %s",
486 depname.Data(), mod->GetName());
489 if (dep->NeedsDependency(mod->GetName())) {
490 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
491 mod->GetName(), dep->GetName());
494 Int_t idep = fModules->IndexOf(dep);
495 // The dependency task must come first
497 // Remove at idep and move all objects below up one slot
498 // down to index i included.
499 fModules->RemoveAt(idep);
500 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
501 fModules->AddAt(dep, i++);
503 //Redo from istart if dependencies were inserted
504 if (i>istart) i=istart-1;
510 //______________________________________________________________________________
511 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
513 // Create the analysis manager and optionally execute the macro in filename.
514 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
516 mgr = new AliAnalysisManager(name);
517 mgr->SetGridHandler((AliAnalysisGrid*)this);
518 if (strlen(filename)) {
519 TString line = gSystem->ExpandPathName(filename);
521 gROOT->ProcessLine(line.Data());
526 //______________________________________________________________________________
527 Int_t AliAnalysisAlien::GetNmodules() const
529 // Get number of modules.
530 if (!fModules) return 0;
531 return fModules->GetEntries();
534 //______________________________________________________________________________
535 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
537 // Get a module by name.
538 if (!fModules) return 0;
539 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
542 //______________________________________________________________________________
543 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
545 // Load a given module.
546 if (mod->IsLoaded()) return kTRUE;
547 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
549 Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
552 Int_t ndeps = mod->GetNdeps();
554 for (Int_t j=0; j<ndeps; j++) {
555 depname = mod->GetDependency(j);
556 AliAnalysisTaskCfg *dep = GetModule(depname);
558 Error("LoadModule","Dependency %s not existing for module %s",
559 depname.Data(), mod->GetName());
562 if (!LoadModule(dep)) {
563 Error("LoadModule","Dependency %s for module %s could not be loaded",
564 depname.Data(), mod->GetName());
568 // Load libraries for the module
569 if (!mod->CheckLoadLibraries()) {
570 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
573 // Check if a custom file name was requested
574 if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
576 // Check if a custom terminate file name was requested
577 if (strlen(mod->GetTerminateFileName())) {
578 if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
579 fTerminateFiles += mod->GetTerminateFileName();
583 if (mod->ExecuteMacro()<0) {
584 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
585 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
588 // Configure dependencies
589 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
590 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
591 mod->GetConfigMacro()->GetTitle(), mod->GetName());
594 // Adjust extra libraries
595 Int_t nlibs = mod->GetNlibs();
597 for (Int_t i=0; i<nlibs; i++) {
598 lib = mod->GetLibrary(i);
599 if (fAdditionalLibs.Contains(lib)) continue;
600 lib = Form("lib%s.so", lib.Data());
601 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
602 fAdditionalLibs += lib;
607 //______________________________________________________________________________
608 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
610 // Generate the full train.
611 fAdditionalLibs = "";
612 if (!LoadModules()) return kFALSE;
613 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
614 if (!mgr->InitAnalysis()) return kFALSE;
617 Int_t productionMode = fProductionMode;
619 TString macro = fAnalysisMacro;
620 TString executable = fExecutable;
621 TString validation = fValidationScript;
622 TString execCommand = fExecutableCommand;
623 SetAnalysisMacro(Form("%s.C", name));
624 SetExecutable(Form("%s.sh", name));
625 // SetExecutableCommand("aliroot -b -q ");
626 SetValidationScript(Form("%s_validation.sh", name));
628 SetProductionMode(productionMode);
629 fAnalysisMacro = macro;
630 fExecutable = executable;
631 fExecutableCommand = execCommand;
632 fValidationScript = validation;
636 //______________________________________________________________________________
637 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
639 // Generate test macros for a single module or for the full train.
640 fAdditionalLibs = "";
641 if (strlen(modname)) {
642 if (!CheckDependencies()) return kFALSE;
643 AliAnalysisTaskCfg *mod = GetModule(modname);
645 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
648 if (!LoadModule(mod)) return kFALSE;
649 } else if (!LoadModules()) return kFALSE;
650 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
651 if (!mgr->InitAnalysis()) return kFALSE;
655 Int_t productionMode = fProductionMode;
657 TString macro = fAnalysisMacro;
658 TString executable = fExecutable;
659 TString validation = fValidationScript;
660 TString execCommand = fExecutableCommand;
661 SetAnalysisMacro(Form("%s.C", name));
662 SetExecutable(Form("%s.sh", name));
663 // SetExecutableCommand("aliroot -b -q ");
664 SetValidationScript(Form("%s_validation.sh", name));
666 WriteAnalysisMacro();
668 WriteValidationScript();
669 SetLocalTest(kFALSE);
670 SetProductionMode(productionMode);
671 fAnalysisMacro = macro;
672 fExecutable = executable;
673 fExecutableCommand = execCommand;
674 fValidationScript = validation;
678 //______________________________________________________________________________
679 Bool_t AliAnalysisAlien::LoadModules()
681 // Load all modules by executing the AddTask macros. Checks first the dependencies.
682 fAdditionalLibs = "";
683 Int_t nmodules = GetNmodules();
685 Warning("LoadModules", "No module to be loaded");
688 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
690 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
693 if (!CheckDependencies()) return kFALSE;
694 nmodules = GetNmodules();
695 AliAnalysisTaskCfg *mod;
696 for (Int_t imod=0; imod<nmodules; imod++) {
697 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
698 if (!LoadModule(mod)) return kFALSE;
703 //______________________________________________________________________________
704 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
706 // Set the run number format. Can be a prefix or a format like "%09d"
708 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
711 //______________________________________________________________________________
712 void AliAnalysisAlien::AddIncludePath(const char *path)
714 // Add include path in the remote analysis macro.
716 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
717 else fIncludePath += Form("-I%s ", path);
720 //______________________________________________________________________________
721 void AliAnalysisAlien::AddRunNumber(Int_t run)
723 // Add a run number to the list of runs to be processed.
724 if (fRunNumbers.Length()) fRunNumbers += " ";
725 fRunNumbers += Form(fRunPrefix.Data(), run);
728 //______________________________________________________________________________
729 void AliAnalysisAlien::AddRunList(const char* runList)
731 // Add several runs into the list of runs; they are expected to be separated by a blank character.
732 TString sList = runList;
733 TObjArray *list = sList.Tokenize(" ");
734 Int_t n = list->GetEntries();
735 for (Int_t i = 0; i < n; i++) {
736 TObjString *os = (TObjString*)list->At(i);
737 AddRunNumber(os->GetString().Atoi());
742 //______________________________________________________________________________
743 void AliAnalysisAlien::AddRunNumber(const char* run)
745 // Add a run number to the list of runs to be processed.
748 TObjArray *arr = runs.Tokenize(" ");
751 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
752 while ((os=(TObjString*)next())){
753 if (fRunNumbers.Length()) fRunNumbers += " ";
754 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
759 //______________________________________________________________________________
760 void AliAnalysisAlien::AddDataFile(const char *lfn)
762 // Adds a data file to the input to be analysed. The file should be a valid LFN
763 // or point to an existing file in the alien workdir.
764 if (!fInputFiles) fInputFiles = new TObjArray();
765 fInputFiles->Add(new TObjString(lfn));
768 //______________________________________________________________________________
769 void AliAnalysisAlien::AddExternalPackage(const char *package)
771 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
772 if (fExternalPackages) fExternalPackages += " ";
773 fExternalPackages += package;
776 //______________________________________________________________________________
777 Bool_t AliAnalysisAlien::Connect()
779 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
780 if (gGrid && gGrid->IsConnected()) return kTRUE;
781 if (fProductionMode) return kTRUE;
783 Info("Connect", "Trying to connect to AliEn ...");
784 TGrid::Connect("alien://");
786 if (!gGrid || !gGrid->IsConnected()) {
787 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
790 fUser = gGrid->GetUser();
791 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
795 //______________________________________________________________________________
796 void AliAnalysisAlien::CdWork()
798 // Check validity of alien workspace. Create directory if possible.
800 Error("CdWork", "Alien connection required");
803 TString homedir = gGrid->GetHomeDirectory();
804 TString workdir = homedir + fGridWorkingDir;
805 if (DirectoryExists(workdir)) {
809 // Work directory not existing - create it
811 if (gGrid->Mkdir(workdir, "-p")) {
812 gGrid->Cd(fGridWorkingDir);
813 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
815 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
816 workdir.Data(), homedir.Data());
817 fGridWorkingDir = "";
821 //______________________________________________________________________________
822 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
824 // Check if file copying is possible.
825 if (fProductionMode) return kTRUE;
826 TString salienpath(alienpath);
827 if (salienpath.Contains(" ")) {
828 Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
832 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
835 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
836 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
837 // Check if alien_CLOSE_SE is defined
838 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
839 if (!closeSE.IsNull()) {
840 Info("CheckFileCopy", "Your current close storage is pointing to: \
841 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
843 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
845 // Check if grid directory exists.
846 if (!DirectoryExists(alienpath)) {
847 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
850 TString stest = "plugin_test_copy";
851 TFile f(stest, "RECREATE");
852 // User may not have write permissions to current directory
854 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
855 gSystem->WorkingDirectory());
859 if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
860 if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
861 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
862 \n# 1. Make sure you have write permissions there. If this is the case: \
863 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
864 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
865 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
866 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
867 gSystem->Unlink(stest.Data());
870 gSystem->Unlink(stest.Data());
871 gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
872 Info("CheckFileCopy", "### ...SUCCESS ###");
876 //______________________________________________________________________________
877 Bool_t AliAnalysisAlien::CheckInputData()
879 // Check validity of input data. If necessary, create xml files.
880 if (fProductionMode) return kTRUE;
881 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
882 if (!fGridDataDir.Length()) {
883 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
887 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
890 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
891 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
892 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
895 // Process declared files
896 Bool_t isCollection = kFALSE;
897 Bool_t isXml = kFALSE;
898 Bool_t useTags = kFALSE;
899 Bool_t checked = kFALSE;
900 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
902 TString workdir = gGrid->GetHomeDirectory();
903 workdir += fGridWorkingDir;
906 TIter next(fInputFiles);
907 while ((objstr=(TObjString*)next())) {
910 file += objstr->GetString();
911 // Store full lfn path
912 if (FileExists(file)) objstr->SetString(file);
914 file = objstr->GetName();
915 if (!FileExists(objstr->GetName())) {
916 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
917 objstr->GetName(), workdir.Data());
921 Bool_t iscoll, isxml, usetags;
922 CheckDataType(file, iscoll, isxml, usetags);
925 isCollection = iscoll;
928 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
930 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
931 Error("CheckInputData", "Some conflict was found in the types of inputs");
937 // Process requested run numbers
938 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
939 // Check validity of alien data directory
940 if (!fGridDataDir.Length()) {
941 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
944 if (!DirectoryExists(fGridDataDir)) {
945 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
949 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
953 if (checked && !isXml) {
954 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
957 // Check validity of run number(s)
962 TString schunk, schunk2;
966 useTags = fDataPattern.Contains("tag");
967 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
969 if (useTags != fDataPattern.Contains("tag")) {
970 Error("CheckInputData", "Cannot mix input files using/not using tags");
973 if (fRunNumbers.Length()) {
974 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
975 arr = fRunNumbers.Tokenize(" ");
977 while ((os=(TObjString*)next())) {
978 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
979 if (!DirectoryExists(path)) {
980 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
983 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
984 TString msg = "\n##### file: ";
986 msg += " type: xml_collection;";
987 if (useTags) msg += " using_tags: Yes";
988 else msg += " using_tags: No";
989 Info("CheckDataType", "%s", msg.Data());
990 if (fNrunsPerMaster<2) {
991 AddDataFile(Form("%s.xml", os->GetString().Data()));
994 if (((nruns-1)%fNrunsPerMaster) == 0) {
995 schunk = os->GetString();
997 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
998 schunk += Form("_%s.xml", os->GetString().Data());
1004 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1005 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1006 format = Form("%%s/%s ", fRunPrefix.Data());
1007 path = Form(format.Data(), fGridDataDir.Data(), irun);
1008 if (!DirectoryExists(path)) {
1011 format = Form("%%s/%s.xml", fRunPrefix.Data());
1012 path = Form(format.Data(), workdir.Data(),irun);
1013 TString msg = "\n##### file: ";
1015 msg += " type: xml_collection;";
1016 if (useTags) msg += " using_tags: Yes";
1017 else msg += " using_tags: No";
1018 Info("CheckDataType", "%s", msg.Data());
1019 if (fNrunsPerMaster<2) {
1020 format = Form("%s.xml", fRunPrefix.Data());
1021 AddDataFile(Form(format.Data(),irun));
1024 if (((nruns-1)%fNrunsPerMaster) == 0) {
1025 schunk = Form(fRunPrefix.Data(),irun);
1027 format = Form("_%s.xml", fRunPrefix.Data());
1028 schunk2 = Form(format.Data(), irun);
1029 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1031 AddDataFile(schunk);
1036 AddDataFile(schunk);
1042 //______________________________________________________________________________
1043 Bool_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1045 // Copy data from the given grid directory according a pattern and make a local
1047 // archivefile (optional) results in that the archive containing the file <pattern> is copied. archivefile can contain a list of files (semicolon-separated) which are all copied
1049 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1052 if (!DirectoryExists(griddir)) {
1053 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1056 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1057 printf("Running command: %s\n", command.Data());
1058 TGridResult *res = gGrid->Command(command);
1059 Int_t nfound = res->GetEntries();
1061 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1064 printf("... found %d files. Copying locally ...\n", nfound);
1067 TObjArray* additionalArchives = 0;
1068 if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1069 additionalArchives = TString(archivefile).Tokenize(";");
1070 archivefile = additionalArchives->At(0)->GetName();
1071 additionalArchives->RemoveAt(0);
1072 additionalArchives->Compress();
1075 // Copy files locally
1077 out.open(output, ios::out);
1079 TString turl, dirname, filename, temp;
1080 TString cdir = gSystem->WorkingDirectory();
1081 gSystem->MakeDirectory(outputdir);
1082 gSystem->ChangeDirectory(outputdir);
1083 for (Int_t i=0; i<nfound; i++) {
1084 map = (TMap*)res->At(i);
1085 turl = map->GetValue("turl")->GetName();
1086 filename = gSystem->BaseName(turl.Data());
1087 dirname = gSystem->DirName(turl.Data());
1088 dirname = gSystem->BaseName(dirname.Data());
1089 gSystem->MakeDirectory(dirname);
1091 TString source(turl);
1092 TString targetFileName(filename);
1094 if (strlen(archivefile) > 0) {
1095 // TODO here the archive in which the file resides should be determined
1096 // however whereis returns only a guid, and guid2lfn does not work
1097 // Therefore we use the one provided as argument for now
1098 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1099 targetFileName = archivefile;
1101 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1102 Bool_t success = kTRUE;
1103 if (additionalArchives)
1104 for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++)
1107 target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1108 gSystem->MakeDirectory(gSystem->DirName(target));
1109 success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1113 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1114 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1118 gSystem->ChangeDirectory(cdir);
1120 if (additionalArchives)
1121 delete additionalArchives;
1125 //______________________________________________________________________________
1126 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1128 // Create dataset for the grid data directory + run number.
1129 const Int_t gMaxEntries = 15000;
1130 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1132 Error("CreateDataset", "Cannot create dataset with no grid connection");
1137 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1138 TString workdir = gGrid->GetHomeDirectory();
1139 workdir += fGridWorkingDir;
1141 // Compose the 'find' command arguments
1144 TString options = "-x collection ";
1145 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1146 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1147 TString conditions = "";
1154 TString schunk, schunk2;
1155 TGridCollection *cbase=0, *cadd=0;
1156 if (!fRunNumbers.Length() && !fRunRange[0]) {
1157 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1158 // Make a single data collection from data directory.
1159 path = fGridDataDir;
1160 if (!DirectoryExists(path)) {
1161 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1165 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1166 else file = Form("%s.xml", gSystem->BaseName(path));
1170 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1172 command += Form("%s -o %d ",options.Data(), nstart);
1176 command += conditions;
1177 printf("command: %s\n", command.Data());
1178 TGridResult *res = gGrid->Command(command);
1179 if (res) delete res;
1180 // Write standard output to file
1181 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1182 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1183 Bool_t nullFile = kFALSE;
1185 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1187 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1189 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1190 gSystem->Exec("rm -f __tmp*");
1198 gSystem->Exec("rm -f __tmp__");
1199 ncount = line.Atoi();
1202 if (ncount == gMaxEntries) {
1203 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1204 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1205 if (!cbase) cbase = cadd;
1213 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1214 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1217 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1218 delete cbase; cbase = 0;
1220 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1222 gSystem->Exec("rm -f __tmp*");
1223 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1227 Bool_t fileExists = FileExists(file);
1228 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1229 // Copy xml file to alien space
1230 if (fileExists) gGrid->Rm(file);
1231 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1232 if (!FileExists(file)) {
1233 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1236 // Update list of files to be processed.
1238 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1242 Bool_t nullResult = kTRUE;
1243 if (fRunNumbers.Length()) {
1244 TObjArray *arr = fRunNumbers.Tokenize(" ");
1247 while ((os=(TObjString*)next())) {
1250 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
1251 if (!DirectoryExists(path)) continue;
1253 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1254 else file = Form("%s.xml", os->GetString().Data());
1255 // If local collection file does not exist, create it via 'find' command.
1259 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1261 command += Form("%s -o %d ",options.Data(), nstart);
1264 command += conditions;
1265 TGridResult *res = gGrid->Command(command);
1266 if (res) delete res;
1267 // Write standard output to file
1268 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1269 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1270 Bool_t nullFile = kFALSE;
1272 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1274 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1276 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1277 gSystem->Exec("rm -f __tmp*");
1278 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1286 gSystem->Exec("rm -f __tmp__");
1287 ncount = line.Atoi();
1289 nullResult = kFALSE;
1291 if (ncount == gMaxEntries) {
1292 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1293 if (fNrunsPerMaster > 1) {
1294 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1295 file.Data(),gMaxEntries);
1298 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1299 if (!cbase) cbase = cadd;
1306 if (cbase && fNrunsPerMaster<2) {
1307 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1308 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1311 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1312 delete cbase; cbase = 0;
1314 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1316 gSystem->Exec("rm -f __tmp*");
1317 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1321 if (TestBit(AliAnalysisGrid::kTest)) break;
1322 // Check if there is one run per master job.
1323 if (fNrunsPerMaster<2) {
1324 if (FileExists(file)) {
1325 if (fOverwriteMode) gGrid->Rm(file);
1327 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1331 // Copy xml file to alien space
1332 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1333 if (!FileExists(file)) {
1334 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1340 if (((nruns-1)%fNrunsPerMaster) == 0) {
1341 schunk = os->GetString();
1342 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1344 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1345 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1349 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1352 schunk += Form("_%s.xml", os->GetString().Data());
1353 if (FileExists(schunk)) {
1354 if (fOverwriteMode) gGrid->Rm(file);
1356 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1360 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1361 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1362 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1363 if (!FileExists(schunk)) {
1364 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1372 Error("CreateDataset", "No valid dataset corresponding to the query!");
1376 // Process a full run range.
1377 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1378 format = Form("%%s/%s ", fRunPrefix.Data());
1381 path = Form(format.Data(), fGridDataDir.Data(), irun);
1382 if (!DirectoryExists(path)) continue;
1384 format = Form("%s.xml", fRunPrefix.Data());
1385 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1386 else file = Form(format.Data(), irun);
1387 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1388 if (fOverwriteMode) gGrid->Rm(file);
1390 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1394 // If local collection file does not exist, create it via 'find' command.
1398 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1400 command += Form("%s -o %d ",options.Data(), nstart);
1403 command += conditions;
1404 TGridResult *res = gGrid->Command(command);
1405 if (res) delete res;
1406 // Write standard output to file
1407 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1408 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1409 Bool_t nullFile = kFALSE;
1411 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1413 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1415 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1416 gSystem->Exec("rm -f __tmp*");
1424 gSystem->Exec("rm -f __tmp__");
1425 ncount = line.Atoi();
1427 nullResult = kFALSE;
1429 if (ncount == gMaxEntries) {
1430 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1431 if (fNrunsPerMaster > 1) {
1432 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1433 file.Data(),gMaxEntries);
1436 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1437 if (!cbase) cbase = cadd;
1444 if (cbase && fNrunsPerMaster<2) {
1445 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1446 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1449 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1450 delete cbase; cbase = 0;
1452 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1454 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1458 if (TestBit(AliAnalysisGrid::kTest)) break;
1459 // Check if there is one run per master job.
1460 if (fNrunsPerMaster<2) {
1461 if (FileExists(file)) {
1462 if (fOverwriteMode) gGrid->Rm(file);
1464 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1468 // Copy xml file to alien space
1469 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1470 if (!FileExists(file)) {
1471 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1476 // Check if the collection for the chunk exist locally.
1477 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1478 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1479 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1482 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1483 if (((nruns-1)%fNrunsPerMaster) == 0) {
1484 schunk = Form(fRunPrefix.Data(), irun);
1485 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1487 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1491 format = Form("%%s_%s.xml", fRunPrefix.Data());
1492 schunk2 = Form(format.Data(), schunk.Data(), irun);
1493 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1497 if (FileExists(schunk)) {
1498 if (fOverwriteMode) gGrid->Rm(schunk);
1500 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1504 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1505 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1506 if (FileExists(schunk)) {
1507 if (fOverwriteMode) gGrid->Rm(schunk);
1509 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1513 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1514 if (!FileExists(schunk)) {
1515 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1521 Error("CreateDataset", "No valid dataset corresponding to the query!");
1528 //______________________________________________________________________________
1529 Bool_t AliAnalysisAlien::CreateJDL()
1531 // Generate a JDL file according to current settings. The name of the file is
1532 // specified by fJDLName.
1533 Bool_t error = kFALSE;
1535 Bool_t copy = kTRUE;
1536 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1537 Bool_t generate = kTRUE;
1538 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1540 Error("CreateJDL", "Alien connection required");
1543 // Check validity of alien workspace
1545 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1546 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1547 workdir += fGridWorkingDir;
1551 Error("CreateJDL()", "Define some input files for your analysis.");
1554 // Compose list of input files
1555 // Check if output files were defined
1556 if (!fOutputFiles.Length()) {
1557 Error("CreateJDL", "You must define at least one output file");
1560 // Check if an output directory was defined and valid
1561 if (!fGridOutputDir.Length()) {
1562 Error("CreateJDL", "You must define AliEn output directory");
1565 if (!fProductionMode) {
1566 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1567 if (!DirectoryExists(fGridOutputDir)) {
1568 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1569 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1571 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1575 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1580 // Exit if any error up to now
1581 if (error) return kFALSE;
1583 if (!fUser.IsNull()) {
1584 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1585 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1587 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1588 TString mergeExec = fExecutable;
1589 mergeExec.ReplaceAll(".sh", "_merge.sh");
1590 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1591 mergeExec.ReplaceAll(".sh", ".C");
1592 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1593 if (!fArguments.IsNull())
1594 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1595 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1597 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1598 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1601 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1602 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1603 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1604 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1606 if (fMaxInitFailed > 0) {
1607 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1608 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1610 if (fSplitMaxInputFileNumber > 0) {
1611 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1612 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1614 if (!IsOneStageMerging()) {
1615 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1616 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1618 if (fSplitMode.Length()) {
1619 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1620 fGridJDL->SetDescription("Split", "We split per SE or file");
1622 fMergingJDL->SetValue("Split", "\"se\"");
1623 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1624 if (!fAliROOTVersion.IsNull()) {
1625 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1626 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1628 if (!fROOTVersion.IsNull()) {
1629 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1630 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1632 if (!fAPIVersion.IsNull()) {
1633 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1634 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1636 if (!fExternalPackages.IsNull()) {
1637 arr = fExternalPackages.Tokenize(" ");
1639 while ((os=(TObjString*)next())) {
1640 TString pkgname = os->GetString();
1641 Int_t index = pkgname.Index("::");
1642 TString pkgversion = pkgname(index+2, pkgname.Length());
1643 pkgname.Remove(index);
1644 fGridJDL->AddToPackages(pkgname, pkgversion);
1645 fMergingJDL->AddToPackages(pkgname, pkgversion);
1649 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1650 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1651 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1652 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1653 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1654 TString analysisFile = fExecutable;
1655 analysisFile.ReplaceAll(".sh", ".root");
1656 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1657 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1658 if (fAdditionalLibs.Length()) {
1659 arr = fAdditionalLibs.Tokenize(" ");
1661 while ((os=(TObjString*)next())) {
1662 if (os->GetString().Contains(".so")) continue;
1663 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1664 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1669 TIter next(fPackages);
1671 while ((obj=next())) {
1672 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1673 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1676 if (fOutputArchive.Length()) {
1677 arr = fOutputArchive.Tokenize(" ");
1679 Bool_t first = kTRUE;
1680 const char *comment = "Files to be archived";
1681 const char *comment1 = comment;
1682 while ((os=(TObjString*)next())) {
1683 if (!first) comment = NULL;
1684 if (!os->GetString().Contains("@") && fCloseSE.Length())
1685 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1687 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1691 // Output archive for the merging jdl
1692 TString outputArchive;
1693 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1694 outputArchive = "log_archive.zip:std*@disk=1 ";
1695 // Add normal output files, extra files + terminate files
1696 TString files = GetListOfFiles("outextter");
1697 // Do not register files in fRegisterExcludes
1698 if (!fRegisterExcludes.IsNull()) {
1699 arr = fRegisterExcludes.Tokenize(" ");
1701 while ((os=(TObjString*)next1())) {
1702 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1703 files.ReplaceAll(os->GetString(),"");
1707 files.ReplaceAll(".root", "*.root");
1708 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1710 TString files = fOutputArchive;
1711 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1712 outputArchive = files;
1714 arr = outputArchive.Tokenize(" ");
1718 while ((os=(TObjString*)next2())) {
1719 if (!first) comment = NULL;
1720 TString currentfile = os->GetString();
1721 if (!currentfile.Contains("@") && fCloseSE.Length())
1722 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1724 fMergingJDL->AddToOutputArchive(currentfile, comment);
1729 arr = fOutputFiles.Tokenize(",");
1731 Bool_t first = kTRUE;
1732 const char *comment = "Files to be saved";
1733 while ((os=(TObjString*)next())) {
1734 // Ignore ouputs in jdl that are also in outputarchive
1735 TString sout = os->GetString();
1736 sout.ReplaceAll("*", "");
1737 sout.ReplaceAll(".root", "");
1738 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1739 if (fOutputArchive.Contains(sout)) continue;
1740 // Ignore fRegisterExcludes
1741 if (fRegisterExcludes.Contains(sout)) continue;
1742 if (!first) comment = NULL;
1743 if (!os->GetString().Contains("@") && fCloseSE.Length())
1744 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1746 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1748 if (fMergeExcludes.Contains(sout)) continue;
1749 if (!os->GetString().Contains("@") && fCloseSE.Length())
1750 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1752 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1755 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1756 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1757 TString validationScript = fValidationScript;
1758 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1759 validationScript.ReplaceAll(".sh", "_merge.sh");
1760 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1761 if (fMasterResubmitThreshold) {
1762 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1763 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1765 // Write a jdl with 2 input parameters: collection name and output dir name.
1768 // Copy jdl to grid workspace
1770 // Check if an output directory was defined and valid
1771 if (!fGridOutputDir.Length()) {
1772 Error("CreateJDL", "You must define AliEn output directory");
1775 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1776 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1777 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1778 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1780 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1786 if (TestBit(AliAnalysisGrid::kSubmit)) {
1787 TString mergeJDLName = fExecutable;
1788 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1789 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1790 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1791 if (fProductionMode) {
1792 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1793 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1795 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1796 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1797 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1798 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1799 Fatal("","Terminating");
1800 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1802 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1803 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1804 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1805 Fatal("","Terminating");
1808 if (fAdditionalLibs.Length()) {
1809 arr = fAdditionalLibs.Tokenize(" ");
1812 while ((os=(TObjString*)next())) {
1813 if (os->GetString().Contains(".so")) continue;
1814 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1815 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1816 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1817 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1818 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1819 Fatal("","Terminating");
1824 TIter next(fPackages);
1826 while ((obj=next())) {
1827 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1828 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1829 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1830 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1831 Form("%s/%s", workdir.Data(), obj->GetName())))
1832 Fatal("","Terminating");
1839 //______________________________________________________________________________
1840 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1842 // Writes one or more JDL's corresponding to findex. If findex is negative,
1843 // all run numbers are considered in one go (jdl). For non-negative indices
1844 // they correspond to the indices in the array fInputFiles.
1845 if (!fInputFiles) return kFALSE;
1848 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1849 workdir += fGridWorkingDir;
1850 TString stageName = "$2";
1851 if (fProductionMode) stageName = "$4";
1852 if (!fMergeDirName.IsNull()) {
1853 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1854 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1856 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1857 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1859 if (fProductionMode) {
1860 TIter next(fInputFiles);
1861 while ((os=next())) {
1862 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1864 if (!fOutputToRunNo)
1865 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1867 fGridJDL->SetOutputDirectory(fGridOutputDir);
1869 if (!fRunNumbers.Length() && !fRunRange[0]) {
1870 // One jdl with no parameters in case input data is specified by name.
1871 TIter next(fInputFiles);
1873 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1874 if (!fOutputSingle.IsNull())
1875 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1877 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1878 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1881 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1882 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1883 if (!fOutputSingle.IsNull()) {
1884 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1885 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1887 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1892 // Generate the JDL as a string
1893 TString sjdl = fGridJDL->Generate();
1894 TString sjdl1 = fMergingJDL->Generate();
1896 if (!fMergeDirName.IsNull()) {
1897 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1898 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1900 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1901 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1903 TString sjdl2 = fMergingJDL->Generate();
1904 Int_t index, index1;
1905 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1906 sjdl.ReplaceAll("(member", "\n (member");
1907 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1908 sjdl.ReplaceAll("{", "{\n ");
1909 sjdl.ReplaceAll("};", "\n};");
1910 sjdl.ReplaceAll("{\n \n", "{\n");
1911 sjdl.ReplaceAll("\n\n", "\n");
1912 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1913 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1914 sjdl1.ReplaceAll("(member", "\n (member");
1915 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1916 sjdl1.ReplaceAll("{", "{\n ");
1917 sjdl1.ReplaceAll("};", "\n};");
1918 sjdl1.ReplaceAll("{\n \n", "{\n");
1919 sjdl1.ReplaceAll("\n\n", "\n");
1920 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1921 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1922 sjdl2.ReplaceAll("(member", "\n (member");
1923 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1924 sjdl2.ReplaceAll("{", "{\n ");
1925 sjdl2.ReplaceAll("};", "\n};");
1926 sjdl2.ReplaceAll("{\n \n", "{\n");
1927 sjdl2.ReplaceAll("\n\n", "\n");
1928 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1929 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1930 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1931 index = sjdl.Index("JDLVariables");
1932 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1933 sjdl += "Workdirectorysize = {\"5000MB\"};";
1934 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1935 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1936 index = fJobTag.Index(":");
1937 if (index < 0) index = fJobTag.Length();
1938 TString jobTag = fJobTag;
1939 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1940 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1941 if (fProductionMode) {
1942 sjdl1.Prepend("# Generated merging jdl (production mode) \
1943 \n# $1 = full alien path to output directory to be merged \
1944 \n# $2 = train number \
1945 \n# $3 = production (like LHC10b) \
1946 \n# $4 = merging stage \
1947 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1948 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1949 sjdl2.Prepend("# Generated merging jdl \
1950 \n# $1 = full alien path to output directory to be merged \
1951 \n# $2 = train number \
1952 \n# $3 = production (like LHC10b) \
1953 \n# $4 = merging stage \
1954 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1956 sjdl1.Prepend("# Generated merging jdl \
1957 \n# $1 = full alien path to output directory to be merged \
1958 \n# $2 = merging stage \
1959 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1960 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1961 sjdl2.Prepend("# Generated merging jdl \
1962 \n# $1 = full alien path to output directory to be merged \
1963 \n# $2 = merging stage \
1964 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1966 index = sjdl1.Index("JDLVariables");
1967 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1968 index = sjdl2.Index("JDLVariables");
1969 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1970 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1971 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1972 index = sjdl2.Index("Split =");
1974 index1 = sjdl2.Index("\n", index);
1975 sjdl2.Remove(index, index1-index+1);
1977 index = sjdl2.Index("SplitMaxInputFileNumber");
1979 index1 = sjdl2.Index("\n", index);
1980 sjdl2.Remove(index, index1-index+1);
1982 index = sjdl2.Index("InputDataCollection");
1984 index1 = sjdl2.Index(";", index);
1985 sjdl2.Remove(index, index1-index+1);
1987 index = sjdl2.Index("InputDataListFormat");
1989 index1 = sjdl2.Index("\n", index);
1990 sjdl2.Remove(index, index1-index+1);
1992 index = sjdl2.Index("InputDataList");
1994 index1 = sjdl2.Index("\n", index);
1995 sjdl2.Remove(index, index1-index+1);
1997 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1998 // Write jdl to file
2000 out.open(fJDLName.Data(), ios::out);
2002 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2005 out << sjdl << endl;
2007 TString mergeJDLName = fExecutable;
2008 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2011 out1.open(mergeJDLName.Data(), ios::out);
2013 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2016 out1 << sjdl1 << endl;
2019 TString finalJDL = mergeJDLName;
2020 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2021 out2.open(finalJDL.Data(), ios::out);
2023 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2026 out2 << sjdl2 << endl;
2030 // Copy jdl to grid workspace
2032 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2034 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2035 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2036 TString finalJDL = mergeJDLName;
2037 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2038 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2039 if (fProductionMode) {
2040 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2041 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2042 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2044 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2045 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2046 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2047 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2048 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2049 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2050 Fatal("","Terminating");
2052 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2053 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2054 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2055 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2056 Fatal("","Terminating");
2057 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2058 Fatal("","Terminating");
2064 //______________________________________________________________________________
2065 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2067 // Returns true if file exists.
2068 if (!gGrid) return kFALSE;
2070 slfn.ReplaceAll("alien://","");
2071 TGridResult *res = gGrid->Ls(slfn);
2072 if (!res) return kFALSE;
2073 TMap *map = dynamic_cast<TMap*>(res->At(0));
2078 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2079 if (!objs || !objs->GetString().Length()) {
2087 //______________________________________________________________________________
2088 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2090 // Returns true if directory exists. Can be also a path.
2091 if (!gGrid) return kFALSE;
2092 // Check if dirname is a path
2093 TString dirstripped = dirname;
2094 dirstripped = dirstripped.Strip();
2095 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2096 TString dir = gSystem->BaseName(dirstripped);
2098 TString path = gSystem->DirName(dirstripped);
2099 TGridResult *res = gGrid->Ls(path, "-F");
2100 if (!res) return kFALSE;
2104 while ((map=dynamic_cast<TMap*>(next()))) {
2105 obj = map->GetValue("name");
2107 if (dir == obj->GetName()) {
2116 //______________________________________________________________________________
2117 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2119 // Check input data type.
2120 isCollection = kFALSE;
2124 Error("CheckDataType", "No connection to grid");
2127 isCollection = IsCollection(lfn);
2128 TString msg = "\n##### file: ";
2131 msg += " type: raw_collection;";
2132 // special treatment for collections
2134 // check for tag files in the collection
2135 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2137 msg += " using_tags: No (unknown)";
2138 Info("CheckDataType", "%s", msg.Data());
2141 const char* typeStr = res->GetKey(0, "origLFN");
2142 if (!typeStr || !strlen(typeStr)) {
2143 msg += " using_tags: No (unknown)";
2144 Info("CheckDataType", "%s", msg.Data());
2147 TString file = typeStr;
2148 useTags = file.Contains(".tag");
2149 if (useTags) msg += " using_tags: Yes";
2150 else msg += " using_tags: No";
2151 Info("CheckDataType", "%s", msg.Data());
2156 isXml = slfn.Contains(".xml");
2158 // Open xml collection and check if there are tag files inside
2159 msg += " type: xml_collection;";
2160 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2162 msg += " using_tags: No (unknown)";
2163 Info("CheckDataType", "%s", msg.Data());
2166 TMap *map = coll->Next();
2168 msg += " using_tags: No (unknown)";
2169 Info("CheckDataType", "%s", msg.Data());
2172 map = (TMap*)map->GetValue("");
2174 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2175 useTags = file.Contains(".tag");
2177 if (useTags) msg += " using_tags: Yes";
2178 else msg += " using_tags: No";
2179 Info("CheckDataType", "%s", msg.Data());
2182 useTags = slfn.Contains(".tag");
2183 if (slfn.Contains(".root")) msg += " type: root file;";
2184 else msg += " type: unknown file;";
2185 if (useTags) msg += " using_tags: Yes";
2186 else msg += " using_tags: No";
2187 Info("CheckDataType", "%s", msg.Data());
2190 //______________________________________________________________________________
2191 void AliAnalysisAlien::EnablePackage(const char *package)
2193 // Enables a par file supposed to exist in the current directory.
2194 TString pkg(package);
2195 pkg.ReplaceAll(".par", "");
2197 if (gSystem->AccessPathName(pkg)) {
2198 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2201 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2202 Info("EnablePackage", "AliEn plugin will use .par packages");
2203 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2205 fPackages = new TObjArray();
2206 fPackages->SetOwner();
2208 fPackages->Add(new TObjString(pkg));
2211 //______________________________________________________________________________
2212 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2214 // Make a tree from files having the location specified in fFileForTestMode.
2215 // Inspired from JF's CreateESDChain.
2216 if (fFileForTestMode.IsNull()) {
2217 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2220 if (gSystem->AccessPathName(fFileForTestMode)) {
2221 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2226 in.open(fFileForTestMode);
2228 // Read the input list of files and add them to the chain
2230 TChain *chain = new TChain(treeName);
2231 TChain *chainFriend = 0;
2232 if (!fFriendChainName.IsNull()) chainFriend = new TChain(treeName);
2236 if (line.IsNull()) continue;
2237 if (count++ == fNtestFiles) break;
2238 TString esdFile(line);
2239 TFile *file = TFile::Open(esdFile);
2240 if (file && !file->IsZombie()) {
2241 chain->Add(esdFile);
2243 if (!fFriendChainName.IsNull()) {
2244 if (esdFile.Index("#") > -1)
2245 esdFile.Remove(esdFile.Index("#"));
2246 esdFile = gSystem->DirName(esdFile);
2247 esdFile += "/" + fFriendChainName;
2248 file = TFile::Open(esdFile);
2249 if (file && !file->IsZombie()) {
2251 chainFriend->Add(esdFile);
2253 Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2258 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2262 if (!chain->GetListOfFiles()->GetEntries()) {
2263 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2269 if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2273 //______________________________________________________________________________
2274 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2276 // Get job status for all jobs with jobid>jobidstart.
2277 static char mstatus[20];
2283 TGridJobStatusList *list = gGrid->Ps("");
2284 if (!list) return mstatus;
2285 Int_t nentries = list->GetSize();
2286 TGridJobStatus *status;
2288 for (Int_t ijob=0; ijob<nentries; ijob++) {
2289 status = (TGridJobStatus *)list->At(ijob);
2290 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2291 if (pid<jobidstart) continue;
2292 if (pid == lastid) {
2293 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2295 switch (status->GetStatus()) {
2296 case TGridJobStatus::kWAITING:
2298 case TGridJobStatus::kRUNNING:
2300 case TGridJobStatus::kABORTED:
2301 case TGridJobStatus::kFAIL:
2302 case TGridJobStatus::kUNKNOWN:
2304 case TGridJobStatus::kDONE:
2313 //______________________________________________________________________________
2314 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2316 // Returns true if file is a collection. Functionality duplicated from
2317 // TAlien::Type() because we don't want to directly depend on TAlien.
2319 Error("IsCollection", "No connection to grid");
2322 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2323 if (!res) return kFALSE;
2324 const char* typeStr = res->GetKey(0, "type");
2325 if (!typeStr || !strlen(typeStr)) return kFALSE;
2326 if (!strcmp(typeStr, "collection")) return kTRUE;
2331 //______________________________________________________________________________
2332 Bool_t AliAnalysisAlien::IsSingleOutput() const
2334 // Check if single-ouput option is on.
2335 return (!fOutputSingle.IsNull());
2338 //______________________________________________________________________________
2339 void AliAnalysisAlien::Print(Option_t *) const
2341 // Print current plugin settings.
2342 printf("### AliEn analysis plugin current settings ###\n");
2343 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2344 if (mgr && mgr->IsProofMode()) {
2345 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2346 if (TestBit(AliAnalysisGrid::kTest))
2347 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2348 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2349 if (!fProofDataSet.IsNull())
2350 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2352 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2354 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2355 if (!fRootVersionForProof.IsNull())
2356 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2358 printf("= ROOT version requested________________________ default\n");
2359 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2360 if (!fAliRootMode.IsNull())
2361 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2363 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2364 if (fNproofWorkersPerSlave)
2365 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2366 if (TestSpecialBit(kClearPackages))
2367 printf("= ClearPackages requested...\n");
2368 if (fIncludePath.Data())
2369 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2370 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2371 if (fPackages && fPackages->GetEntries()) {
2372 TIter next(fPackages);
2375 while ((obj=next())) list += obj->GetName();
2376 printf("= Par files to be used: ________________________ %s\n", list.Data());
2378 if (TestSpecialBit(kProofConnectGrid))
2379 printf("= Requested PROOF connection to grid\n");
2382 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2383 if (fOverwriteMode) {
2384 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2385 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2387 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2388 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2389 printf("= Production mode:______________________________ %d\n", fProductionMode);
2390 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2391 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2392 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2394 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2395 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2396 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2397 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2398 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2399 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2400 if (fRunNumbers.Length())
2401 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2403 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2404 if (!fRunRange[0] && !fRunNumbers.Length()) {
2405 TIter next(fInputFiles);
2408 while ((obj=next())) list += obj->GetName();
2409 printf("= Input files to be processed: _________________ %s\n", list.Data());
2411 if (TestBit(AliAnalysisGrid::kTest))
2412 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2413 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2414 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2415 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2416 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2417 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2418 printf("=====================================================================\n");
2419 printf("= Job price: ___________________________________ %d\n", fPrice);
2420 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2421 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2422 if (fMaxInitFailed>0)
2423 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2424 if (fMasterResubmitThreshold>0)
2425 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2426 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2427 if (fNrunsPerMaster>0)
2428 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2429 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2430 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2431 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2432 if (fArguments.Length())
2433 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2434 if (fExecutableArgs.Length())
2435 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2436 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2437 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2438 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2439 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2441 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2442 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2443 if (fIncludePath.Data())
2444 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2445 if (fCloseSE.Length())
2446 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2447 if (fFriendChainName.Length())
2448 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2449 if (fPackages && fPackages->GetEntries()) {
2450 TIter next(fPackages);
2453 while ((obj=next())) list += obj->GetName();
2454 printf("= Par files to be used: ________________________ %s\n", list.Data());
2458 //______________________________________________________________________________
2459 void AliAnalysisAlien::SetDefaults()
2461 // Set default values for everything. What cannot be filled will be left empty.
2462 if (fGridJDL) delete fGridJDL;
2463 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2464 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2467 fSplitMaxInputFileNumber = 100;
2469 fMasterResubmitThreshold = 0;
2475 fNrunsPerMaster = 1;
2476 fMaxMergeFiles = 100;
2478 fExecutable = "analysis.sh";
2479 fExecutableCommand = "root -b -q";
2481 fExecutableArgs = "";
2482 fAnalysisMacro = "myAnalysis.C";
2483 fAnalysisSource = "";
2484 fAdditionalLibs = "";
2488 fAliROOTVersion = "";
2489 fUser = ""; // Your alien user name
2490 fGridWorkingDir = "";
2491 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2492 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2493 fFriendChainName = "";
2494 fGridOutputDir = "output";
2495 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2496 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2497 fInputFormat = "xml-single";
2498 fJDLName = "analysis.jdl";
2499 fJobTag = "Automatically generated analysis JDL";
2500 fMergeExcludes = "";
2503 SetCheckCopy(kTRUE);
2504 SetDefaultOutputs(kTRUE);
2508 //______________________________________________________________________________
2509 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2511 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2512 // First check if the result is already in the output directory.
2513 if (FileExists(Form("%s/%s",aliendir,filename))) {
2514 printf("Final merged results found. Not merging again.\n");
2517 // Now check the last stage done.
2520 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2523 // Next stage of merging
2525 TString pattern = "*root_archive.zip";
2526 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2527 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2528 if (res) delete res;
2529 // Write standard output to file
2530 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2531 // Count the number of files inside
2533 ifile.open(Form("Stage_%d.xml",stage));
2534 if (!ifile.good()) {
2535 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2540 while (!ifile.eof()) {
2542 if (line.Contains("/event")) nfiles++;
2546 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2549 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2551 // Copy the file in the output directory
2552 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2553 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2554 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2555 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2556 // Check if this is the last stage to be done.
2557 Bool_t laststage = (nfiles<nperchunk);
2558 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2560 printf("### Submiting final merging stage %d\n", stage);
2561 TString finalJDL = jdl;
2562 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2563 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2564 Int_t jobId = SubmitSingleJob(query);
2565 if (!jobId) return kFALSE;
2567 printf("### Submiting merging stage %d\n", stage);
2568 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2569 Int_t jobId = SubmitSingleJob(query);
2570 if (!jobId) return kFALSE;
2575 //______________________________________________________________________________
2576 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2578 // Loat the analysis manager from a file.
2579 TFile *file = TFile::Open(fname);
2581 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2584 TIter nextkey(file->GetListOfKeys());
2585 AliAnalysisManager *mgr = 0;
2587 while ((key=(TKey*)nextkey())) {
2588 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2589 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2592 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2596 //______________________________________________________________________________
2597 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2599 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2600 if (!gGrid) return 0;
2601 printf("=> %s ------> ",query);
2602 TGridResult *res = gGrid->Command(query);
2604 TString jobId = res->GetKey(0,"jobId");
2606 if (jobId.IsNull()) {
2607 printf("submission failed. Reason:\n");
2610 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2613 printf(" Job id: %s\n", jobId.Data());
2617 //______________________________________________________________________________
2618 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2620 // Merge given output files from basedir. Basedir can be an alien output directory
2621 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2622 // files in a group (ignored for xml input). Merging can be done in stages:
2623 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2624 // stage=1 : works with an xml of all root_archive.zip in the output directory
2625 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2626 TString outputFile = output;
2628 TString outputChunk;
2629 TString previousChunk = "";
2630 TObjArray *listoffiles = new TObjArray();
2631 // listoffiles->SetOwner();
2632 Int_t countChunk = 0;
2633 Int_t countZero = nmaxmerge;
2634 Bool_t merged = kTRUE;
2635 Int_t index = outputFile.Index("@");
2636 if (index > 0) outputFile.Remove(index);
2637 TString inputFile = outputFile;
2638 TString sbasedir = basedir;
2639 if (sbasedir.Contains(".xml")) {
2640 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2641 nmaxmerge = 9999999;
2642 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2644 ::Error("MergeOutput", "Input XML collection empty.");
2647 // Iterate grid collection
2648 while (coll->Next()) {
2649 TString fname = gSystem->DirName(coll->GetTURL());
2652 listoffiles->Add(new TNamed(fname.Data(),""));
2655 command = Form("find %s/ *%s", basedir, inputFile.Data());
2656 printf("command: %s\n", command.Data());
2657 TGridResult *res = gGrid->Command(command);
2659 ::Error("MergeOutput","No result for the find command\n");
2665 while ((map=(TMap*)nextmap())) {
2666 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2667 if (!objs || !objs->GetString().Length()) {
2668 // Nothing found - skip this output
2673 listoffiles->Add(new TNamed(objs->GetName(),""));
2677 if (!listoffiles->GetEntries()) {
2678 ::Error("MergeOutput","No result for the find command\n");
2683 TFileMerger *fm = 0;
2684 TIter next0(listoffiles);
2685 TObjArray *listoffilestmp = new TObjArray();
2686 listoffilestmp->SetOwner();
2689 // Keep only the files at upper level
2690 Int_t countChar = 0;
2691 while ((nextfile=next0())) {
2692 snextfile = nextfile->GetName();
2693 Int_t crtCount = snextfile.CountChar('/');
2694 if (nextfile == listoffiles->First()) countChar = crtCount;
2695 if (crtCount < countChar) countChar = crtCount;
2698 while ((nextfile=next0())) {
2699 snextfile = nextfile->GetName();
2700 Int_t crtCount = snextfile.CountChar('/');
2701 if (crtCount > countChar) {
2705 listoffilestmp->Add(nextfile);
2708 listoffiles = listoffilestmp; // Now contains 'good' files
2709 listoffiles->Print();
2710 TIter next(listoffiles);
2711 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2712 outputChunk = outputFile;
2713 outputChunk.ReplaceAll(".root", "_*.root");
2714 // Check for existent temporary merge files
2715 // Check overwrite mode and remove previous partial results if needed
2716 // Preserve old merging functionality for stage 0.
2718 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2720 // Skip as many input files as in a chunk
2721 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2724 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2728 snextfile = nextfile->GetName();
2730 outputChunk = outputFile;
2731 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2733 if (gSystem->AccessPathName(outputChunk)) continue;
2734 // Merged file with chunks up to <countChunk> found
2735 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2736 previousChunk = outputChunk;
2740 countZero = nmaxmerge;
2742 while ((nextfile=next())) {
2743 snextfile = nextfile->GetName();
2744 // Loop 'find' results and get next LFN
2745 if (countZero == nmaxmerge) {
2746 // First file in chunk - create file merger and add previous chunk if any.
2747 fm = new TFileMerger(kTRUE);
2748 fm->SetFastMethod(kTRUE);
2749 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2750 outputChunk = outputFile;
2751 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2753 // If last file found, put merged results in the output file
2754 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2755 // Add file to be merged and decrement chunk counter.
2756 fm->AddFile(snextfile);
2758 if (countZero==0 || nextfile == listoffiles->Last()) {
2759 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2760 // Nothing found - skip this output
2761 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2765 fm->OutputFile(outputChunk);
2766 // Merge the outputs, then go to next chunk
2768 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2772 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2773 gSystem->Unlink(previousChunk);
2775 if (nextfile == listoffiles->Last()) break;
2777 countZero = nmaxmerge;
2778 previousChunk = outputChunk;
2785 // Merging stage different than 0.
2786 // Move to the begining of the requested chunk.
2787 fm = new TFileMerger(kTRUE);
2788 fm->SetFastMethod(kTRUE);
2789 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2791 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2792 // Nothing found - skip this output
2793 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2797 fm->OutputFile(outputFile);
2798 // Merge the outputs
2800 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2804 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2810 //______________________________________________________________________________
2811 Bool_t AliAnalysisAlien::MergeOutputs()
2813 // Merge analysis outputs existing in the AliEn space.
2814 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2815 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2817 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2821 if (!TestBit(AliAnalysisGrid::kMerge)) {
2822 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2825 if (fProductionMode) {
2826 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2829 Info("MergeOutputs", "Submitting merging JDL");
2830 if (!SubmitMerging()) return kFALSE;
2831 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2832 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2835 // Get the output path
2836 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2837 if (!DirectoryExists(fGridOutputDir)) {
2838 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2841 if (!fOutputFiles.Length()) {
2842 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2845 // Check if fast read option was requested
2846 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2847 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2848 if (fFastReadOption) {
2849 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2850 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2851 gEnv->SetValue("XNet.ConnectTimeout",50);
2852 gEnv->SetValue("XNet.RequestTimeout",50);
2853 gEnv->SetValue("XNet.MaxRedirectCount",2);
2854 gEnv->SetValue("XNet.ReconnectTimeout",50);
2855 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2857 // Make sure we change the temporary directory
2858 gSystem->Setenv("TMPDIR", gSystem->pwd());
2859 // Set temporary compilation directory to current one
2860 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2861 TObjArray *list = fOutputFiles.Tokenize(",");
2865 Bool_t merged = kTRUE;
2866 while((str=(TObjString*)next())) {
2867 outputFile = str->GetString();
2868 Int_t index = outputFile.Index("@");
2869 if (index > 0) outputFile.Remove(index);
2870 TString outputChunk = outputFile;
2871 outputChunk.ReplaceAll(".root", "_*.root");
2872 // Skip already merged outputs
2873 if (!gSystem->AccessPathName(outputFile)) {
2874 if (fOverwriteMode) {
2875 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2876 gSystem->Unlink(outputFile);
2877 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2878 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2879 outputChunk.Data());
2880 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2883 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2887 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2888 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2889 outputChunk.Data());
2890 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2893 if (fMergeExcludes.Contains(outputFile.Data()) ||
2894 fRegisterExcludes.Contains(outputFile.Data())) continue;
2895 // Perform a 'find' command in the output directory, looking for registered outputs
2896 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2898 Error("MergeOutputs", "Terminate() will NOT be executed");
2901 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2902 if (fileOpened) fileOpened->Close();
2907 //______________________________________________________________________________
2908 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2910 // Use the output files connected to output containers from the analysis manager
2911 // rather than the files defined by SetOutputFiles
2912 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2913 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2914 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2917 //______________________________________________________________________________
2918 void AliAnalysisAlien::SetOutputFiles(const char *list)
2920 // Manually set the output files list.
2921 // Removes duplicates. Not allowed if default outputs are not disabled.
2922 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2923 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2926 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2928 TString slist = list;
2929 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2930 TObjArray *arr = slist.Tokenize(" ");
2934 while ((os=(TObjString*)next())) {
2935 sout = os->GetString();
2936 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2937 if (fOutputFiles.Contains(sout)) continue;
2938 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2939 fOutputFiles += sout;
2944 //______________________________________________________________________________
2945 void AliAnalysisAlien::SetOutputArchive(const char *list)
2947 // Manually set the output archive list. Free text - you are on your own...
2948 // Not allowed if default outputs are not disabled.
2949 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2950 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2953 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2954 fOutputArchive = list;
2957 //______________________________________________________________________________
2958 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2960 // Setting a prefered output SE is not allowed anymore.
2961 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2964 //______________________________________________________________________________
2965 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2967 // Set some PROOF special parameter.
2968 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2970 TObject *old = pair->Key();
2971 TObject *val = pair->Value();
2972 fProofParam.Remove(old);
2976 fProofParam.Add(new TObjString(pname), new TObjString(value));
2979 //______________________________________________________________________________
2980 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2982 // Returns a special PROOF parameter.
2983 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2984 if (!pair) return 0;
2985 return pair->Value()->GetName();
2988 //______________________________________________________________________________
2989 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2991 // Start remote grid analysis.
2992 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2993 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2994 if (!mgr || !mgr->IsInitialized()) {
2995 Error("StartAnalysis", "You need an initialized analysis manager for this");
2998 // Are we in PROOF mode ?
2999 if (mgr->IsProofMode()) {
3000 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
3001 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3002 if (fProofCluster.IsNull()) {
3003 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3006 if (fProofDataSet.IsNull() && !testMode) {
3007 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3010 // Set the needed environment
3011 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3012 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3013 if (fProofReset && !testMode) {
3014 if (fProofReset==1) {
3015 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3016 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3018 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3019 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3021 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3026 // Check if there is an old active session
3027 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3029 Error("StartAnalysis","You have to reset your old session first\n");
3033 // Do we need to change the ROOT version ? The success of this cannot be checked.
3034 if (!fRootVersionForProof.IsNull() && !testMode) {
3035 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
3036 fProofCluster.Data(), fRootVersionForProof.Data()));
3038 // Connect to PROOF and check the status
3041 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3042 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3044 if (!sworkers.IsNull())
3045 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3047 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3049 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3051 Error("StartAnalysis", "Could not start PROOF in test mode");
3056 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3059 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3060 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3061 // Set proof special parameters if any
3062 TIter nextpp(&fProofParam);
3063 TObject *proofparam;
3064 while ((proofparam=nextpp())) {
3065 TString svalue = GetProofParameter(proofparam->GetName());
3066 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3068 // Is dataset existing ?
3070 TString dataset = fProofDataSet;
3071 Int_t index = dataset.Index("#");
3072 if (index>=0) dataset.Remove(index);
3073 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3074 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3077 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3079 // Is ClearPackages() needed ?
3080 if (TestSpecialBit(kClearPackages)) {
3081 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3082 gROOT->ProcessLine("gProof->ClearPackages();");
3084 // Is a given aliroot mode requested ?
3087 if (!fAliRootMode.IsNull()) {
3088 TString alirootMode = fAliRootMode;
3089 if (alirootMode == "default") alirootMode = "";
3090 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3091 optionsList.SetOwner();
3092 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3093 // Check the additional libs to be loaded
3095 Bool_t parMode = kFALSE;
3096 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3097 // Parse the extra libs for .so
3098 if (fAdditionalLibs.Length()) {
3099 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3102 while((str=(TObjString*)next())) {
3103 if (str->GetString().Contains(".so")) {
3105 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());
3108 TString stmp = str->GetName();
3109 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3110 stmp.ReplaceAll(".so","");
3111 if (!extraLibs.IsNull()) extraLibs += ":";
3115 if (str->GetString().Contains(".par")) {
3116 // The first par file found in the list will not allow any further .so
3118 if (!parLibs.IsNull()) parLibs += ":";
3119 parLibs += str->GetName();
3123 if (list) delete list;
3125 if (!extraLibs.IsNull()) {
3126 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3127 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3129 // Check extra includes
3130 if (!fIncludePath.IsNull()) {
3131 TString includePath = fIncludePath;
3132 includePath.ReplaceAll(" ",":");
3133 includePath.ReplaceAll("$ALICE_ROOT/","");
3134 includePath.ReplaceAll("${ALICE_ROOT}/","");
3135 includePath.ReplaceAll("-I","");
3136 includePath.Remove(TString::kTrailing, ':');
3137 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3138 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3140 // Check if connection to grid is requested
3141 if (TestSpecialBit(kProofConnectGrid))
3142 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3143 // Enable AliRoot par
3145 // Enable proof lite package
3146 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3147 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3148 TNamed *obj = (TNamed*)optionsList.At(i);
3149 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3151 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3152 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3153 Info("StartAnalysis", "AliRootProofLite enabled");
3155 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3159 if ( ! fAliROOTVersion.IsNull() ) {
3160 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3161 fAliROOTVersion.Data(), &optionsList))) {
3162 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3167 // Enable first par files from fAdditionalLibs
3168 if (!parLibs.IsNull()) {
3169 TObjArray *list = parLibs.Tokenize(":");
3171 TObjString *package;
3172 while((package=(TObjString*)next())) {
3173 TString spkg = package->GetName();
3174 spkg.ReplaceAll(".par", "");
3175 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3176 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3177 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3178 if (gROOT->ProcessLine(enablePackage)) {
3179 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3183 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3187 if (list) delete list;
3190 if (fAdditionalLibs.Contains(".so") && !testMode) {
3191 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3192 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3196 // Enable par files if requested
3197 if (fPackages && fPackages->GetEntries()) {
3198 TIter next(fPackages);
3200 while ((package=next())) {
3201 // Skip packages already enabled
3202 if (parLibs.Contains(package->GetName())) continue;
3203 TString spkg = package->GetName();
3204 spkg.ReplaceAll(".par", "");
3205 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3206 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3207 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3208 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3212 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3217 // Do we need to load analysis source files ?
3218 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3219 if (fAnalysisSource.Length()) {
3220 TObjArray *list = fAnalysisSource.Tokenize(" ");
3223 while((str=(TObjString*)next())) {
3224 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3226 if (list) delete list;
3229 // Register dataset to proof lite.
3230 if (fFileForTestMode.IsNull()) {
3231 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3234 if (gSystem->AccessPathName(fFileForTestMode)) {
3235 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3238 TFileCollection *coll = new TFileCollection();
3239 coll->AddFromFile(fFileForTestMode);
3240 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3241 gROOT->ProcessLine("gProof->ShowDataSets()");
3246 // Check if output files have to be taken from the analysis manager
3247 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3248 // Add output files and AOD files
3249 fOutputFiles = GetListOfFiles("outaod");
3250 // Add extra files registered to the analysis manager
3251 TString extra = GetListOfFiles("ext");
3252 if (!extra.IsNull()) {
3253 extra.ReplaceAll(".root", "*.root");
3254 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3255 fOutputFiles += extra;
3257 // Compose the output archive.
3258 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3259 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3261 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3262 if (TestBit(AliAnalysisGrid::kOffline)) {
3263 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3264 \n there nor any job run. You can revise the JDL and analysis \
3265 \n macro then run the same in \"submit\" mode.");
3266 } else if (TestBit(AliAnalysisGrid::kTest)) {
3267 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3269 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3270 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3271 \n space and job submitted.");
3272 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3273 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3274 if (fMergeViaJDL) CheckInputData();
3277 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3282 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3285 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3286 if (!CheckInputData()) {
3287 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3290 if (!CreateDataset(fDataPattern)) {
3292 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3293 if (fRunNumbers.Length()) serror = "run numbers";
3294 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3295 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3296 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3299 WriteAnalysisFile();
3300 WriteAnalysisMacro();
3302 WriteValidationScript();
3304 WriteMergingMacro();
3305 WriteMergeExecutable();
3306 WriteValidationScript(kTRUE);
3308 if (!CreateJDL()) return kFALSE;
3309 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3311 // Locally testing the analysis
3312 Info("StartAnalysis", "\n_______________________________________________________________________ \
3313 \n Running analysis script in a daughter shell as on a worker node \
3314 \n_______________________________________________________________________");
3315 TObjArray *list = fOutputFiles.Tokenize(",");
3319 while((str=(TObjString*)next())) {
3320 outputFile = str->GetString();
3321 Int_t index = outputFile.Index("@");
3322 if (index > 0) outputFile.Remove(index);
3323 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3326 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3327 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3328 // gSystem->Exec("cat stdout");
3331 // Check if submitting is managed by LPM manager
3332 if (fProductionMode) {
3333 //TString prodfile = fJDLName;
3334 //prodfile.ReplaceAll(".jdl", ".prod");
3335 //WriteProductionFile(prodfile);
3336 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3339 // Submit AliEn job(s)
3340 gGrid->Cd(fGridOutputDir);
3343 if (!fRunNumbers.Length() && !fRunRange[0]) {
3344 // Submit a given xml or a set of runs
3345 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3346 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3348 const char *cjobId = res->GetKey(0,"jobId");
3352 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3355 Info("StartAnalysis", "\n_______________________________________________________________________ \
3356 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3357 \n_______________________________________________________________________",
3358 fJDLName.Data(), cjobId);
3363 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3367 // Submit for a range of enumeration of runs.
3368 if (!Submit()) return kFALSE;
3371 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3372 \n You may exit at any time and terminate the job later using the option <terminate> \
3373 \n ##################################################################################", jobID.Data());
3374 gSystem->Exec("aliensh");
3378 //______________________________________________________________________________
3379 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3381 // Get a comma-separated list of output files of the requested type.
3382 // Type can be (case unsensitive):
3383 // aod - list of aod files (std, extensions and filters)
3384 // out - list of output files connected to containers (but not aod's or extras)
3385 // ext - list of extra files registered to the manager
3386 // ter - list of files produced in terminate
3387 static TString files;
3389 TString stype = type;
3391 TString aodfiles, extra;
3392 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3394 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3395 return files.Data();
3397 if (mgr->GetOutputEventHandler()) {
3398 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3399 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3400 if (!extraaod.IsNull()) {
3402 aodfiles += extraaod;
3405 if (stype.Contains("aod")) {
3407 if (stype == "aod") return files.Data();
3409 // Add output files that are not in the list of AOD files
3410 TString outputfiles = "";
3411 TIter next(mgr->GetOutputs());
3412 AliAnalysisDataContainer *output;
3413 const char *filename = 0;
3414 while ((output=(AliAnalysisDataContainer*)next())) {
3415 filename = output->GetFileName();
3416 if (!(strcmp(filename, "default"))) continue;
3417 if (outputfiles.Contains(filename)) continue;
3418 if (aodfiles.Contains(filename)) continue;
3419 if (!outputfiles.IsNull()) outputfiles += ",";
3420 outputfiles += filename;
3422 if (stype.Contains("out")) {
3423 if (!files.IsNull()) files += ",";
3424 files += outputfiles;
3425 if (stype == "out") return files.Data();
3427 // Add extra files registered to the analysis manager
3429 extra = mgr->GetExtraFiles();
3430 if (!extra.IsNull()) {
3432 extra.ReplaceAll(" ", ",");
3433 TObjArray *fextra = extra.Tokenize(",");
3434 TIter nextx(fextra);
3436 while ((obj=nextx())) {
3437 if (aodfiles.Contains(obj->GetName())) continue;
3438 if (outputfiles.Contains(obj->GetName())) continue;
3439 if (sextra.Contains(obj->GetName())) continue;
3440 if (!sextra.IsNull()) sextra += ",";
3441 sextra += obj->GetName();
3444 if (stype.Contains("ext")) {
3445 if (!files.IsNull()) files += ",";
3449 if (stype == "ext") return files.Data();
3451 if (!fTerminateFiles.IsNull()) {
3452 fTerminateFiles.Strip();
3453 fTerminateFiles.ReplaceAll(" ",",");
3454 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3455 TIter nextx(fextra);
3457 while ((obj=nextx())) {
3458 if (aodfiles.Contains(obj->GetName())) continue;
3459 if (outputfiles.Contains(obj->GetName())) continue;
3460 if (termfiles.Contains(obj->GetName())) continue;
3461 if (sextra.Contains(obj->GetName())) continue;
3462 if (!termfiles.IsNull()) termfiles += ",";
3463 termfiles += obj->GetName();
3467 if (stype.Contains("ter")) {
3468 if (!files.IsNull() && !termfiles.IsNull()) {
3473 return files.Data();
3476 //______________________________________________________________________________
3477 Bool_t AliAnalysisAlien::Submit()
3479 // Submit all master jobs.
3480 Int_t nmasterjobs = fInputFiles->GetEntries();
3481 Long_t tshoot = gSystem->Now();
3482 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3483 while (fNsubmitted < nmasterjobs) {
3484 Long_t now = gSystem->Now();
3485 if ((now-tshoot)>30000) {
3487 if (!SubmitNext()) return kFALSE;
3493 //______________________________________________________________________________
3494 Bool_t AliAnalysisAlien::SubmitMerging()
3496 // Submit all merging jobs.
3497 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3498 gGrid->Cd(fGridOutputDir);
3499 TString mergeJDLName = fExecutable;
3500 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3502 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3505 Int_t ntosubmit = fInputFiles->GetEntries();
3506 for (Int_t i=0; i<ntosubmit; i++) {
3507 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3508 runOutDir.ReplaceAll(".xml", "");
3509 if (fOutputToRunNo) {
3510 // The output directory is the run number
3511 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3512 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3514 if (!fRunNumbers.Length() && !fRunRange[0]) {
3515 // The output directory is the grid outdir
3516 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3517 runOutDir = fGridOutputDir;
3519 // The output directory is the master number in 3 digits format
3520 printf("### Submitting merging job for master <%03d>\n", i);
3521 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3524 // Check now the number of merging stages.
3525 TObjArray *list = fOutputFiles.Tokenize(",");
3529 while((str=(TObjString*)next())) {
3530 outputFile = str->GetString();
3531 Int_t index = outputFile.Index("@");
3532 if (index > 0) outputFile.Remove(index);
3533 if (!fMergeExcludes.Contains(outputFile) &&
3534 !fRegisterExcludes.Contains(outputFile)) break;
3537 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3538 if (!done && (i==ntosubmit-1)) return kFALSE;
3539 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3541 if (!ntosubmit) return kTRUE;
3542 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3543 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3544 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3545 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3546 \n ################################################################################################################");
3547 gSystem->Exec("aliensh");
3551 //______________________________________________________________________________
3552 Bool_t AliAnalysisAlien::SubmitNext()
3554 // Submit next bunch of master jobs if the queue is free. The first master job is
3555 // submitted right away, while the next will not be unless the previous was split.
3556 // The plugin will not submit new master jobs if there are more that 500 jobs in
3558 static Bool_t iscalled = kFALSE;
3559 static Int_t firstmaster = 0;
3560 static Int_t lastmaster = 0;
3561 static Int_t npermaster = 0;
3562 if (iscalled) return kTRUE;
3564 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3565 Int_t ntosubmit = 0;
3568 Int_t nmasterjobs = fInputFiles->GetEntries();
3571 if (!IsUseSubmitPolicy()) {
3573 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3574 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3575 ntosubmit = nmasterjobs;
3578 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3579 printf("=== master %d: %s\n", lastmaster, status.Data());
3580 // If last master not split, just return
3581 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3582 // No more than 100 waiting jobs
3583 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3584 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3585 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3586 if (!ntosubmit) ntosubmit = 1;
3587 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3588 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3590 for (Int_t i=0; i<ntosubmit; i++) {
3591 // Submit for a range of enumeration of runs.
3592 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3594 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3595 runOutDir.ReplaceAll(".xml", "");
3597 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3599 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3600 printf("********* %s\n",query.Data());
3601 res = gGrid->Command(query);
3603 TString cjobId1 = res->GetKey(0,"jobId");
3604 if (!cjobId1.Length()) {
3608 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3611 Info("StartAnalysis", "\n_______________________________________________________________________ \
3612 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3613 \n_______________________________________________________________________",
3614 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3617 lastmaster = cjobId1.Atoi();
3618 if (!firstmaster) firstmaster = lastmaster;
3623 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3631 //______________________________________________________________________________
3632 void AliAnalysisAlien::WriteAnalysisFile()
3634 // Write current analysis manager into the file <analysisFile>
3635 TString analysisFile = fExecutable;
3636 analysisFile.ReplaceAll(".sh", ".root");
3637 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3638 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3639 if (!mgr || !mgr->IsInitialized()) {
3640 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3643 // Check analysis type
3645 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3646 handler = (TObject*)mgr->GetInputEventHandler();
3648 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3649 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3650 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3651 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3653 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3654 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3657 TDirectory *cdir = gDirectory;
3658 TFile *file = TFile::Open(analysisFile, "RECREATE");
3660 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3661 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3662 // Unless merging makes no sense
3663 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3666 // Enable termination for local jobs
3667 mgr->SetSkipTerminate(kFALSE);
3669 if (cdir) cdir->cd();
3670 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3672 Bool_t copy = kTRUE;
3673 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3676 TString workdir = gGrid->GetHomeDirectory();
3677 workdir += fGridWorkingDir;
3678 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3679 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3680 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3681 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3685 //______________________________________________________________________________
3686 void AliAnalysisAlien::WriteAnalysisMacro()
3688 // Write the analysis macro that will steer the analysis in grid mode.
3689 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3691 out.open(fAnalysisMacro.Data(), ios::out);
3693 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3696 Bool_t hasSTEERBase = kFALSE;
3697 Bool_t hasESD = kFALSE;
3698 Bool_t hasAOD = kFALSE;
3699 Bool_t hasANALYSIS = kFALSE;
3700 Bool_t hasOADB = kFALSE;
3701 Bool_t hasANALYSISalice = kFALSE;
3702 Bool_t hasCORRFW = kFALSE;
3703 TString func = fAnalysisMacro;
3704 TString type = "ESD";
3705 TString comment = "// Analysis using ";
3706 if (IsUseMCchain()) {
3710 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3711 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3716 if (type!="AOD" && fFriendChainName!="") {
3717 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3720 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3721 else comment += " data";
3722 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3723 func.ReplaceAll(".C", "");
3724 out << "void " << func.Data() << "()" << endl;
3726 out << comment.Data() << endl;
3727 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3728 out << " TStopwatch timer;" << endl;
3729 out << " timer.Start();" << endl << endl;
3730 // Change temp directory to current one
3731 out << "// Set temporary merging directory to current one" << endl;
3732 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3733 out << "// Set temporary compilation directory to current one" << endl;
3734 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3735 // Reset existing include path
3736 out << "// Reset existing include path and add current directory first in the search" << endl;
3737 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3738 if (!fExecutableCommand.Contains("aliroot")) {
3739 out << "// load base root libraries" << endl;
3740 out << " gSystem->Load(\"libTree\");" << endl;
3741 out << " gSystem->Load(\"libGeom\");" << endl;
3742 out << " gSystem->Load(\"libVMC\");" << endl;
3743 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3744 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3746 if (fAdditionalRootLibs.Length()) {
3747 // in principle libtree /lib geom libvmc etc. can go into this list, too
3748 out << "// Add aditional libraries" << endl;
3749 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3752 while((str=(TObjString*)next())) {
3753 if (str->GetString().Contains(".so"))
3754 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3756 if (list) delete list;
3758 out << "// Load analysis framework libraries" << endl;
3759 TString setupPar = "AliAnalysisAlien::SetupPar";
3761 if (!fExecutableCommand.Contains("aliroot")) {
3762 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3763 out << " gSystem->Load(\"libESD\");" << endl;
3764 out << " gSystem->Load(\"libAOD\");" << endl;
3766 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3767 out << " gSystem->Load(\"libOADB\");" << endl;
3768 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3769 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3771 TIter next(fPackages);
3774 while ((obj=next())) {
3775 pkgname = obj->GetName();
3776 if (pkgname == "STEERBase" ||
3777 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3778 if (pkgname == "ESD" ||
3779 pkgname == "ESD.par") hasESD = kTRUE;
3780 if (pkgname == "AOD" ||
3781 pkgname == "AOD.par") hasAOD = kTRUE;
3782 if (pkgname == "ANALYSIS" ||
3783 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3784 if (pkgname == "OADB" ||
3785 pkgname == "OADB.par") hasOADB = kTRUE;
3786 if (pkgname == "ANALYSISalice" ||
3787 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3788 if (pkgname == "CORRFW" ||
3789 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3791 if (hasANALYSISalice) setupPar = "SetupPar";
3792 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3793 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3794 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3795 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3796 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3797 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3798 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3799 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3800 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3801 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3802 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3803 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3804 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3805 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3806 out << "// Compile other par packages" << endl;
3808 while ((obj=next())) {
3809 pkgname = obj->GetName();
3810 if (pkgname == "STEERBase" ||
3811 pkgname == "STEERBase.par" ||
3813 pkgname == "ESD.par" ||
3815 pkgname == "AOD.par" ||
3816 pkgname == "ANALYSIS" ||
3817 pkgname == "ANALYSIS.par" ||
3818 pkgname == "OADB" ||
3819 pkgname == "OADB.par" ||
3820 pkgname == "ANALYSISalice" ||
3821 pkgname == "ANALYSISalice.par" ||
3822 pkgname == "CORRFW" ||
3823 pkgname == "CORRFW.par") continue;
3824 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3827 out << "// include path" << endl;
3828 // Get the include path from the interpreter and remove entries pointing to AliRoot
3829 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3830 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3831 out << " TIter nextpath(listpaths);" << endl;
3832 out << " TObjString *pname;" << endl;
3833 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3834 out << " TString current = pname->GetName();" << endl;
3835 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3836 out << " gSystem->AddIncludePath(current);" << endl;
3837 out << " }" << endl;
3838 out << " if (listpaths) delete listpaths;" << endl;
3839 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3840 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3841 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3842 if (fAdditionalLibs.Length()) {
3843 out << "// Add aditional AliRoot libraries" << endl;
3844 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3847 while((str=(TObjString*)next())) {
3848 if (str->GetString().Contains(".so"))
3849 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3850 if (str->GetString().Contains(".par"))
3851 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3853 if (list) delete list;
3856 out << "// analysis source to be compiled at runtime (if any)" << endl;
3857 if (fAnalysisSource.Length()) {
3858 TObjArray *list = fAnalysisSource.Tokenize(" ");
3861 while((str=(TObjString*)next())) {
3862 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3864 if (list) delete list;
3867 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3868 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3869 if (fFastReadOption) {
3870 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 !!! \
3871 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3872 out << "// fast xrootd reading enabled" << endl;
3873 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3874 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3875 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3876 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3877 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3878 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3880 if (!IsLocalTest()) {
3881 out << "// connect to AliEn and make the chain" << endl;
3882 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3884 out << "// read the analysis manager from file" << endl;
3885 TString analysisFile = fExecutable;
3886 analysisFile.ReplaceAll(".sh", ".root");
3887 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3888 << analysisFile << "\");" << endl;
3889 out << " if (!mgr) return;" << endl;
3890 if (IsLocalTest()) {
3891 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3892 out << " plugin->SetRunMode(\"test\");" << endl;
3893 if (fFileForTestMode.IsNull())
3894 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3896 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3897 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3898 if (!fFriendChainName.IsNull())
3899 out << " plugin->SetFriendChainName(\"" << fFriendChainName << "\");" << endl;
3900 out << " mgr->SetGridHandler(plugin);" << endl;
3901 if (AliAnalysisManager::GetAnalysisManager()) {
3902 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3903 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3905 out << " mgr->SetDebugLevel(10);" << endl;
3906 out << " mgr->SetNSysInfo(100);" << endl;
3909 out << " mgr->PrintStatus();" << endl;
3910 if (AliAnalysisManager::GetAnalysisManager()) {
3911 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3912 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3914 if (TestBit(AliAnalysisGrid::kTest))
3915 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3917 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3920 if (!IsLocalTest()) {
3921 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3922 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3924 out << " mgr->StartAnalysis(\"localfile\");" << endl;
3926 out << " timer.Stop();" << endl;
3927 out << " timer.Print();" << endl;
3928 out << "}" << endl << endl;
3929 if (!IsLocalTest()) {
3930 out <<"//________________________________________________________________________________" << endl;
3931 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3933 out << "// Create a chain using url's from xml file" << endl;
3934 out << " TString filename;" << endl;
3935 out << " Int_t run = 0;" << endl;
3936 if (IsUseMCchain()) {
3937 out << " TString treename = \"TE\";" << endl;
3939 out << " TString treename = type;" << endl;
3940 out << " treename.ToLower();" << endl;
3941 out << " treename += \"Tree\";" << endl;
3943 out << " printf(\"***************************************\\n\");" << endl;
3944 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3945 out << " printf(\"***************************************\\n\");" << endl;
3946 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3947 out << " if (!coll) {" << endl;
3948 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3949 out << " return NULL;" << endl;
3950 out << " }" << endl;
3951 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3952 out << " TChain *chain = new TChain(treename);" << endl;
3953 if(fFriendChainName!="") {
3954 out << " TChain *chainFriend = new TChain(treename);" << endl;
3956 out << " coll->Reset();" << endl;
3957 out << " while (coll->Next()) {" << endl;
3958 out << " filename = coll->GetTURL("");" << endl;
3959 out << " if (mgr) {" << endl;
3960 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3961 out << " if (nrun && nrun != run) {" << endl;
3962 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3963 out << " mgr->SetRunFromPath(nrun);" << endl;
3964 out << " run = nrun;" << endl;
3965 out << " }" << endl;
3966 out << " }" << endl;
3967 out << " chain->Add(filename);" << endl;
3968 if(fFriendChainName!="") {
3969 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3970 out << " if (fileFriend.Index(\"#\") > -1) fileFriend.Remove(fileFriend.Index(\"#\"));" << endl;
3971 out << " fileFriend = gSystem->DirName(fileFriend);" << endl;
3972 out << " fileFriend += \"/\";" << endl;
3973 out << " fileFriend += \"" << fFriendChainName << "\";";
3974 out << " TFile *file = TFile::Open(fileFriend);" << endl;
3975 out << " if (file) {" << endl;
3976 out << " file->Close();" << endl;
3977 out << " chainFriend->Add(fileFriend.Data());" << endl;
3978 out << " } else {" << endl;
3979 out << " ::Fatal(\"CreateChain\", \"Cannot open friend file: %s\", fileFriend.Data());" << endl;
3980 out << " return 0;" << endl;
3981 out << " }" << endl;
3983 out << " }" << endl;
3984 out << " if (!chain->GetNtrees()) {" << endl;
3985 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3986 out << " return NULL;" << endl;
3987 out << " }" << endl;
3988 if(fFriendChainName!="") {
3989 out << " chain->AddFriend(chainFriend);" << endl;
3991 out << " return chain;" << endl;
3992 out << "}" << endl << endl;
3994 if (hasANALYSISalice) {
3995 out <<"//________________________________________________________________________________" << endl;
3996 out << "Bool_t SetupPar(const char *package) {" << endl;
3997 out << "// Compile the package and set it up." << endl;
3998 out << " TString pkgdir = package;" << endl;
3999 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4000 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4001 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4002 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4003 out << " // Check for BUILD.sh and execute" << endl;
4004 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4005 out << " printf(\"*******************************\\n\");" << endl;
4006 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4007 out << " printf(\"*******************************\\n\");" << endl;
4008 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4009 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4010 out << " gSystem->ChangeDirectory(cdir);" << endl;
4011 out << " return kFALSE;" << endl;
4012 out << " }" << endl;
4013 out << " } else {" << endl;
4014 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4015 out << " gSystem->ChangeDirectory(cdir);" << endl;
4016 out << " return kFALSE;" << endl;
4017 out << " }" << endl;
4018 out << " // Check for SETUP.C and execute" << endl;
4019 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4020 out << " printf(\"*******************************\\n\");" << endl;
4021 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4022 out << " printf(\"*******************************\\n\");" << endl;
4023 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4024 out << " } else {" << endl;
4025 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4026 out << " gSystem->ChangeDirectory(cdir);" << endl;
4027 out << " return kFALSE;" << endl;
4028 out << " }" << endl;
4029 out << " // Restore original workdir" << endl;
4030 out << " gSystem->ChangeDirectory(cdir);" << endl;
4031 out << " return kTRUE;" << endl;
4034 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4036 Bool_t copy = kTRUE;
4037 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4040 TString workdir = gGrid->GetHomeDirectory();
4041 workdir += fGridWorkingDir;
4042 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4043 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4044 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4045 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4046 Form("alien://%s/%s", workdir.Data(),
4047 fAnalysisMacro.Data()))) Fatal("","Terminating");
4051 //______________________________________________________________________________
4052 void AliAnalysisAlien::WriteMergingMacro()
4054 // Write a macro to merge the outputs per master job.
4055 if (!fMergeViaJDL) return;
4056 if (!fOutputFiles.Length()) {
4057 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4060 TString mergingMacro = fExecutable;
4061 mergingMacro.ReplaceAll(".sh","_merge.C");
4062 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4063 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4065 out.open(mergingMacro.Data(), ios::out);
4067 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4070 Bool_t hasSTEERBase = kFALSE;
4071 Bool_t hasESD = kFALSE;
4072 Bool_t hasAOD = kFALSE;
4073 Bool_t hasANALYSIS = kFALSE;
4074 Bool_t hasOADB = kFALSE;
4075 Bool_t hasANALYSISalice = kFALSE;
4076 Bool_t hasCORRFW = kFALSE;
4077 TString func = mergingMacro;
4079 func.ReplaceAll(".C", "");
4080 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4082 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4083 out << " TStopwatch timer;" << endl;
4084 out << " timer.Start();" << endl << endl;
4085 // Reset existing include path
4086 out << "// Reset existing include path and add current directory first in the search" << endl;
4087 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4088 if (!fExecutableCommand.Contains("aliroot")) {
4089 out << "// load base root libraries" << endl;
4090 out << " gSystem->Load(\"libTree\");" << endl;
4091 out << " gSystem->Load(\"libGeom\");" << endl;
4092 out << " gSystem->Load(\"libVMC\");" << endl;
4093 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4094 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4096 if (fAdditionalRootLibs.Length()) {
4097 // in principle libtree /lib geom libvmc etc. can go into this list, too
4098 out << "// Add aditional libraries" << endl;
4099 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4102 while((str=(TObjString*)next())) {
4103 if (str->GetString().Contains(".so"))
4104 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4106 if (list) delete list;
4108 out << "// Load analysis framework libraries" << endl;
4110 if (!fExecutableCommand.Contains("aliroot")) {
4111 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4112 out << " gSystem->Load(\"libESD\");" << endl;
4113 out << " gSystem->Load(\"libAOD\");" << endl;
4115 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4116 out << " gSystem->Load(\"libOADB\");" << endl;
4117 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4118 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4120 TIter next(fPackages);
4123 TString setupPar = "AliAnalysisAlien::SetupPar";
4124 while ((obj=next())) {
4125 pkgname = obj->GetName();
4126 if (pkgname == "STEERBase" ||
4127 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4128 if (pkgname == "ESD" ||
4129 pkgname == "ESD.par") hasESD = kTRUE;
4130 if (pkgname == "AOD" ||
4131 pkgname == "AOD.par") hasAOD = kTRUE;
4132 if (pkgname == "ANALYSIS" ||
4133 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4134 if (pkgname == "OADB" ||
4135 pkgname == "OADB.par") hasOADB = kTRUE;
4136 if (pkgname == "ANALYSISalice" ||
4137 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4138 if (pkgname == "CORRFW" ||
4139 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4141 if (hasANALYSISalice) setupPar = "SetupPar";
4142 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4143 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4144 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4145 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4146 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4147 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4148 out << " gSystem->Load(\"libOADB\");" << endl;
4149 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4150 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4151 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4152 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4153 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4154 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4155 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4156 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4157 out << "// Compile other par packages" << endl;
4159 while ((obj=next())) {
4160 pkgname = obj->GetName();
4161 if (pkgname == "STEERBase" ||
4162 pkgname == "STEERBase.par" ||
4164 pkgname == "ESD.par" ||
4166 pkgname == "AOD.par" ||
4167 pkgname == "ANALYSIS" ||
4168 pkgname == "ANALYSIS.par" ||
4169 pkgname == "OADB" ||
4170 pkgname == "OADB.par" ||
4171 pkgname == "ANALYSISalice" ||
4172 pkgname == "ANALYSISalice.par" ||
4173 pkgname == "CORRFW" ||
4174 pkgname == "CORRFW.par") continue;
4175 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4178 out << "// include path" << endl;
4179 // Get the include path from the interpreter and remove entries pointing to AliRoot
4180 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4181 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4182 out << " TIter nextpath(listpaths);" << endl;
4183 out << " TObjString *pname;" << endl;
4184 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4185 out << " TString current = pname->GetName();" << endl;
4186 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4187 out << " gSystem->AddIncludePath(current);" << endl;
4188 out << " }" << endl;
4189 out << " if (listpaths) delete listpaths;" << endl;
4190 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4191 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4192 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4193 if (fAdditionalLibs.Length()) {
4194 out << "// Add aditional AliRoot libraries" << endl;
4195 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4198 while((str=(TObjString*)next())) {
4199 if (str->GetString().Contains(".so"))
4200 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4202 if (list) delete list;
4205 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4206 if (fAnalysisSource.Length()) {
4207 TObjArray *list = fAnalysisSource.Tokenize(" ");
4210 while((str=(TObjString*)next())) {
4211 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4213 if (list) delete list;
4217 if (fFastReadOption) {
4218 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 !!!");
4219 out << "// fast xrootd reading enabled" << endl;
4220 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4221 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4222 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4223 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4224 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4225 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4227 // Change temp directory to current one
4228 out << "// Set temporary merging directory to current one" << endl;
4229 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4230 out << "// Set temporary compilation directory to current one" << endl;
4231 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4232 out << "// Connect to AliEn" << endl;
4233 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4234 out << " TString outputDir = dir;" << endl;
4235 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4236 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4237 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4238 out << " TIter *iter = new TIter(list);" << endl;
4239 out << " TObjString *str;" << endl;
4240 out << " TString outputFile;" << endl;
4241 out << " Bool_t merged = kTRUE;" << endl;
4242 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4243 out << " outputFile = str->GetString();" << endl;
4244 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4245 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4246 out << " if (index > 0) outputFile.Remove(index);" << endl;
4247 out << " // Skip already merged outputs" << endl;
4248 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4249 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4250 out << " continue;" << endl;
4251 out << " }" << endl;
4252 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4253 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4254 out << " if (!merged) {" << endl;
4255 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4256 out << " return;" << endl;
4257 out << " }" << endl;
4258 out << " }" << endl;
4259 out << " // all outputs merged, validate" << endl;
4260 out << " ofstream out;" << endl;
4261 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4262 out << " out.close();" << endl;
4263 out << " // read the analysis manager from file" << endl;
4264 TString analysisFile = fExecutable;
4265 analysisFile.ReplaceAll(".sh", ".root");
4266 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4267 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4268 << analysisFile << "\");" << endl;
4269 out << " if (!mgr) return;" << endl;
4270 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4271 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4272 out << " mgr->PrintStatus();" << endl;
4273 if (AliAnalysisManager::GetAnalysisManager()) {
4274 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4275 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4277 if (TestBit(AliAnalysisGrid::kTest))
4278 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4280 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4283 out << " TTree *tree = NULL;" << endl;
4284 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4285 out << "}" << endl << endl;
4286 if (hasANALYSISalice) {
4287 out <<"//________________________________________________________________________________" << endl;
4288 out << "Bool_t SetupPar(const char *package) {" << endl;
4289 out << "// Compile the package and set it up." << endl;
4290 out << " TString pkgdir = package;" << endl;
4291 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4292 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4293 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4294 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4295 out << " // Check for BUILD.sh and execute" << endl;
4296 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4297 out << " printf(\"*******************************\\n\");" << endl;
4298 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4299 out << " printf(\"*******************************\\n\");" << endl;
4300 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4301 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4302 out << " gSystem->ChangeDirectory(cdir);" << endl;
4303 out << " return kFALSE;" << endl;
4304 out << " }" << endl;
4305 out << " } else {" << endl;
4306 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4307 out << " gSystem->ChangeDirectory(cdir);" << endl;
4308 out << " return kFALSE;" << endl;
4309 out << " }" << endl;
4310 out << " // Check for SETUP.C and execute" << endl;
4311 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4312 out << " printf(\"*******************************\\n\");" << endl;
4313 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4314 out << " printf(\"*******************************\\n\");" << endl;
4315 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4316 out << " } else {" << endl;
4317 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4318 out << " gSystem->ChangeDirectory(cdir);" << endl;
4319 out << " return kFALSE;" << endl;
4320 out << " }" << endl;
4321 out << " // Restore original workdir" << endl;
4322 out << " gSystem->ChangeDirectory(cdir);" << endl;
4323 out << " return kTRUE;" << endl;
4327 Bool_t copy = kTRUE;
4328 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4331 TString workdir = gGrid->GetHomeDirectory();
4332 workdir += fGridWorkingDir;
4333 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4334 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4335 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4336 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4337 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4341 //______________________________________________________________________________
4342 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4344 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4345 // Note that for loading the compiled library. The current directory should have precedence in
4347 TString pkgdir = package;
4348 pkgdir.ReplaceAll(".par","");
4349 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4350 TString cdir = gSystem->WorkingDirectory();
4351 gSystem->ChangeDirectory(pkgdir);
4352 // Check for BUILD.sh and execute
4353 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4354 printf("**************************************************\n");
4355 printf("*** Building PAR archive %s\n", package);
4356 printf("**************************************************\n");
4357 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4358 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4359 gSystem->ChangeDirectory(cdir);
4363 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4364 gSystem->ChangeDirectory(cdir);
4367 // Check for SETUP.C and execute
4368 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4369 printf("**************************************************\n");
4370 printf("*** Setup PAR archive %s\n", package);
4371 printf("**************************************************\n");
4372 gROOT->Macro("PROOF-INF/SETUP.C");
4373 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4375 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4376 gSystem->ChangeDirectory(cdir);
4379 // Restore original workdir
4380 gSystem->ChangeDirectory(cdir);
4384 //______________________________________________________________________________
4385 void AliAnalysisAlien::WriteExecutable()
4387 // Generate the alien executable script.
4388 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4390 out.open(fExecutable.Data(), ios::out);
4392 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4395 out << "#!/bin/bash" << endl;
4396 // Make sure we can properly compile par files
4397 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4398 out << "echo \"=========================================\"" << endl;
4399 out << "echo \"############## PATH : ##############\"" << endl;
4400 out << "echo $PATH" << endl;
4401 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4402 out << "echo $LD_LIBRARY_PATH" << endl;
4403 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4404 out << "echo $ROOTSYS" << endl;
4405 out << "echo \"############## which root : ##############\"" << endl;
4406 out << "which root" << endl;
4407 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4408 out << "echo $ALICE_ROOT" << endl;
4409 out << "echo \"############## which aliroot : ##############\"" << endl;
4410 out << "which aliroot" << endl;
4411 out << "echo \"############## system limits : ##############\"" << endl;
4412 out << "ulimit -a" << endl;
4413 out << "echo \"############## memory : ##############\"" << endl;
4414 out << "free -m" << endl;
4415 out << "echo \"=========================================\"" << endl << endl;
4416 out << fExecutableCommand << " ";
4417 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4418 out << "RET=$?" << endl;
4419 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4420 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4421 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4422 out << " let sig=\"$RET - 128\""<<endl;
4423 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4424 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4425 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4426 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4427 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4428 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4430 out << " exit $RET"<< endl;
4431 out << "fi" << endl << endl ;
4432 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4433 out << "echo \"############## memory after: ##############\"" << endl;
4434 out << "free -m" << endl;
4436 Bool_t copy = kTRUE;
4437 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4440 TString workdir = gGrid->GetHomeDirectory();
4441 TString bindir = Form("%s/bin", workdir.Data());
4442 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4443 workdir += fGridWorkingDir;
4444 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4445 if (FileExists(executable)) gGrid->Rm(executable);
4446 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4447 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4448 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4449 executable.Data())) Fatal("","Terminating");
4453 //______________________________________________________________________________
4454 void AliAnalysisAlien::WriteMergeExecutable()
4456 // Generate the alien executable script for the merging job.
4457 if (!fMergeViaJDL) return;
4458 TString mergeExec = fExecutable;
4459 mergeExec.ReplaceAll(".sh", "_merge.sh");
4460 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4462 out.open(mergeExec.Data(), ios::out);
4464 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4467 out << "#!/bin/bash" << endl;
4468 // Make sure we can properly compile par files
4469 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4470 out << "echo \"=========================================\"" << endl;
4471 out << "echo \"############## PATH : ##############\"" << endl;
4472 out << "echo $PATH" << endl;
4473 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4474 out << "echo $LD_LIBRARY_PATH" << endl;
4475 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4476 out << "echo $ROOTSYS" << endl;
4477 out << "echo \"############## which root : ##############\"" << endl;
4478 out << "which root" << endl;
4479 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4480 out << "echo $ALICE_ROOT" << endl;
4481 out << "echo \"############## which aliroot : ##############\"" << endl;
4482 out << "which aliroot" << endl;
4483 out << "echo \"############## system limits : ##############\"" << endl;
4484 out << "ulimit -a" << endl;
4485 out << "echo \"############## memory : ##############\"" << endl;
4486 out << "free -m" << endl;
4487 out << "echo \"=========================================\"" << endl << endl;
4488 TString mergeMacro = fExecutable;
4489 mergeMacro.ReplaceAll(".sh", "_merge.C");
4490 if (IsOneStageMerging())
4491 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4493 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4494 out << fExecutableCommand << " " << "$ARG" << endl;
4495 out << "RET=$?" << endl;
4496 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4497 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4498 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4499 out << " let sig=\"$RET - 128\""<<endl;
4500 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4501 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4502 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4503 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4504 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4505 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4507 out << " exit $RET"<< endl;
4508 out << "fi" << endl << endl ;
4509 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4510 out << "echo \"############## memory after: ##############\"" << endl;
4511 out << "free -m" << endl;
4513 Bool_t copy = kTRUE;
4514 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4517 TString workdir = gGrid->GetHomeDirectory();
4518 TString bindir = Form("%s/bin", workdir.Data());
4519 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4520 workdir += fGridWorkingDir;
4521 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4522 if (FileExists(executable)) gGrid->Rm(executable);
4523 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4524 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4525 if (!copyLocal2Alien("WriteMergeExecutable",
4526 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4530 //______________________________________________________________________________
4531 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4533 // Write the production file to be submitted by LPM manager. The format is:
4534 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4535 // Next lines: full_path_to_dataset XXX (XXX is a string)
4536 // To submit, one has to: submit jdl XXX for all lines
4538 out.open(filename, ios::out);
4540 Error("WriteProductionFile", "Bad file name: %s", filename);
4544 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4545 workdir = gGrid->GetHomeDirectory();
4546 workdir += fGridWorkingDir;
4547 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4548 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4549 out << locjdl << " " << njobspermaster << endl;
4550 Int_t nmasterjobs = fInputFiles->GetEntries();
4551 for (Int_t i=0; i<nmasterjobs; i++) {
4552 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4553 runOutDir.ReplaceAll(".xml", "");
4555 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4557 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4560 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4561 if (FileExists(filename)) gGrid->Rm(filename);
4562 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4563 if (!copyLocal2Alien("WriteProductionFile", filename,
4564 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4568 //______________________________________________________________________________
4569 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4571 // Generate the alien validation script.
4572 // Generate the validation script
4574 if (fValidationScript.IsNull()) {
4575 fValidationScript = fExecutable;
4576 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4578 TString validationScript = fValidationScript;
4579 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4581 Error("WriteValidationScript", "Alien connection required");
4584 if (!fTerminateFiles.IsNull()) {
4585 fTerminateFiles.Strip();
4586 fTerminateFiles.ReplaceAll(" ",",");
4588 TString outStream = "";
4589 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4590 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4592 out.open(validationScript, ios::out);
4593 out << "#!/bin/bash" << endl;
4594 out << "##################################################" << endl;
4595 out << "validateout=`dirname $0`" << endl;
4596 out << "validatetime=`date`" << endl;
4597 out << "validated=\"0\";" << endl;
4598 out << "error=0" << endl;
4599 out << "if [ -z $validateout ]" << endl;
4600 out << "then" << endl;
4601 out << " validateout=\".\"" << endl;
4602 out << "fi" << endl << endl;
4603 out << "cd $validateout;" << endl;
4604 out << "validateworkdir=`pwd`;" << endl << endl;
4605 out << "echo \"*******************************************************\"" << outStream << endl;
4606 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4608 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4609 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4610 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4611 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4612 out << "ls -la ./" << outStream << endl;
4613 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4614 out << "##################################################" << endl;
4617 out << "if [ ! -f stderr ] ; then" << endl;
4618 out << " error=1" << endl;
4619 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4620 out << " echo \"Error = $error\" " << outStream << endl;
4621 out << "fi" << endl;
4623 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4624 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4625 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4626 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4629 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4630 out << " error=1" << endl;
4631 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4632 out << " echo \"$parArch\" " << outStream << endl;
4633 out << " echo \"Error = $error\" " << outStream << endl;
4634 out << "fi" << endl;
4636 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4637 out << " error=1" << endl;
4638 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4639 out << " echo \"$segViol\" " << outStream << endl;
4640 out << " echo \"Error = $error\" " << outStream << endl;
4641 out << "fi" << endl;
4643 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4644 out << " error=1" << endl;
4645 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4646 out << " echo \"$segFault\" " << outStream << endl;
4647 out << " echo \"Error = $error\" " << outStream << endl;
4648 out << "fi" << endl;
4650 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4651 out << " error=1" << endl;
4652 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4653 out << " echo \"$glibcErr\" " << outStream << endl;
4654 out << " echo \"Error = $error\" " << outStream << endl;
4655 out << "fi" << endl;
4657 // Part dedicated to the specific analyses running into the train
4659 TString outputFiles = fOutputFiles;
4660 if (merge && !fTerminateFiles.IsNull()) {
4662 outputFiles += fTerminateFiles;
4664 TObjArray *arr = outputFiles.Tokenize(",");
4667 while (!merge && (os=(TObjString*)next1())) {
4668 // No need to validate outputs produced by merging since the merging macro does this
4669 outputFile = os->GetString();
4670 Int_t index = outputFile.Index("@");
4671 if (index > 0) outputFile.Remove(index);
4672 if (fTerminateFiles.Contains(outputFile)) continue;
4673 if (outputFile.Contains("*")) continue;
4674 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4675 out << " error=1" << endl;
4676 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4677 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4678 out << "fi" << endl;
4681 out << "if ! [ -f outputs_valid ] ; then" << endl;
4682 out << " error=1" << endl;
4683 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4684 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4685 out << "fi" << endl;
4687 out << "if [ $error = 0 ] ; then" << endl;
4688 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4689 if (!IsKeepLogs()) {
4690 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4692 out << " rm -f std*" << endl;
4694 out << "fi" << endl;
4696 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4697 out << "echo \"*******************************************************\"" << outStream << endl;
4698 out << "cd -" << endl;
4699 out << "exit $error" << endl;
4701 Bool_t copy = kTRUE;
4702 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4705 TString workdir = gGrid->GetHomeDirectory();
4706 workdir += fGridWorkingDir;
4707 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4708 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4709 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4710 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4711 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");