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 esdFile.ReplaceAll("AliAOD.root", fFriendChainName.Data());
2245 esdFile.ReplaceAll("AliAODs.root", fFriendChainName.Data());
2246 file = TFile::Open(esdFile);
2247 if (file && !file->IsZombie()) {
2249 chainFriend->Add(esdFile);
2251 Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2256 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2260 if (!chain->GetListOfFiles()->GetEntries()) {
2261 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2267 if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2271 //______________________________________________________________________________
2272 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2274 // Get job status for all jobs with jobid>jobidstart.
2275 static char mstatus[20];
2281 TGridJobStatusList *list = gGrid->Ps("");
2282 if (!list) return mstatus;
2283 Int_t nentries = list->GetSize();
2284 TGridJobStatus *status;
2286 for (Int_t ijob=0; ijob<nentries; ijob++) {
2287 status = (TGridJobStatus *)list->At(ijob);
2288 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2289 if (pid<jobidstart) continue;
2290 if (pid == lastid) {
2291 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2293 switch (status->GetStatus()) {
2294 case TGridJobStatus::kWAITING:
2296 case TGridJobStatus::kRUNNING:
2298 case TGridJobStatus::kABORTED:
2299 case TGridJobStatus::kFAIL:
2300 case TGridJobStatus::kUNKNOWN:
2302 case TGridJobStatus::kDONE:
2311 //______________________________________________________________________________
2312 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2314 // Returns true if file is a collection. Functionality duplicated from
2315 // TAlien::Type() because we don't want to directly depend on TAlien.
2317 Error("IsCollection", "No connection to grid");
2320 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2321 if (!res) return kFALSE;
2322 const char* typeStr = res->GetKey(0, "type");
2323 if (!typeStr || !strlen(typeStr)) return kFALSE;
2324 if (!strcmp(typeStr, "collection")) return kTRUE;
2329 //______________________________________________________________________________
2330 Bool_t AliAnalysisAlien::IsSingleOutput() const
2332 // Check if single-ouput option is on.
2333 return (!fOutputSingle.IsNull());
2336 //______________________________________________________________________________
2337 void AliAnalysisAlien::Print(Option_t *) const
2339 // Print current plugin settings.
2340 printf("### AliEn analysis plugin current settings ###\n");
2341 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2342 if (mgr && mgr->IsProofMode()) {
2343 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2344 if (TestBit(AliAnalysisGrid::kTest))
2345 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2346 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2347 if (!fProofDataSet.IsNull())
2348 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2350 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2352 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2353 if (!fRootVersionForProof.IsNull())
2354 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2356 printf("= ROOT version requested________________________ default\n");
2357 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2358 if (!fAliRootMode.IsNull())
2359 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2361 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2362 if (fNproofWorkersPerSlave)
2363 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2364 if (TestSpecialBit(kClearPackages))
2365 printf("= ClearPackages requested...\n");
2366 if (fIncludePath.Data())
2367 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2368 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2369 if (fPackages && fPackages->GetEntries()) {
2370 TIter next(fPackages);
2373 while ((obj=next())) list += obj->GetName();
2374 printf("= Par files to be used: ________________________ %s\n", list.Data());
2376 if (TestSpecialBit(kProofConnectGrid))
2377 printf("= Requested PROOF connection to grid\n");
2380 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2381 if (fOverwriteMode) {
2382 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2383 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2385 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2386 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2387 printf("= Production mode:______________________________ %d\n", fProductionMode);
2388 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2389 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2390 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2392 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2393 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2394 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2395 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2396 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2397 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2398 if (fRunNumbers.Length())
2399 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2401 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2402 if (!fRunRange[0] && !fRunNumbers.Length()) {
2403 TIter next(fInputFiles);
2406 while ((obj=next())) list += obj->GetName();
2407 printf("= Input files to be processed: _________________ %s\n", list.Data());
2409 if (TestBit(AliAnalysisGrid::kTest))
2410 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2411 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2412 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2413 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2414 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2415 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2416 printf("=====================================================================\n");
2417 printf("= Job price: ___________________________________ %d\n", fPrice);
2418 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2419 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2420 if (fMaxInitFailed>0)
2421 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2422 if (fMasterResubmitThreshold>0)
2423 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2424 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2425 if (fNrunsPerMaster>0)
2426 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2427 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2428 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2429 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2430 if (fArguments.Length())
2431 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2432 if (fExecutableArgs.Length())
2433 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2434 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2435 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2436 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2437 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2439 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2440 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2441 if (fIncludePath.Data())
2442 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2443 if (fCloseSE.Length())
2444 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2445 if (fFriendChainName.Length())
2446 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2447 if (fPackages && fPackages->GetEntries()) {
2448 TIter next(fPackages);
2451 while ((obj=next())) list += obj->GetName();
2452 printf("= Par files to be used: ________________________ %s\n", list.Data());
2456 //______________________________________________________________________________
2457 void AliAnalysisAlien::SetDefaults()
2459 // Set default values for everything. What cannot be filled will be left empty.
2460 if (fGridJDL) delete fGridJDL;
2461 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2462 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2465 fSplitMaxInputFileNumber = 100;
2467 fMasterResubmitThreshold = 0;
2473 fNrunsPerMaster = 1;
2474 fMaxMergeFiles = 100;
2476 fExecutable = "analysis.sh";
2477 fExecutableCommand = "root -b -q";
2479 fExecutableArgs = "";
2480 fAnalysisMacro = "myAnalysis.C";
2481 fAnalysisSource = "";
2482 fAdditionalLibs = "";
2486 fAliROOTVersion = "";
2487 fUser = ""; // Your alien user name
2488 fGridWorkingDir = "";
2489 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2490 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2491 fFriendChainName = "";
2492 fGridOutputDir = "output";
2493 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2494 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2495 fInputFormat = "xml-single";
2496 fJDLName = "analysis.jdl";
2497 fJobTag = "Automatically generated analysis JDL";
2498 fMergeExcludes = "";
2501 SetCheckCopy(kTRUE);
2502 SetDefaultOutputs(kTRUE);
2506 //______________________________________________________________________________
2507 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2509 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2510 // First check if the result is already in the output directory.
2511 if (FileExists(Form("%s/%s",aliendir,filename))) {
2512 printf("Final merged results found. Not merging again.\n");
2515 // Now check the last stage done.
2518 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2521 // Next stage of merging
2523 TString pattern = "*root_archive.zip";
2524 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2525 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2526 if (res) delete res;
2527 // Write standard output to file
2528 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2529 // Count the number of files inside
2531 ifile.open(Form("Stage_%d.xml",stage));
2532 if (!ifile.good()) {
2533 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2538 while (!ifile.eof()) {
2540 if (line.Contains("/event")) nfiles++;
2544 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2547 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2549 // Copy the file in the output directory
2550 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2551 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2552 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2553 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2554 // Check if this is the last stage to be done.
2555 Bool_t laststage = (nfiles<nperchunk);
2556 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2558 printf("### Submiting final merging stage %d\n", stage);
2559 TString finalJDL = jdl;
2560 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2561 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2562 Int_t jobId = SubmitSingleJob(query);
2563 if (!jobId) return kFALSE;
2565 printf("### Submiting merging stage %d\n", stage);
2566 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2567 Int_t jobId = SubmitSingleJob(query);
2568 if (!jobId) return kFALSE;
2573 //______________________________________________________________________________
2574 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2576 // Loat the analysis manager from a file.
2577 TFile *file = TFile::Open(fname);
2579 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2582 TIter nextkey(file->GetListOfKeys());
2583 AliAnalysisManager *mgr = 0;
2585 while ((key=(TKey*)nextkey())) {
2586 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2587 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2590 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2594 //______________________________________________________________________________
2595 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2597 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2598 if (!gGrid) return 0;
2599 printf("=> %s ------> ",query);
2600 TGridResult *res = gGrid->Command(query);
2602 TString jobId = res->GetKey(0,"jobId");
2604 if (jobId.IsNull()) {
2605 printf("submission failed. Reason:\n");
2608 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2611 printf(" Job id: %s\n", jobId.Data());
2615 //______________________________________________________________________________
2616 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2618 // Merge given output files from basedir. Basedir can be an alien output directory
2619 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2620 // files in a group (ignored for xml input). Merging can be done in stages:
2621 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2622 // stage=1 : works with an xml of all root_archive.zip in the output directory
2623 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2624 TString outputFile = output;
2626 TString outputChunk;
2627 TString previousChunk = "";
2628 TObjArray *listoffiles = new TObjArray();
2629 // listoffiles->SetOwner();
2630 Int_t countChunk = 0;
2631 Int_t countZero = nmaxmerge;
2632 Bool_t merged = kTRUE;
2633 Int_t index = outputFile.Index("@");
2634 if (index > 0) outputFile.Remove(index);
2635 TString inputFile = outputFile;
2636 TString sbasedir = basedir;
2637 if (sbasedir.Contains(".xml")) {
2638 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2639 nmaxmerge = 9999999;
2640 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2642 ::Error("MergeOutput", "Input XML collection empty.");
2645 // Iterate grid collection
2646 while (coll->Next()) {
2647 TString fname = gSystem->DirName(coll->GetTURL());
2650 listoffiles->Add(new TNamed(fname.Data(),""));
2653 command = Form("find %s/ *%s", basedir, inputFile.Data());
2654 printf("command: %s\n", command.Data());
2655 TGridResult *res = gGrid->Command(command);
2657 ::Error("MergeOutput","No result for the find command\n");
2663 while ((map=(TMap*)nextmap())) {
2664 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2665 if (!objs || !objs->GetString().Length()) {
2666 // Nothing found - skip this output
2671 listoffiles->Add(new TNamed(objs->GetName(),""));
2675 if (!listoffiles->GetEntries()) {
2676 ::Error("MergeOutput","No result for the find command\n");
2681 TFileMerger *fm = 0;
2682 TIter next0(listoffiles);
2683 TObjArray *listoffilestmp = new TObjArray();
2684 listoffilestmp->SetOwner();
2687 // Keep only the files at upper level
2688 Int_t countChar = 0;
2689 while ((nextfile=next0())) {
2690 snextfile = nextfile->GetName();
2691 Int_t crtCount = snextfile.CountChar('/');
2692 if (nextfile == listoffiles->First()) countChar = crtCount;
2693 if (crtCount < countChar) countChar = crtCount;
2696 while ((nextfile=next0())) {
2697 snextfile = nextfile->GetName();
2698 Int_t crtCount = snextfile.CountChar('/');
2699 if (crtCount > countChar) {
2703 listoffilestmp->Add(nextfile);
2706 listoffiles = listoffilestmp; // Now contains 'good' files
2707 listoffiles->Print();
2708 TIter next(listoffiles);
2709 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2710 outputChunk = outputFile;
2711 outputChunk.ReplaceAll(".root", "_*.root");
2712 // Check for existent temporary merge files
2713 // Check overwrite mode and remove previous partial results if needed
2714 // Preserve old merging functionality for stage 0.
2716 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2718 // Skip as many input files as in a chunk
2719 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2722 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2726 snextfile = nextfile->GetName();
2728 outputChunk = outputFile;
2729 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2731 if (gSystem->AccessPathName(outputChunk)) continue;
2732 // Merged file with chunks up to <countChunk> found
2733 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2734 previousChunk = outputChunk;
2738 countZero = nmaxmerge;
2740 while ((nextfile=next())) {
2741 snextfile = nextfile->GetName();
2742 // Loop 'find' results and get next LFN
2743 if (countZero == nmaxmerge) {
2744 // First file in chunk - create file merger and add previous chunk if any.
2745 fm = new TFileMerger(kTRUE);
2746 fm->SetFastMethod(kTRUE);
2747 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2748 outputChunk = outputFile;
2749 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2751 // If last file found, put merged results in the output file
2752 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2753 // Add file to be merged and decrement chunk counter.
2754 fm->AddFile(snextfile);
2756 if (countZero==0 || nextfile == listoffiles->Last()) {
2757 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2758 // Nothing found - skip this output
2759 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2763 fm->OutputFile(outputChunk);
2764 // Merge the outputs, then go to next chunk
2766 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2770 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2771 gSystem->Unlink(previousChunk);
2773 if (nextfile == listoffiles->Last()) break;
2775 countZero = nmaxmerge;
2776 previousChunk = outputChunk;
2783 // Merging stage different than 0.
2784 // Move to the begining of the requested chunk.
2785 fm = new TFileMerger(kTRUE);
2786 fm->SetFastMethod(kTRUE);
2787 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2789 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2790 // Nothing found - skip this output
2791 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2795 fm->OutputFile(outputFile);
2796 // Merge the outputs
2798 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2802 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2808 //______________________________________________________________________________
2809 Bool_t AliAnalysisAlien::MergeOutputs()
2811 // Merge analysis outputs existing in the AliEn space.
2812 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2813 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2815 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2819 if (!TestBit(AliAnalysisGrid::kMerge)) {
2820 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2823 if (fProductionMode) {
2824 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2827 Info("MergeOutputs", "Submitting merging JDL");
2828 if (!SubmitMerging()) return kFALSE;
2829 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2830 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2833 // Get the output path
2834 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2835 if (!DirectoryExists(fGridOutputDir)) {
2836 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2839 if (!fOutputFiles.Length()) {
2840 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2843 // Check if fast read option was requested
2844 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2845 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2846 if (fFastReadOption) {
2847 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2848 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2849 gEnv->SetValue("XNet.ConnectTimeout",50);
2850 gEnv->SetValue("XNet.RequestTimeout",50);
2851 gEnv->SetValue("XNet.MaxRedirectCount",2);
2852 gEnv->SetValue("XNet.ReconnectTimeout",50);
2853 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2855 // Make sure we change the temporary directory
2856 gSystem->Setenv("TMPDIR", gSystem->pwd());
2857 // Set temporary compilation directory to current one
2858 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2859 TObjArray *list = fOutputFiles.Tokenize(",");
2863 Bool_t merged = kTRUE;
2864 while((str=(TObjString*)next())) {
2865 outputFile = str->GetString();
2866 Int_t index = outputFile.Index("@");
2867 if (index > 0) outputFile.Remove(index);
2868 TString outputChunk = outputFile;
2869 outputChunk.ReplaceAll(".root", "_*.root");
2870 // Skip already merged outputs
2871 if (!gSystem->AccessPathName(outputFile)) {
2872 if (fOverwriteMode) {
2873 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2874 gSystem->Unlink(outputFile);
2875 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2876 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2877 outputChunk.Data());
2878 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2881 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2885 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2886 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2887 outputChunk.Data());
2888 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2891 if (fMergeExcludes.Contains(outputFile.Data()) ||
2892 fRegisterExcludes.Contains(outputFile.Data())) continue;
2893 // Perform a 'find' command in the output directory, looking for registered outputs
2894 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2896 Error("MergeOutputs", "Terminate() will NOT be executed");
2899 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2900 if (fileOpened) fileOpened->Close();
2905 //______________________________________________________________________________
2906 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2908 // Use the output files connected to output containers from the analysis manager
2909 // rather than the files defined by SetOutputFiles
2910 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2911 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2912 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2915 //______________________________________________________________________________
2916 void AliAnalysisAlien::SetOutputFiles(const char *list)
2918 // Manually set the output files list.
2919 // Removes duplicates. Not allowed if default outputs are not disabled.
2920 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2921 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2924 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2926 TString slist = list;
2927 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2928 TObjArray *arr = slist.Tokenize(" ");
2932 while ((os=(TObjString*)next())) {
2933 sout = os->GetString();
2934 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2935 if (fOutputFiles.Contains(sout)) continue;
2936 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2937 fOutputFiles += sout;
2942 //______________________________________________________________________________
2943 void AliAnalysisAlien::SetOutputArchive(const char *list)
2945 // Manually set the output archive list. Free text - you are on your own...
2946 // Not allowed if default outputs are not disabled.
2947 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2948 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2951 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2952 fOutputArchive = list;
2955 //______________________________________________________________________________
2956 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2958 // Setting a prefered output SE is not allowed anymore.
2959 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2962 //______________________________________________________________________________
2963 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2965 // Set some PROOF special parameter.
2966 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2968 TObject *old = pair->Key();
2969 TObject *val = pair->Value();
2970 fProofParam.Remove(old);
2974 fProofParam.Add(new TObjString(pname), new TObjString(value));
2977 //______________________________________________________________________________
2978 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2980 // Returns a special PROOF parameter.
2981 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2982 if (!pair) return 0;
2983 return pair->Value()->GetName();
2986 //______________________________________________________________________________
2987 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2989 // Start remote grid analysis.
2990 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2991 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2992 if (!mgr || !mgr->IsInitialized()) {
2993 Error("StartAnalysis", "You need an initialized analysis manager for this");
2996 // Are we in PROOF mode ?
2997 if (mgr->IsProofMode()) {
2998 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2999 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3000 if (fProofCluster.IsNull()) {
3001 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3004 if (fProofDataSet.IsNull() && !testMode) {
3005 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3008 // Set the needed environment
3009 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3010 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3011 if (fProofReset && !testMode) {
3012 if (fProofReset==1) {
3013 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3014 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3016 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3017 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3019 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3024 // Check if there is an old active session
3025 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3027 Error("StartAnalysis","You have to reset your old session first\n");
3031 // Do we need to change the ROOT version ? The success of this cannot be checked.
3032 if (!fRootVersionForProof.IsNull() && !testMode) {
3033 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
3034 fProofCluster.Data(), fRootVersionForProof.Data()));
3036 // Connect to PROOF and check the status
3039 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3040 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3042 if (!sworkers.IsNull())
3043 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3045 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3047 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3049 Error("StartAnalysis", "Could not start PROOF in test mode");
3054 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3057 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3058 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3059 // Set proof special parameters if any
3060 TIter nextpp(&fProofParam);
3061 TObject *proofparam;
3062 while ((proofparam=nextpp())) {
3063 TString svalue = GetProofParameter(proofparam->GetName());
3064 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3066 // Is dataset existing ?
3068 TString dataset = fProofDataSet;
3069 Int_t index = dataset.Index("#");
3070 if (index>=0) dataset.Remove(index);
3071 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3072 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3075 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3077 // Is ClearPackages() needed ?
3078 if (TestSpecialBit(kClearPackages)) {
3079 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3080 gROOT->ProcessLine("gProof->ClearPackages();");
3082 // Is a given aliroot mode requested ?
3085 if (!fAliRootMode.IsNull()) {
3086 TString alirootMode = fAliRootMode;
3087 if (alirootMode == "default") alirootMode = "";
3088 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3089 optionsList.SetOwner();
3090 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3091 // Check the additional libs to be loaded
3093 Bool_t parMode = kFALSE;
3094 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3095 // Parse the extra libs for .so
3096 if (fAdditionalLibs.Length()) {
3097 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3100 while((str=(TObjString*)next())) {
3101 if (str->GetString().Contains(".so")) {
3103 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());
3106 TString stmp = str->GetName();
3107 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3108 stmp.ReplaceAll(".so","");
3109 if (!extraLibs.IsNull()) extraLibs += ":";
3113 if (str->GetString().Contains(".par")) {
3114 // The first par file found in the list will not allow any further .so
3116 if (!parLibs.IsNull()) parLibs += ":";
3117 parLibs += str->GetName();
3121 if (list) delete list;
3123 if (!extraLibs.IsNull()) {
3124 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3125 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3127 // Check extra includes
3128 if (!fIncludePath.IsNull()) {
3129 TString includePath = fIncludePath;
3130 includePath.ReplaceAll(" ",":");
3131 includePath.ReplaceAll("$ALICE_ROOT/","");
3132 includePath.ReplaceAll("${ALICE_ROOT}/","");
3133 includePath.ReplaceAll("-I","");
3134 includePath.Remove(TString::kTrailing, ':');
3135 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3136 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3138 // Check if connection to grid is requested
3139 if (TestSpecialBit(kProofConnectGrid))
3140 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3141 // Enable AliRoot par
3143 // Enable proof lite package
3144 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3145 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3146 TNamed *obj = (TNamed*)optionsList.At(i);
3147 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3149 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3150 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3151 Info("StartAnalysis", "AliRootProofLite enabled");
3153 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3157 if ( ! fAliROOTVersion.IsNull() ) {
3158 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3159 fAliROOTVersion.Data(), &optionsList))) {
3160 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3165 // Enable first par files from fAdditionalLibs
3166 if (!parLibs.IsNull()) {
3167 TObjArray *list = parLibs.Tokenize(":");
3169 TObjString *package;
3170 while((package=(TObjString*)next())) {
3171 TString spkg = package->GetName();
3172 spkg.ReplaceAll(".par", "");
3173 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3174 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3175 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3176 if (gROOT->ProcessLine(enablePackage)) {
3177 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3181 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3185 if (list) delete list;
3188 if (fAdditionalLibs.Contains(".so") && !testMode) {
3189 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3190 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3194 // Enable par files if requested
3195 if (fPackages && fPackages->GetEntries()) {
3196 TIter next(fPackages);
3198 while ((package=next())) {
3199 // Skip packages already enabled
3200 if (parLibs.Contains(package->GetName())) continue;
3201 TString spkg = package->GetName();
3202 spkg.ReplaceAll(".par", "");
3203 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3204 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3205 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3206 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3210 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3215 // Do we need to load analysis source files ?
3216 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3217 if (fAnalysisSource.Length()) {
3218 TObjArray *list = fAnalysisSource.Tokenize(" ");
3221 while((str=(TObjString*)next())) {
3222 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3224 if (list) delete list;
3227 // Register dataset to proof lite.
3228 if (fFileForTestMode.IsNull()) {
3229 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3232 if (gSystem->AccessPathName(fFileForTestMode)) {
3233 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3236 TFileCollection *coll = new TFileCollection();
3237 coll->AddFromFile(fFileForTestMode);
3238 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3239 gROOT->ProcessLine("gProof->ShowDataSets()");
3244 // Check if output files have to be taken from the analysis manager
3245 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3246 // Add output files and AOD files
3247 fOutputFiles = GetListOfFiles("outaod");
3248 // Add extra files registered to the analysis manager
3249 TString extra = GetListOfFiles("ext");
3250 if (!extra.IsNull()) {
3251 extra.ReplaceAll(".root", "*.root");
3252 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3253 fOutputFiles += extra;
3255 // Compose the output archive.
3256 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3257 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3259 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3260 if (TestBit(AliAnalysisGrid::kOffline)) {
3261 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3262 \n there nor any job run. You can revise the JDL and analysis \
3263 \n macro then run the same in \"submit\" mode.");
3264 } else if (TestBit(AliAnalysisGrid::kTest)) {
3265 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3267 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3268 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3269 \n space and job submitted.");
3270 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3271 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3272 if (fMergeViaJDL) CheckInputData();
3275 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3280 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3283 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3284 if (!CheckInputData()) {
3285 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3288 if (!CreateDataset(fDataPattern)) {
3290 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3291 if (fRunNumbers.Length()) serror = "run numbers";
3292 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3293 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3294 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3297 WriteAnalysisFile();
3298 WriteAnalysisMacro();
3300 WriteValidationScript();
3302 WriteMergingMacro();
3303 WriteMergeExecutable();
3304 WriteValidationScript(kTRUE);
3306 if (!CreateJDL()) return kFALSE;
3307 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3309 // Locally testing the analysis
3310 Info("StartAnalysis", "\n_______________________________________________________________________ \
3311 \n Running analysis script in a daughter shell as on a worker node \
3312 \n_______________________________________________________________________");
3313 TObjArray *list = fOutputFiles.Tokenize(",");
3317 while((str=(TObjString*)next())) {
3318 outputFile = str->GetString();
3319 Int_t index = outputFile.Index("@");
3320 if (index > 0) outputFile.Remove(index);
3321 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3324 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3325 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3326 // gSystem->Exec("cat stdout");
3329 // Check if submitting is managed by LPM manager
3330 if (fProductionMode) {
3331 TString prodfile = fJDLName;
3332 prodfile.ReplaceAll(".jdl", ".prod");
3333 WriteProductionFile(prodfile);
3334 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3337 // Submit AliEn job(s)
3338 gGrid->Cd(fGridOutputDir);
3341 if (!fRunNumbers.Length() && !fRunRange[0]) {
3342 // Submit a given xml or a set of runs
3343 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3344 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3346 const char *cjobId = res->GetKey(0,"jobId");
3350 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3353 Info("StartAnalysis", "\n_______________________________________________________________________ \
3354 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3355 \n_______________________________________________________________________",
3356 fJDLName.Data(), cjobId);
3361 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3365 // Submit for a range of enumeration of runs.
3366 if (!Submit()) return kFALSE;
3369 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3370 \n You may exit at any time and terminate the job later using the option <terminate> \
3371 \n ##################################################################################", jobID.Data());
3372 gSystem->Exec("aliensh");
3376 //______________________________________________________________________________
3377 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3379 // Get a comma-separated list of output files of the requested type.
3380 // Type can be (case unsensitive):
3381 // aod - list of aod files (std, extensions and filters)
3382 // out - list of output files connected to containers (but not aod's or extras)
3383 // ext - list of extra files registered to the manager
3384 // ter - list of files produced in terminate
3385 static TString files;
3387 TString stype = type;
3389 TString aodfiles, extra;
3390 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3392 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3393 return files.Data();
3395 if (mgr->GetOutputEventHandler()) {
3396 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3397 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3398 if (!extraaod.IsNull()) {
3400 aodfiles += extraaod;
3403 if (stype.Contains("aod")) {
3405 if (stype == "aod") return files.Data();
3407 // Add output files that are not in the list of AOD files
3408 TString outputfiles = "";
3409 TIter next(mgr->GetOutputs());
3410 AliAnalysisDataContainer *output;
3411 const char *filename = 0;
3412 while ((output=(AliAnalysisDataContainer*)next())) {
3413 filename = output->GetFileName();
3414 if (!(strcmp(filename, "default"))) continue;
3415 if (outputfiles.Contains(filename)) continue;
3416 if (aodfiles.Contains(filename)) continue;
3417 if (!outputfiles.IsNull()) outputfiles += ",";
3418 outputfiles += filename;
3420 if (stype.Contains("out")) {
3421 if (!files.IsNull()) files += ",";
3422 files += outputfiles;
3423 if (stype == "out") return files.Data();
3425 // Add extra files registered to the analysis manager
3427 extra = mgr->GetExtraFiles();
3428 if (!extra.IsNull()) {
3430 extra.ReplaceAll(" ", ",");
3431 TObjArray *fextra = extra.Tokenize(",");
3432 TIter nextx(fextra);
3434 while ((obj=nextx())) {
3435 if (aodfiles.Contains(obj->GetName())) continue;
3436 if (outputfiles.Contains(obj->GetName())) continue;
3437 if (sextra.Contains(obj->GetName())) continue;
3438 if (!sextra.IsNull()) sextra += ",";
3439 sextra += obj->GetName();
3442 if (stype.Contains("ext")) {
3443 if (!files.IsNull()) files += ",";
3447 if (stype == "ext") return files.Data();
3449 if (!fTerminateFiles.IsNull()) {
3450 fTerminateFiles.Strip();
3451 fTerminateFiles.ReplaceAll(" ",",");
3452 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3453 TIter nextx(fextra);
3455 while ((obj=nextx())) {
3456 if (aodfiles.Contains(obj->GetName())) continue;
3457 if (outputfiles.Contains(obj->GetName())) continue;
3458 if (termfiles.Contains(obj->GetName())) continue;
3459 if (sextra.Contains(obj->GetName())) continue;
3460 if (!termfiles.IsNull()) termfiles += ",";
3461 termfiles += obj->GetName();
3465 if (stype.Contains("ter")) {
3466 if (!files.IsNull() && !termfiles.IsNull()) {
3471 return files.Data();
3474 //______________________________________________________________________________
3475 Bool_t AliAnalysisAlien::Submit()
3477 // Submit all master jobs.
3478 Int_t nmasterjobs = fInputFiles->GetEntries();
3479 Long_t tshoot = gSystem->Now();
3480 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3481 while (fNsubmitted < nmasterjobs) {
3482 Long_t now = gSystem->Now();
3483 if ((now-tshoot)>30000) {
3485 if (!SubmitNext()) return kFALSE;
3491 //______________________________________________________________________________
3492 Bool_t AliAnalysisAlien::SubmitMerging()
3494 // Submit all merging jobs.
3495 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3496 gGrid->Cd(fGridOutputDir);
3497 TString mergeJDLName = fExecutable;
3498 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3500 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3503 Int_t ntosubmit = fInputFiles->GetEntries();
3504 for (Int_t i=0; i<ntosubmit; i++) {
3505 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3506 runOutDir.ReplaceAll(".xml", "");
3507 if (fOutputToRunNo) {
3508 // The output directory is the run number
3509 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3510 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3512 if (!fRunNumbers.Length() && !fRunRange[0]) {
3513 // The output directory is the grid outdir
3514 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3515 runOutDir = fGridOutputDir;
3517 // The output directory is the master number in 3 digits format
3518 printf("### Submitting merging job for master <%03d>\n", i);
3519 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3522 // Check now the number of merging stages.
3523 TObjArray *list = fOutputFiles.Tokenize(",");
3527 while((str=(TObjString*)next())) {
3528 outputFile = str->GetString();
3529 Int_t index = outputFile.Index("@");
3530 if (index > 0) outputFile.Remove(index);
3531 if (!fMergeExcludes.Contains(outputFile) &&
3532 !fRegisterExcludes.Contains(outputFile)) break;
3535 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3536 if (!done && (i==ntosubmit-1)) return kFALSE;
3537 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3539 if (!ntosubmit) return kTRUE;
3540 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3541 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3542 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3543 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3544 \n ################################################################################################################");
3545 gSystem->Exec("aliensh");
3549 //______________________________________________________________________________
3550 Bool_t AliAnalysisAlien::SubmitNext()
3552 // Submit next bunch of master jobs if the queue is free. The first master job is
3553 // submitted right away, while the next will not be unless the previous was split.
3554 // The plugin will not submit new master jobs if there are more that 500 jobs in
3556 static Bool_t iscalled = kFALSE;
3557 static Int_t firstmaster = 0;
3558 static Int_t lastmaster = 0;
3559 static Int_t npermaster = 0;
3560 if (iscalled) return kTRUE;
3562 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3563 Int_t ntosubmit = 0;
3566 Int_t nmasterjobs = fInputFiles->GetEntries();
3569 if (!IsUseSubmitPolicy()) {
3571 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3572 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3573 ntosubmit = nmasterjobs;
3576 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3577 printf("=== master %d: %s\n", lastmaster, status.Data());
3578 // If last master not split, just return
3579 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3580 // No more than 100 waiting jobs
3581 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3582 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3583 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3584 if (!ntosubmit) ntosubmit = 1;
3585 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3586 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3588 for (Int_t i=0; i<ntosubmit; i++) {
3589 // Submit for a range of enumeration of runs.
3590 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3592 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3593 runOutDir.ReplaceAll(".xml", "");
3595 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3597 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3598 printf("********* %s\n",query.Data());
3599 res = gGrid->Command(query);
3601 TString cjobId1 = res->GetKey(0,"jobId");
3602 if (!cjobId1.Length()) {
3606 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3609 Info("StartAnalysis", "\n_______________________________________________________________________ \
3610 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3611 \n_______________________________________________________________________",
3612 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3615 lastmaster = cjobId1.Atoi();
3616 if (!firstmaster) firstmaster = lastmaster;
3621 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3629 //______________________________________________________________________________
3630 void AliAnalysisAlien::WriteAnalysisFile()
3632 // Write current analysis manager into the file <analysisFile>
3633 TString analysisFile = fExecutable;
3634 analysisFile.ReplaceAll(".sh", ".root");
3635 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3636 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3637 if (!mgr || !mgr->IsInitialized()) {
3638 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3641 // Check analysis type
3643 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3644 handler = (TObject*)mgr->GetInputEventHandler();
3646 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3647 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3648 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3649 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3651 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3652 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3655 TDirectory *cdir = gDirectory;
3656 TFile *file = TFile::Open(analysisFile, "RECREATE");
3658 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3659 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3660 // Unless merging makes no sense
3661 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3664 // Enable termination for local jobs
3665 mgr->SetSkipTerminate(kFALSE);
3667 if (cdir) cdir->cd();
3668 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3670 Bool_t copy = kTRUE;
3671 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3674 TString workdir = gGrid->GetHomeDirectory();
3675 workdir += fGridWorkingDir;
3676 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3677 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3678 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3679 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3683 //______________________________________________________________________________
3684 void AliAnalysisAlien::WriteAnalysisMacro()
3686 // Write the analysis macro that will steer the analysis in grid mode.
3687 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3689 out.open(fAnalysisMacro.Data(), ios::out);
3691 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3694 Bool_t hasSTEERBase = kFALSE;
3695 Bool_t hasESD = kFALSE;
3696 Bool_t hasAOD = kFALSE;
3697 Bool_t hasANALYSIS = kFALSE;
3698 Bool_t hasOADB = kFALSE;
3699 Bool_t hasANALYSISalice = kFALSE;
3700 Bool_t hasCORRFW = kFALSE;
3701 TString func = fAnalysisMacro;
3702 TString type = "ESD";
3703 TString comment = "// Analysis using ";
3704 if (IsUseMCchain()) {
3708 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3709 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3714 if (type!="AOD" && fFriendChainName!="") {
3715 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3718 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3719 else comment += " data";
3720 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3721 func.ReplaceAll(".C", "");
3722 out << "void " << func.Data() << "()" << endl;
3724 out << comment.Data() << endl;
3725 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3726 out << " TStopwatch timer;" << endl;
3727 out << " timer.Start();" << endl << endl;
3728 // Change temp directory to current one
3729 out << "// Set temporary merging directory to current one" << endl;
3730 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3731 out << "// Set temporary compilation directory to current one" << endl;
3732 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3733 // Reset existing include path
3734 out << "// Reset existing include path and add current directory first in the search" << endl;
3735 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3736 if (!fExecutableCommand.Contains("aliroot")) {
3737 out << "// load base root libraries" << endl;
3738 out << " gSystem->Load(\"libTree\");" << endl;
3739 out << " gSystem->Load(\"libGeom\");" << endl;
3740 out << " gSystem->Load(\"libVMC\");" << endl;
3741 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3742 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3744 if (fAdditionalRootLibs.Length()) {
3745 // in principle libtree /lib geom libvmc etc. can go into this list, too
3746 out << "// Add aditional libraries" << endl;
3747 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3750 while((str=(TObjString*)next())) {
3751 if (str->GetString().Contains(".so"))
3752 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3754 if (list) delete list;
3756 out << "// Load analysis framework libraries" << endl;
3757 TString setupPar = "AliAnalysisAlien::SetupPar";
3759 if (!fExecutableCommand.Contains("aliroot")) {
3760 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3761 out << " gSystem->Load(\"libESD\");" << endl;
3762 out << " gSystem->Load(\"libAOD\");" << endl;
3764 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3765 out << " gSystem->Load(\"libOADB\");" << endl;
3766 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3767 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3769 TIter next(fPackages);
3772 while ((obj=next())) {
3773 pkgname = obj->GetName();
3774 if (pkgname == "STEERBase" ||
3775 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3776 if (pkgname == "ESD" ||
3777 pkgname == "ESD.par") hasESD = kTRUE;
3778 if (pkgname == "AOD" ||
3779 pkgname == "AOD.par") hasAOD = kTRUE;
3780 if (pkgname == "ANALYSIS" ||
3781 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3782 if (pkgname == "OADB" ||
3783 pkgname == "OADB.par") hasOADB = kTRUE;
3784 if (pkgname == "ANALYSISalice" ||
3785 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3786 if (pkgname == "CORRFW" ||
3787 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3789 if (hasANALYSISalice) setupPar = "SetupPar";
3790 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3791 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3792 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3793 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3794 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3795 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3796 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3797 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3798 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3799 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3800 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3801 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3802 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3803 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3804 out << "// Compile other par packages" << endl;
3806 while ((obj=next())) {
3807 pkgname = obj->GetName();
3808 if (pkgname == "STEERBase" ||
3809 pkgname == "STEERBase.par" ||
3811 pkgname == "ESD.par" ||
3813 pkgname == "AOD.par" ||
3814 pkgname == "ANALYSIS" ||
3815 pkgname == "ANALYSIS.par" ||
3816 pkgname == "OADB" ||
3817 pkgname == "OADB.par" ||
3818 pkgname == "ANALYSISalice" ||
3819 pkgname == "ANALYSISalice.par" ||
3820 pkgname == "CORRFW" ||
3821 pkgname == "CORRFW.par") continue;
3822 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3825 out << "// include path" << endl;
3826 // Get the include path from the interpreter and remove entries pointing to AliRoot
3827 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3828 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3829 out << " TIter nextpath(listpaths);" << endl;
3830 out << " TObjString *pname;" << endl;
3831 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3832 out << " TString current = pname->GetName();" << endl;
3833 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3834 out << " gSystem->AddIncludePath(current);" << endl;
3835 out << " }" << endl;
3836 out << " if (listpaths) delete listpaths;" << endl;
3837 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3838 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3839 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3840 if (fAdditionalLibs.Length()) {
3841 out << "// Add aditional AliRoot libraries" << endl;
3842 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3845 while((str=(TObjString*)next())) {
3846 if (str->GetString().Contains(".so"))
3847 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3848 if (str->GetString().Contains(".par"))
3849 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3851 if (list) delete list;
3854 out << "// analysis source to be compiled at runtime (if any)" << endl;
3855 if (fAnalysisSource.Length()) {
3856 TObjArray *list = fAnalysisSource.Tokenize(" ");
3859 while((str=(TObjString*)next())) {
3860 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3862 if (list) delete list;
3865 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3866 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3867 if (fFastReadOption) {
3868 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 !!! \
3869 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3870 out << "// fast xrootd reading enabled" << endl;
3871 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3872 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3873 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3874 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3875 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3876 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3878 if (!IsLocalTest()) {
3879 out << "// connect to AliEn and make the chain" << endl;
3880 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3882 out << "// read the analysis manager from file" << endl;
3883 TString analysisFile = fExecutable;
3884 analysisFile.ReplaceAll(".sh", ".root");
3885 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3886 << analysisFile << "\");" << endl;
3887 out << " if (!mgr) return;" << endl;
3888 if (IsLocalTest()) {
3889 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3890 out << " plugin->SetRunMode(\"test\");" << endl;
3891 if (fFileForTestMode.IsNull())
3892 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3894 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3895 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3896 out << " mgr->SetGridHandler(plugin);" << endl;
3897 if (AliAnalysisManager::GetAnalysisManager()) {
3898 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3899 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3901 out << " mgr->SetDebugLevel(10);" << endl;
3902 out << " mgr->SetNSysInfo(100);" << endl;
3905 out << " mgr->PrintStatus();" << endl;
3906 if (AliAnalysisManager::GetAnalysisManager()) {
3907 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3908 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3910 if (TestBit(AliAnalysisGrid::kTest))
3911 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3913 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3916 if (!IsLocalTest()) {
3917 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3918 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3920 out << " mgr->StartAnalysis(\"localfile\");" << endl;
3922 out << " timer.Stop();" << endl;
3923 out << " timer.Print();" << endl;
3924 out << "}" << endl << endl;
3925 if (!IsLocalTest()) {
3926 out <<"//________________________________________________________________________________" << endl;
3927 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3929 out << "// Create a chain using url's from xml file" << endl;
3930 out << " TString filename;" << endl;
3931 out << " Int_t run = 0;" << endl;
3932 if (IsUseMCchain()) {
3933 out << " TString treename = \"TE\";" << endl;
3935 out << " TString treename = type;" << endl;
3936 out << " treename.ToLower();" << endl;
3937 out << " treename += \"Tree\";" << endl;
3939 out << " printf(\"***************************************\\n\");" << endl;
3940 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3941 out << " printf(\"***************************************\\n\");" << endl;
3942 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3943 out << " if (!coll) {" << endl;
3944 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3945 out << " return NULL;" << endl;
3946 out << " }" << endl;
3947 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3948 out << " TChain *chain = new TChain(treename);" << endl;
3949 if(fFriendChainName!="") {
3950 out << " TChain *chainFriend = new TChain(treename);" << endl;
3952 out << " coll->Reset();" << endl;
3953 out << " while (coll->Next()) {" << endl;
3954 out << " filename = coll->GetTURL("");" << endl;
3955 out << " if (mgr) {" << endl;
3956 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3957 out << " if (nrun && nrun != run) {" << endl;
3958 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3959 out << " mgr->SetRunFromPath(nrun);" << endl;
3960 out << " run = nrun;" << endl;
3961 out << " }" << endl;
3962 out << " }" << endl;
3963 out << " chain->Add(filename);" << endl;
3964 if(fFriendChainName!="") {
3965 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3966 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3967 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3968 out << " chainFriend->Add(fileFriend.Data());" << endl;
3970 out << " }" << endl;
3971 out << " if (!chain->GetNtrees()) {" << endl;
3972 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3973 out << " return NULL;" << endl;
3974 out << " }" << endl;
3975 if(fFriendChainName!="") {
3976 out << " chain->AddFriend(chainFriend);" << endl;
3978 out << " return chain;" << endl;
3979 out << "}" << endl << endl;
3981 if (hasANALYSISalice) {
3982 out <<"//________________________________________________________________________________" << endl;
3983 out << "Bool_t SetupPar(const char *package) {" << endl;
3984 out << "// Compile the package and set it up." << endl;
3985 out << " TString pkgdir = package;" << endl;
3986 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3987 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3988 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3989 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3990 out << " // Check for BUILD.sh and execute" << endl;
3991 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3992 out << " printf(\"*******************************\\n\");" << endl;
3993 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3994 out << " printf(\"*******************************\\n\");" << endl;
3995 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3996 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3997 out << " gSystem->ChangeDirectory(cdir);" << endl;
3998 out << " return kFALSE;" << endl;
3999 out << " }" << endl;
4000 out << " } else {" << endl;
4001 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4002 out << " gSystem->ChangeDirectory(cdir);" << endl;
4003 out << " return kFALSE;" << endl;
4004 out << " }" << endl;
4005 out << " // Check for SETUP.C and execute" << endl;
4006 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4007 out << " printf(\"*******************************\\n\");" << endl;
4008 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4009 out << " printf(\"*******************************\\n\");" << endl;
4010 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4011 out << " } else {" << endl;
4012 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4013 out << " gSystem->ChangeDirectory(cdir);" << endl;
4014 out << " return kFALSE;" << endl;
4015 out << " }" << endl;
4016 out << " // Restore original workdir" << endl;
4017 out << " gSystem->ChangeDirectory(cdir);" << endl;
4018 out << " return kTRUE;" << endl;
4021 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4023 Bool_t copy = kTRUE;
4024 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4027 TString workdir = gGrid->GetHomeDirectory();
4028 workdir += fGridWorkingDir;
4029 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4030 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4031 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4032 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4033 Form("alien://%s/%s", workdir.Data(),
4034 fAnalysisMacro.Data()))) Fatal("","Terminating");
4038 //______________________________________________________________________________
4039 void AliAnalysisAlien::WriteMergingMacro()
4041 // Write a macro to merge the outputs per master job.
4042 if (!fMergeViaJDL) return;
4043 if (!fOutputFiles.Length()) {
4044 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4047 TString mergingMacro = fExecutable;
4048 mergingMacro.ReplaceAll(".sh","_merge.C");
4049 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4050 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4052 out.open(mergingMacro.Data(), ios::out);
4054 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4057 Bool_t hasSTEERBase = kFALSE;
4058 Bool_t hasESD = kFALSE;
4059 Bool_t hasAOD = kFALSE;
4060 Bool_t hasANALYSIS = kFALSE;
4061 Bool_t hasOADB = kFALSE;
4062 Bool_t hasANALYSISalice = kFALSE;
4063 Bool_t hasCORRFW = kFALSE;
4064 TString func = mergingMacro;
4066 func.ReplaceAll(".C", "");
4067 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4069 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4070 out << " TStopwatch timer;" << endl;
4071 out << " timer.Start();" << endl << endl;
4072 // Reset existing include path
4073 out << "// Reset existing include path and add current directory first in the search" << endl;
4074 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4075 if (!fExecutableCommand.Contains("aliroot")) {
4076 out << "// load base root libraries" << endl;
4077 out << " gSystem->Load(\"libTree\");" << endl;
4078 out << " gSystem->Load(\"libGeom\");" << endl;
4079 out << " gSystem->Load(\"libVMC\");" << endl;
4080 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4081 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4083 if (fAdditionalRootLibs.Length()) {
4084 // in principle libtree /lib geom libvmc etc. can go into this list, too
4085 out << "// Add aditional libraries" << endl;
4086 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4089 while((str=(TObjString*)next())) {
4090 if (str->GetString().Contains(".so"))
4091 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4093 if (list) delete list;
4095 out << "// Load analysis framework libraries" << endl;
4097 if (!fExecutableCommand.Contains("aliroot")) {
4098 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4099 out << " gSystem->Load(\"libESD\");" << endl;
4100 out << " gSystem->Load(\"libAOD\");" << endl;
4102 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4103 out << " gSystem->Load(\"libOADB\");" << endl;
4104 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4105 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4107 TIter next(fPackages);
4110 TString setupPar = "AliAnalysisAlien::SetupPar";
4111 while ((obj=next())) {
4112 pkgname = obj->GetName();
4113 if (pkgname == "STEERBase" ||
4114 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4115 if (pkgname == "ESD" ||
4116 pkgname == "ESD.par") hasESD = kTRUE;
4117 if (pkgname == "AOD" ||
4118 pkgname == "AOD.par") hasAOD = kTRUE;
4119 if (pkgname == "ANALYSIS" ||
4120 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4121 if (pkgname == "OADB" ||
4122 pkgname == "OADB.par") hasOADB = kTRUE;
4123 if (pkgname == "ANALYSISalice" ||
4124 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4125 if (pkgname == "CORRFW" ||
4126 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4128 if (hasANALYSISalice) setupPar = "SetupPar";
4129 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4130 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4131 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4132 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4133 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4134 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4135 out << " gSystem->Load(\"libOADB\");" << endl;
4136 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4137 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4138 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4139 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4140 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4141 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4142 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4143 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4144 out << "// Compile other par packages" << endl;
4146 while ((obj=next())) {
4147 pkgname = obj->GetName();
4148 if (pkgname == "STEERBase" ||
4149 pkgname == "STEERBase.par" ||
4151 pkgname == "ESD.par" ||
4153 pkgname == "AOD.par" ||
4154 pkgname == "ANALYSIS" ||
4155 pkgname == "ANALYSIS.par" ||
4156 pkgname == "OADB" ||
4157 pkgname == "OADB.par" ||
4158 pkgname == "ANALYSISalice" ||
4159 pkgname == "ANALYSISalice.par" ||
4160 pkgname == "CORRFW" ||
4161 pkgname == "CORRFW.par") continue;
4162 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4165 out << "// include path" << endl;
4166 // Get the include path from the interpreter and remove entries pointing to AliRoot
4167 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4168 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4169 out << " TIter nextpath(listpaths);" << endl;
4170 out << " TObjString *pname;" << endl;
4171 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4172 out << " TString current = pname->GetName();" << endl;
4173 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4174 out << " gSystem->AddIncludePath(current);" << endl;
4175 out << " }" << endl;
4176 out << " if (listpaths) delete listpaths;" << endl;
4177 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4178 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4179 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4180 if (fAdditionalLibs.Length()) {
4181 out << "// Add aditional AliRoot libraries" << endl;
4182 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4185 while((str=(TObjString*)next())) {
4186 if (str->GetString().Contains(".so"))
4187 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4189 if (list) delete list;
4192 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4193 if (fAnalysisSource.Length()) {
4194 TObjArray *list = fAnalysisSource.Tokenize(" ");
4197 while((str=(TObjString*)next())) {
4198 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4200 if (list) delete list;
4204 if (fFastReadOption) {
4205 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 !!!");
4206 out << "// fast xrootd reading enabled" << endl;
4207 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4208 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4209 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4210 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4211 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4212 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4214 // Change temp directory to current one
4215 out << "// Set temporary merging directory to current one" << endl;
4216 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4217 out << "// Set temporary compilation directory to current one" << endl;
4218 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4219 out << "// Connect to AliEn" << endl;
4220 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4221 out << " TString outputDir = dir;" << endl;
4222 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4223 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4224 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4225 out << " TIter *iter = new TIter(list);" << endl;
4226 out << " TObjString *str;" << endl;
4227 out << " TString outputFile;" << endl;
4228 out << " Bool_t merged = kTRUE;" << endl;
4229 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4230 out << " outputFile = str->GetString();" << endl;
4231 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4232 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4233 out << " if (index > 0) outputFile.Remove(index);" << endl;
4234 out << " // Skip already merged outputs" << endl;
4235 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4236 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4237 out << " continue;" << endl;
4238 out << " }" << endl;
4239 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4240 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4241 out << " if (!merged) {" << endl;
4242 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4243 out << " return;" << endl;
4244 out << " }" << endl;
4245 out << " }" << endl;
4246 out << " // all outputs merged, validate" << endl;
4247 out << " ofstream out;" << endl;
4248 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4249 out << " out.close();" << endl;
4250 out << " // read the analysis manager from file" << endl;
4251 TString analysisFile = fExecutable;
4252 analysisFile.ReplaceAll(".sh", ".root");
4253 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4254 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4255 << analysisFile << "\");" << endl;
4256 out << " if (!mgr) return;" << endl;
4257 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4258 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4259 out << " mgr->PrintStatus();" << endl;
4260 if (AliAnalysisManager::GetAnalysisManager()) {
4261 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4262 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4264 if (TestBit(AliAnalysisGrid::kTest))
4265 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4267 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4270 out << " TTree *tree = NULL;" << endl;
4271 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4272 out << "}" << endl << endl;
4273 if (hasANALYSISalice) {
4274 out <<"//________________________________________________________________________________" << endl;
4275 out << "Bool_t SetupPar(const char *package) {" << endl;
4276 out << "// Compile the package and set it up." << endl;
4277 out << " TString pkgdir = package;" << endl;
4278 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4279 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4280 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4281 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4282 out << " // Check for BUILD.sh and execute" << endl;
4283 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4284 out << " printf(\"*******************************\\n\");" << endl;
4285 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4286 out << " printf(\"*******************************\\n\");" << endl;
4287 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4288 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4289 out << " gSystem->ChangeDirectory(cdir);" << endl;
4290 out << " return kFALSE;" << endl;
4291 out << " }" << endl;
4292 out << " } else {" << endl;
4293 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4294 out << " gSystem->ChangeDirectory(cdir);" << endl;
4295 out << " return kFALSE;" << endl;
4296 out << " }" << endl;
4297 out << " // Check for SETUP.C and execute" << endl;
4298 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4299 out << " printf(\"*******************************\\n\");" << endl;
4300 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4301 out << " printf(\"*******************************\\n\");" << endl;
4302 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4303 out << " } else {" << endl;
4304 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4305 out << " gSystem->ChangeDirectory(cdir);" << endl;
4306 out << " return kFALSE;" << endl;
4307 out << " }" << endl;
4308 out << " // Restore original workdir" << endl;
4309 out << " gSystem->ChangeDirectory(cdir);" << endl;
4310 out << " return kTRUE;" << endl;
4314 Bool_t copy = kTRUE;
4315 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4318 TString workdir = gGrid->GetHomeDirectory();
4319 workdir += fGridWorkingDir;
4320 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4321 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4322 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4323 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4324 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4328 //______________________________________________________________________________
4329 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4331 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4332 // Note that for loading the compiled library. The current directory should have precedence in
4334 TString pkgdir = package;
4335 pkgdir.ReplaceAll(".par","");
4336 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4337 TString cdir = gSystem->WorkingDirectory();
4338 gSystem->ChangeDirectory(pkgdir);
4339 // Check for BUILD.sh and execute
4340 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4341 printf("**************************************************\n");
4342 printf("*** Building PAR archive %s\n", package);
4343 printf("**************************************************\n");
4344 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4345 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4346 gSystem->ChangeDirectory(cdir);
4350 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4351 gSystem->ChangeDirectory(cdir);
4354 // Check for SETUP.C and execute
4355 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4356 printf("**************************************************\n");
4357 printf("*** Setup PAR archive %s\n", package);
4358 printf("**************************************************\n");
4359 gROOT->Macro("PROOF-INF/SETUP.C");
4360 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4362 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4363 gSystem->ChangeDirectory(cdir);
4366 // Restore original workdir
4367 gSystem->ChangeDirectory(cdir);
4371 //______________________________________________________________________________
4372 void AliAnalysisAlien::WriteExecutable()
4374 // Generate the alien executable script.
4375 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4377 out.open(fExecutable.Data(), ios::out);
4379 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4382 out << "#!/bin/bash" << endl;
4383 // Make sure we can properly compile par files
4384 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4385 out << "echo \"=========================================\"" << endl;
4386 out << "echo \"############## PATH : ##############\"" << endl;
4387 out << "echo $PATH" << endl;
4388 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4389 out << "echo $LD_LIBRARY_PATH" << endl;
4390 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4391 out << "echo $ROOTSYS" << endl;
4392 out << "echo \"############## which root : ##############\"" << endl;
4393 out << "which root" << endl;
4394 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4395 out << "echo $ALICE_ROOT" << endl;
4396 out << "echo \"############## which aliroot : ##############\"" << endl;
4397 out << "which aliroot" << endl;
4398 out << "echo \"############## system limits : ##############\"" << endl;
4399 out << "ulimit -a" << endl;
4400 out << "echo \"############## memory : ##############\"" << endl;
4401 out << "free -m" << endl;
4402 out << "echo \"=========================================\"" << endl << endl;
4403 out << fExecutableCommand << " ";
4404 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4405 out << "RET=$?" << endl;
4406 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4407 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4408 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4409 out << " let sig=\"$RET - 128\""<<endl;
4410 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4411 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4412 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4413 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4414 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4415 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4417 out << " exit $RET"<< endl;
4418 out << "fi" << endl << endl ;
4419 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4420 out << "echo \"############## memory after: ##############\"" << endl;
4421 out << "free -m" << endl;
4423 Bool_t copy = kTRUE;
4424 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4427 TString workdir = gGrid->GetHomeDirectory();
4428 TString bindir = Form("%s/bin", workdir.Data());
4429 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4430 workdir += fGridWorkingDir;
4431 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4432 if (FileExists(executable)) gGrid->Rm(executable);
4433 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4434 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4435 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4436 executable.Data())) Fatal("","Terminating");
4440 //______________________________________________________________________________
4441 void AliAnalysisAlien::WriteMergeExecutable()
4443 // Generate the alien executable script for the merging job.
4444 if (!fMergeViaJDL) return;
4445 TString mergeExec = fExecutable;
4446 mergeExec.ReplaceAll(".sh", "_merge.sh");
4447 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4449 out.open(mergeExec.Data(), ios::out);
4451 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4454 out << "#!/bin/bash" << endl;
4455 // Make sure we can properly compile par files
4456 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4457 out << "echo \"=========================================\"" << endl;
4458 out << "echo \"############## PATH : ##############\"" << endl;
4459 out << "echo $PATH" << endl;
4460 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4461 out << "echo $LD_LIBRARY_PATH" << endl;
4462 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4463 out << "echo $ROOTSYS" << endl;
4464 out << "echo \"############## which root : ##############\"" << endl;
4465 out << "which root" << endl;
4466 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4467 out << "echo $ALICE_ROOT" << endl;
4468 out << "echo \"############## which aliroot : ##############\"" << endl;
4469 out << "which aliroot" << endl;
4470 out << "echo \"############## system limits : ##############\"" << endl;
4471 out << "ulimit -a" << endl;
4472 out << "echo \"############## memory : ##############\"" << endl;
4473 out << "free -m" << endl;
4474 out << "echo \"=========================================\"" << endl << endl;
4475 TString mergeMacro = fExecutable;
4476 mergeMacro.ReplaceAll(".sh", "_merge.C");
4477 if (IsOneStageMerging())
4478 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4480 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4481 out << fExecutableCommand << " " << "$ARG" << endl;
4482 out << "RET=$?" << endl;
4483 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4484 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4485 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4486 out << " let sig=\"$RET - 128\""<<endl;
4487 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4488 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4489 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4490 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4491 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4492 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4494 out << " exit $RET"<< endl;
4495 out << "fi" << endl << endl ;
4496 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4497 out << "echo \"############## memory after: ##############\"" << endl;
4498 out << "free -m" << endl;
4500 Bool_t copy = kTRUE;
4501 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4504 TString workdir = gGrid->GetHomeDirectory();
4505 TString bindir = Form("%s/bin", workdir.Data());
4506 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4507 workdir += fGridWorkingDir;
4508 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4509 if (FileExists(executable)) gGrid->Rm(executable);
4510 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4511 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4512 if (!copyLocal2Alien("WriteMergeExecutable",
4513 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4517 //______________________________________________________________________________
4518 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4520 // Write the production file to be submitted by LPM manager. The format is:
4521 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4522 // Next lines: full_path_to_dataset XXX (XXX is a string)
4523 // To submit, one has to: submit jdl XXX for all lines
4525 out.open(filename, ios::out);
4527 Error("WriteProductionFile", "Bad file name: %s", filename);
4531 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4532 workdir = gGrid->GetHomeDirectory();
4533 workdir += fGridWorkingDir;
4534 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4535 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4536 out << locjdl << " " << njobspermaster << endl;
4537 Int_t nmasterjobs = fInputFiles->GetEntries();
4538 for (Int_t i=0; i<nmasterjobs; i++) {
4539 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4540 runOutDir.ReplaceAll(".xml", "");
4542 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4544 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4547 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4548 if (FileExists(filename)) gGrid->Rm(filename);
4549 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4550 if (!copyLocal2Alien("WriteProductionFile", filename,
4551 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4555 //______________________________________________________________________________
4556 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4558 // Generate the alien validation script.
4559 // Generate the validation script
4561 if (fValidationScript.IsNull()) {
4562 fValidationScript = fExecutable;
4563 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4565 TString validationScript = fValidationScript;
4566 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4568 Error("WriteValidationScript", "Alien connection required");
4571 if (!fTerminateFiles.IsNull()) {
4572 fTerminateFiles.Strip();
4573 fTerminateFiles.ReplaceAll(" ",",");
4575 TString outStream = "";
4576 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4577 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4579 out.open(validationScript, ios::out);
4580 out << "#!/bin/bash" << endl;
4581 out << "##################################################" << endl;
4582 out << "validateout=`dirname $0`" << endl;
4583 out << "validatetime=`date`" << endl;
4584 out << "validated=\"0\";" << endl;
4585 out << "error=0" << endl;
4586 out << "if [ -z $validateout ]" << endl;
4587 out << "then" << endl;
4588 out << " validateout=\".\"" << endl;
4589 out << "fi" << endl << endl;
4590 out << "cd $validateout;" << endl;
4591 out << "validateworkdir=`pwd`;" << endl << endl;
4592 out << "echo \"*******************************************************\"" << outStream << endl;
4593 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4595 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4596 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4597 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4598 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4599 out << "ls -la ./" << outStream << endl;
4600 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4601 out << "##################################################" << endl;
4604 out << "if [ ! -f stderr ] ; then" << endl;
4605 out << " error=1" << endl;
4606 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4607 out << " echo \"Error = $error\" " << outStream << endl;
4608 out << "fi" << endl;
4610 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4611 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4612 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4613 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4616 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4617 out << " error=1" << endl;
4618 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4619 out << " echo \"$parArch\" " << outStream << endl;
4620 out << " echo \"Error = $error\" " << outStream << endl;
4621 out << "fi" << endl;
4623 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4624 out << " error=1" << endl;
4625 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4626 out << " echo \"$segViol\" " << outStream << endl;
4627 out << " echo \"Error = $error\" " << outStream << endl;
4628 out << "fi" << endl;
4630 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4631 out << " error=1" << endl;
4632 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4633 out << " echo \"$segFault\" " << outStream << endl;
4634 out << " echo \"Error = $error\" " << outStream << endl;
4635 out << "fi" << endl;
4637 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4638 out << " error=1" << endl;
4639 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4640 out << " echo \"$glibcErr\" " << outStream << endl;
4641 out << " echo \"Error = $error\" " << outStream << endl;
4642 out << "fi" << endl;
4644 // Part dedicated to the specific analyses running into the train
4646 TString outputFiles = fOutputFiles;
4647 if (merge && !fTerminateFiles.IsNull()) {
4649 outputFiles += fTerminateFiles;
4651 TObjArray *arr = outputFiles.Tokenize(",");
4654 while (!merge && (os=(TObjString*)next1())) {
4655 // No need to validate outputs produced by merging since the merging macro does this
4656 outputFile = os->GetString();
4657 Int_t index = outputFile.Index("@");
4658 if (index > 0) outputFile.Remove(index);
4659 if (fTerminateFiles.Contains(outputFile)) continue;
4660 if (outputFile.Contains("*")) continue;
4661 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4662 out << " error=1" << endl;
4663 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4664 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4665 out << "fi" << endl;
4668 out << "if ! [ -f outputs_valid ] ; then" << endl;
4669 out << " error=1" << endl;
4670 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4671 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4672 out << "fi" << endl;
4674 out << "if [ $error = 0 ] ; then" << endl;
4675 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4676 if (!IsKeepLogs()) {
4677 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4679 out << " rm -f std*" << endl;
4681 out << "fi" << endl;
4683 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4684 out << "echo \"*******************************************************\"" << outStream << endl;
4685 out << "cd -" << endl;
4686 out << "exit $error" << endl;
4688 Bool_t copy = kTRUE;
4689 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4692 TString workdir = gGrid->GetHomeDirectory();
4693 workdir += fGridWorkingDir;
4694 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4695 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4696 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4697 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4698 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");