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"
32 #include "TInterpreter.h"
34 #include "TFileCollection.h"
36 #include "TObjString.h"
37 #include "TObjArray.h"
40 #include "TGridResult.h"
41 #include "TGridCollection.h"
43 #include "TGridJobStatusList.h"
44 #include "TGridJobStatus.h"
45 #include "TFileMerger.h"
46 #include "AliAnalysisManager.h"
47 #include "AliAnalysisTaskCfg.h"
48 #include "AliVEventHandler.h"
49 #include "AliAnalysisDataContainer.h"
50 #include "AliMultiInputEventHandler.h"
56 ClassImp(AliAnalysisAlien)
62 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
64 TString sl(Form("file:%s", loc));
65 TString sr(Form("alien://%s", rem));
66 Bool_t ret = TFile::Cp(sl, sr);
68 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
74 //______________________________________________________________________________
75 AliAnalysisAlien::AliAnalysisAlien()
81 fSplitMaxInputFileNumber(0),
83 fMasterResubmitThreshold(0),
96 fNproofWorkersPerSlave(0),
102 fExecutableCommand(),
108 fAdditionalRootLibs(),
156 //______________________________________________________________________________
157 AliAnalysisAlien::AliAnalysisAlien(const char *name)
158 :AliAnalysisGrid(name),
163 fSplitMaxInputFileNumber(0),
165 fMasterResubmitThreshold(0),
178 fNproofWorkersPerSlave(0),
184 fExecutableCommand(),
190 fAdditionalRootLibs(),
238 //______________________________________________________________________________
239 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
240 :AliAnalysisGrid(other),
243 fPrice(other.fPrice),
245 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
246 fMaxInitFailed(other.fMaxInitFailed),
247 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
248 fNtestFiles(other.fNtestFiles),
249 fNrunsPerMaster(other.fNrunsPerMaster),
250 fMaxMergeFiles(other.fMaxMergeFiles),
251 fMaxMergeStages(other.fMaxMergeStages),
252 fNsubmitted(other.fNsubmitted),
253 fProductionMode(other.fProductionMode),
254 fOutputToRunNo(other.fOutputToRunNo),
255 fMergeViaJDL(other.fMergeViaJDL),
256 fFastReadOption(other.fFastReadOption),
257 fOverwriteMode(other.fOverwriteMode),
258 fNreplicas(other.fNreplicas),
259 fNproofWorkers(other.fNproofWorkers),
260 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
261 fProofReset(other.fProofReset),
262 fNMCevents(other.fNMCevents),
263 fNMCjobs(other.fNMCjobs),
264 fRunNumbers(other.fRunNumbers),
265 fExecutable(other.fExecutable),
266 fExecutableCommand(other.fExecutableCommand),
267 fArguments(other.fArguments),
268 fExecutableArgs(other.fExecutableArgs),
269 fAnalysisMacro(other.fAnalysisMacro),
270 fAnalysisSource(other.fAnalysisSource),
271 fValidationScript(other.fValidationScript),
272 fAdditionalRootLibs(other.fAdditionalRootLibs),
273 fAdditionalLibs(other.fAdditionalLibs),
274 fGeneratorLibs(other.fGeneratorLibs),
275 fSplitMode(other.fSplitMode),
276 fAPIVersion(other.fAPIVersion),
277 fROOTVersion(other.fROOTVersion),
278 fAliROOTVersion(other.fAliROOTVersion),
279 fExternalPackages(other.fExternalPackages),
281 fGridWorkingDir(other.fGridWorkingDir),
282 fGridDataDir(other.fGridDataDir),
283 fDataPattern(other.fDataPattern),
284 fGridOutputDir(other.fGridOutputDir),
285 fOutputArchive(other.fOutputArchive),
286 fOutputFiles(other.fOutputFiles),
287 fInputFormat(other.fInputFormat),
288 fDatasetName(other.fDatasetName),
289 fJDLName(other.fJDLName),
290 fTerminateFiles(other.fTerminateFiles),
291 fMergeExcludes(other.fMergeExcludes),
292 fRegisterExcludes(other.fRegisterExcludes),
293 fIncludePath(other.fIncludePath),
294 fCloseSE(other.fCloseSE),
295 fFriendChainName(other.fFriendChainName),
296 fJobTag(other.fJobTag),
297 fOutputSingle(other.fOutputSingle),
298 fRunPrefix(other.fRunPrefix),
299 fProofCluster(other.fProofCluster),
300 fProofDataSet(other.fProofDataSet),
301 fFileForTestMode(other.fFileForTestMode),
302 fAliRootMode(other.fAliRootMode),
303 fProofProcessOpt(other.fProofProcessOpt),
304 fMergeDirName(other.fMergeDirName),
309 fDropToShell(other.fDropToShell),
310 fMCLoop(other.fMCLoop),
311 fGridJobIDs(other.fGridJobIDs),
312 fGridStages(other.fGridStages),
313 fFriendLibs(other.fFriendLibs),
314 fTreeName(other.fTreeName)
317 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
318 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
319 fRunRange[0] = other.fRunRange[0];
320 fRunRange[1] = other.fRunRange[1];
321 if (other.fInputFiles) {
322 fInputFiles = new TObjArray();
323 TIter next(other.fInputFiles);
325 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
326 fInputFiles->SetOwner();
328 if (other.fPackages) {
329 fPackages = new TObjArray();
330 TIter next(other.fPackages);
332 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
333 fPackages->SetOwner();
335 if (other.fModules) {
336 fModules = new TObjArray();
337 fModules->SetOwner();
338 TIter next(other.fModules);
339 AliAnalysisTaskCfg *mod, *crt;
340 while ((crt=(AliAnalysisTaskCfg*)next())) {
341 mod = new AliAnalysisTaskCfg(*crt);
347 //______________________________________________________________________________
348 AliAnalysisAlien::~AliAnalysisAlien()
356 fProofParam.DeleteAll();
359 //______________________________________________________________________________
360 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
363 if (this != &other) {
364 AliAnalysisGrid::operator=(other);
365 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
366 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
367 fPrice = other.fPrice;
369 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
370 fMaxInitFailed = other.fMaxInitFailed;
371 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
372 fNtestFiles = other.fNtestFiles;
373 fNrunsPerMaster = other.fNrunsPerMaster;
374 fMaxMergeFiles = other.fMaxMergeFiles;
375 fMaxMergeStages = other.fMaxMergeStages;
376 fNsubmitted = other.fNsubmitted;
377 fProductionMode = other.fProductionMode;
378 fOutputToRunNo = other.fOutputToRunNo;
379 fMergeViaJDL = other.fMergeViaJDL;
380 fFastReadOption = other.fFastReadOption;
381 fOverwriteMode = other.fOverwriteMode;
382 fNreplicas = other.fNreplicas;
383 fNproofWorkers = other.fNproofWorkers;
384 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
385 fProofReset = other.fProofReset;
386 fNMCevents = other.fNMCevents;
387 fNMCjobs = other.fNMCjobs;
388 fRunNumbers = other.fRunNumbers;
389 fExecutable = other.fExecutable;
390 fExecutableCommand = other.fExecutableCommand;
391 fArguments = other.fArguments;
392 fExecutableArgs = other.fExecutableArgs;
393 fAnalysisMacro = other.fAnalysisMacro;
394 fAnalysisSource = other.fAnalysisSource;
395 fValidationScript = other.fValidationScript;
396 fAdditionalRootLibs = other.fAdditionalRootLibs;
397 fAdditionalLibs = other.fAdditionalLibs;
398 fGeneratorLibs = other.fGeneratorLibs;
399 fSplitMode = other.fSplitMode;
400 fAPIVersion = other.fAPIVersion;
401 fROOTVersion = other.fROOTVersion;
402 fAliROOTVersion = other.fAliROOTVersion;
403 fExternalPackages = other.fExternalPackages;
405 fGridWorkingDir = other.fGridWorkingDir;
406 fGridDataDir = other.fGridDataDir;
407 fDataPattern = other.fDataPattern;
408 fGridOutputDir = other.fGridOutputDir;
409 fOutputArchive = other.fOutputArchive;
410 fOutputFiles = other.fOutputFiles;
411 fInputFormat = other.fInputFormat;
412 fDatasetName = other.fDatasetName;
413 fJDLName = other.fJDLName;
414 fTerminateFiles = other.fTerminateFiles;
415 fMergeExcludes = other.fMergeExcludes;
416 fRegisterExcludes = other.fRegisterExcludes;
417 fIncludePath = other.fIncludePath;
418 fCloseSE = other.fCloseSE;
419 fFriendChainName = other.fFriendChainName;
420 fJobTag = other.fJobTag;
421 fOutputSingle = other.fOutputSingle;
422 fRunPrefix = other.fRunPrefix;
423 fProofCluster = other.fProofCluster;
424 fProofDataSet = other.fProofDataSet;
425 fFileForTestMode = other.fFileForTestMode;
426 fAliRootMode = other.fAliRootMode;
427 fProofProcessOpt = other.fProofProcessOpt;
428 fMergeDirName = other.fMergeDirName;
429 fDropToShell = other.fDropToShell;
430 fMCLoop = other.fMCLoop;
431 fGridJobIDs = other.fGridJobIDs;
432 fGridStages = other.fGridStages;
433 fFriendLibs = other.fFriendLibs;
434 fTreeName = other.fTreeName;
435 if (other.fInputFiles) {
436 fInputFiles = new TObjArray();
437 TIter next(other.fInputFiles);
439 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
440 fInputFiles->SetOwner();
442 if (other.fPackages) {
443 fPackages = new TObjArray();
444 TIter next(other.fPackages);
446 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
447 fPackages->SetOwner();
449 if (other.fModules) {
450 fModules = new TObjArray();
451 fModules->SetOwner();
452 TIter next(other.fModules);
453 AliAnalysisTaskCfg *mod, *crt;
454 while ((crt=(AliAnalysisTaskCfg*)next())) {
455 mod = new AliAnalysisTaskCfg(*crt);
463 //______________________________________________________________________________
464 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
466 // Add a single additional library to be loaded. Extension must be present.
468 if (!lib.Contains(".")) {
469 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
472 if (fAdditionalLibs.Contains(name)) {
473 Warning("AddAdditionalLibrary", "Library %s already added.", name);
476 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
477 fAdditionalLibs += lib;
480 //______________________________________________________________________________
481 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
483 // Adding a module. Checks if already existing. Becomes owned by this.
485 if (GetModule(module->GetName())) {
486 Error("AddModule", "A module having the same name %s already added", module->GetName());
490 fModules = new TObjArray();
491 fModules->SetOwner();
493 fModules->Add(module);
496 //______________________________________________________________________________
497 void AliAnalysisAlien::AddModules(TObjArray *list)
499 // Adding a list of modules. Checks if already existing. Becomes owned by this.
501 AliAnalysisTaskCfg *module;
502 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
505 //______________________________________________________________________________
506 Bool_t AliAnalysisAlien::CheckDependencies()
508 // Check if all dependencies are satisfied. Reorder modules if needed.
509 Int_t nmodules = GetNmodules();
511 Warning("CheckDependencies", "No modules added yet to check their dependencies");
514 AliAnalysisTaskCfg *mod = 0;
515 AliAnalysisTaskCfg *dep = 0;
518 for (i=0; i<nmodules; i++) {
519 mod = (AliAnalysisTaskCfg*) fModules->At(i);
520 Int_t ndeps = mod->GetNdeps();
522 for (j=0; j<ndeps; j++) {
523 depname = mod->GetDependency(j);
524 dep = GetModule(depname);
526 Error("CheckDependencies","Dependency %s not added for module %s",
527 depname.Data(), mod->GetName());
530 if (dep->NeedsDependency(mod->GetName())) {
531 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
532 mod->GetName(), dep->GetName());
535 Int_t idep = fModules->IndexOf(dep);
536 // The dependency task must come first
538 // Remove at idep and move all objects below up one slot
539 // down to index i included.
540 fModules->RemoveAt(idep);
541 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
542 fModules->AddAt(dep, i++);
544 //Redo from istart if dependencies were inserted
545 if (i>istart) i=istart-1;
551 //______________________________________________________________________________
552 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
554 // Create the analysis manager and optionally execute the macro in filename.
555 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
557 mgr->SetMCLoop(fMCLoop);
560 mgr = new AliAnalysisManager(name);
561 mgr->SetGridHandler((AliAnalysisGrid*)this);
562 mgr->SetMCLoop(fMCLoop);
563 if (strlen(filename)) {
564 TString line = gSystem->ExpandPathName(filename);
566 gROOT->ProcessLine(line.Data());
571 //______________________________________________________________________________
572 Int_t AliAnalysisAlien::GetNmodules() const
574 // Get number of modules.
575 if (!fModules) return 0;
576 return fModules->GetEntries();
579 //______________________________________________________________________________
580 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
582 // Get a module by name.
583 if (!fModules) return 0;
584 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
587 //______________________________________________________________________________
588 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
590 // Load a given module.
591 if (mod->IsLoaded()) return kTRUE;
592 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
594 Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
597 Int_t ndeps = mod->GetNdeps();
599 for (Int_t j=0; j<ndeps; j++) {
600 depname = mod->GetDependency(j);
601 AliAnalysisTaskCfg *dep = GetModule(depname);
603 Error("LoadModule","Dependency %s not existing for module %s",
604 depname.Data(), mod->GetName());
607 if (!LoadModule(dep)) {
608 Error("LoadModule","Dependency %s for module %s could not be loaded",
609 depname.Data(), mod->GetName());
613 // Load libraries for the module
614 if (!mod->CheckLoadLibraries()) {
615 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
618 // Check if a custom file name was requested
619 if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
621 // Check if a custom terminate file name was requested
622 if (strlen(mod->GetTerminateFileName())) {
623 if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
624 fTerminateFiles += mod->GetTerminateFileName();
628 if (mod->ExecuteMacro()<0) {
629 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
630 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
633 // Configure dependencies
634 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
635 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
636 mod->GetConfigMacro()->GetTitle(), mod->GetName());
639 // Adjust extra libraries
640 Int_t nlibs = mod->GetNlibs();
642 for (Int_t i=0; i<nlibs; i++) {
643 lib = mod->GetLibrary(i);
644 lib = Form("lib%s.so", lib.Data());
645 if (fAdditionalLibs.Contains(lib)) continue;
646 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
647 fAdditionalLibs += lib;
652 //______________________________________________________________________________
653 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
655 // Generate the full train.
656 fAdditionalLibs = "";
657 if (!LoadModules()) return kFALSE;
658 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
659 if (!mgr->InitAnalysis()) return kFALSE;
662 Int_t productionMode = fProductionMode;
664 TString macro = fAnalysisMacro;
665 TString executable = fExecutable;
666 TString validation = fValidationScript;
667 TString execCommand = fExecutableCommand;
668 SetAnalysisMacro(Form("%s.C", name));
669 SetExecutable(Form("%s.sh", name));
670 // SetExecutableCommand("aliroot -b -q ");
671 SetValidationScript(Form("%s_validation.sh", name));
673 SetProductionMode(productionMode);
674 fAnalysisMacro = macro;
675 fExecutable = executable;
676 fExecutableCommand = execCommand;
677 fValidationScript = validation;
681 //______________________________________________________________________________
682 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
684 // Generate test macros for a single module or for the full train.
685 fAdditionalLibs = "";
686 if (strlen(modname)) {
687 if (!CheckDependencies()) return kFALSE;
688 AliAnalysisTaskCfg *mod = GetModule(modname);
690 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
693 if (!LoadModule(mod)) return kFALSE;
694 if (!LoadFriendLibs()) return kFALSE;
695 } else if (!LoadModules()) return kFALSE;
696 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
697 if (!mgr->InitAnalysis()) return kFALSE;
701 Int_t productionMode = fProductionMode;
703 TString macro = fAnalysisMacro;
704 TString executable = fExecutable;
705 TString validation = fValidationScript;
706 TString execCommand = fExecutableCommand;
707 SetAnalysisMacro(Form("%s.C", name));
708 SetExecutable(Form("%s.sh", name));
709 fOutputFiles = GetListOfFiles("outaod");
710 // Add extra files registered to the analysis manager
711 TString extra = GetListOfFiles("ext");
712 if (!extra.IsNull()) {
713 extra.ReplaceAll(".root", "*.root");
714 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
715 fOutputFiles += extra;
717 // SetExecutableCommand("aliroot -b -q ");
718 SetValidationScript(Form("%s_validation.sh", name));
720 WriteAnalysisMacro();
722 WriteValidationScript();
724 WriteMergeExecutable();
725 WriteValidationScript(kTRUE);
726 SetLocalTest(kFALSE);
727 SetProductionMode(productionMode);
728 fAnalysisMacro = macro;
729 fExecutable = executable;
730 fExecutableCommand = execCommand;
731 fValidationScript = validation;
735 //______________________________________________________________________________
736 Bool_t AliAnalysisAlien::LoadModules()
738 // Load all modules by executing the AddTask macros. Checks first the dependencies.
739 fAdditionalLibs = "";
740 Int_t nmodules = GetNmodules();
742 Warning("LoadModules", "No module to be loaded");
745 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
747 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
750 if (!CheckDependencies()) return kFALSE;
751 nmodules = GetNmodules();
752 AliAnalysisTaskCfg *mod;
753 for (Int_t imod=0; imod<nmodules; imod++) {
754 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
755 if (!LoadModule(mod)) return kFALSE;
757 // Load additional friend libraries
758 return LoadFriendLibs();
761 //______________________________________________________________________________
762 Bool_t AliAnalysisAlien::LoadFriendLibs() const
764 // Load libraries required for reading friends.
765 if (fFriendLibs.Length()) {
768 if (fFriendLibs.Contains(",")) list = fFriendLibs.Tokenize(",");
769 else list = fFriendLibs.Tokenize(" ");
770 for (Int_t ilib=0; ilib<list->GetEntriesFast(); ilib++) {
771 lib = list->At(ilib)->GetName();
772 lib.ReplaceAll(".so","");
773 lib.ReplaceAll(".dylib","");
774 lib.ReplaceAll(" ","");
775 if (lib.BeginsWith("lib")) lib.Remove(0, 3);
777 Int_t loaded = strlen(gSystem->GetLibraries(lib,"",kFALSE));
778 if (!loaded) loaded = gSystem->Load(lib);
780 Error("LoadModules", "Cannot load library for friends %s", lib.Data());
789 //______________________________________________________________________________
790 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
792 // Set the run number format. Can be a prefix or a format like "%09d"
794 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
797 //______________________________________________________________________________
798 void AliAnalysisAlien::AddIncludePath(const char *path)
800 // Add include path in the remote analysis macro.
802 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
803 else fIncludePath += Form("-I%s ", path);
806 //______________________________________________________________________________
807 void AliAnalysisAlien::AddRunNumber(Int_t run)
809 // Add a run number to the list of runs to be processed.
810 if (fRunNumbers.Length()) fRunNumbers += " ";
811 fRunNumbers += Form(fRunPrefix.Data(), run);
814 //______________________________________________________________________________
815 void AliAnalysisAlien::AddRunList(const char* runList)
817 // Add several runs into the list of runs; they are expected to be separated by a blank character.
818 TString sList = runList;
819 TObjArray *list = sList.Tokenize(" ");
820 Int_t n = list->GetEntries();
821 for (Int_t i = 0; i < n; i++) {
822 TObjString *os = (TObjString*)list->At(i);
823 AddRunNumber(os->GetString().Atoi());
828 //______________________________________________________________________________
829 void AliAnalysisAlien::AddRunNumber(const char* run)
831 // Add a run number to the list of runs to be processed.
834 TObjArray *arr = runs.Tokenize(" ");
837 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
838 while ((os=(TObjString*)next())){
839 if (fRunNumbers.Length()) fRunNumbers += " ";
840 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
845 //______________________________________________________________________________
846 void AliAnalysisAlien::AddDataFile(const char *lfn)
848 // Adds a data file to the input to be analysed. The file should be a valid LFN
849 // or point to an existing file in the alien workdir.
850 if (!fInputFiles) fInputFiles = new TObjArray();
851 fInputFiles->Add(new TObjString(lfn));
854 //______________________________________________________________________________
855 void AliAnalysisAlien::AddExternalPackage(const char *package)
857 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
858 if (fExternalPackages) fExternalPackages += " ";
859 fExternalPackages += package;
862 //______________________________________________________________________________
863 Bool_t AliAnalysisAlien::Connect()
865 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
866 if (gGrid && gGrid->IsConnected()) return kTRUE;
867 if (fProductionMode) return kTRUE;
869 Info("Connect", "Trying to connect to AliEn ...");
870 TGrid::Connect("alien://");
872 if (!gGrid || !gGrid->IsConnected()) {
873 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
876 fUser = gGrid->GetUser();
877 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
881 //______________________________________________________________________________
882 void AliAnalysisAlien::CdWork()
884 // Check validity of alien workspace. Create directory if possible.
886 Error("CdWork", "Alien connection required");
889 TString homedir = gGrid->GetHomeDirectory();
890 TString workdir = homedir + fGridWorkingDir;
891 if (DirectoryExists(workdir)) {
895 // Work directory not existing - create it
897 if (gGrid->Mkdir(workdir, "-p")) {
898 gGrid->Cd(fGridWorkingDir);
899 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
901 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
902 workdir.Data(), homedir.Data());
903 fGridWorkingDir = "";
907 //______________________________________________________________________________
908 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
910 // Check if file copying is possible.
911 if (fProductionMode) return kTRUE;
912 TString salienpath(alienpath);
913 if (salienpath.Contains(" ")) {
914 Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
918 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
921 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
922 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
923 // Check if alien_CLOSE_SE is defined
924 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
925 if (!closeSE.IsNull()) {
926 Info("CheckFileCopy", "Your current close storage is pointing to: \
927 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
929 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
931 // Check if grid directory exists.
932 if (!DirectoryExists(alienpath)) {
933 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
936 TString stest = "plugin_test_copy";
937 TFile f(stest, "RECREATE");
938 // User may not have write permissions to current directory
940 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
941 gSystem->WorkingDirectory());
945 if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
946 if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
947 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
948 \n# 1. Make sure you have write permissions there. If this is the case: \
949 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
950 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
951 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
952 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
953 gSystem->Unlink(stest.Data());
956 gSystem->Unlink(stest.Data());
957 gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
958 Info("CheckFileCopy", "### ...SUCCESS ###");
962 //______________________________________________________________________________
963 Bool_t AliAnalysisAlien::CheckInputData()
965 // Check validity of input data. If necessary, create xml files.
966 if (fProductionMode) return kTRUE;
967 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
968 if (!fGridDataDir.Length()) {
969 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
973 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
976 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
977 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
978 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
981 // Process declared files
982 Bool_t isCollection = kFALSE;
983 Bool_t isXml = kFALSE;
984 Bool_t useTags = kFALSE;
985 Bool_t checked = kFALSE;
986 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
988 TString workdir = gGrid->GetHomeDirectory();
989 workdir += fGridWorkingDir;
992 TIter next(fInputFiles);
993 while ((objstr=(TObjString*)next())) {
996 file += objstr->GetString();
997 // Store full lfn path
998 if (FileExists(file)) objstr->SetString(file);
1000 file = objstr->GetName();
1001 if (!FileExists(objstr->GetName())) {
1002 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
1003 objstr->GetName(), workdir.Data());
1007 Bool_t iscoll, isxml, usetags;
1008 CheckDataType(file, iscoll, isxml, usetags);
1011 isCollection = iscoll;
1014 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
1016 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
1017 Error("CheckInputData", "Some conflict was found in the types of inputs");
1023 // Process requested run numbers
1024 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
1025 // Check validity of alien data directory
1026 if (!fGridDataDir.Length()) {
1027 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
1030 if (!DirectoryExists(fGridDataDir)) {
1031 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
1035 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
1039 if (checked && !isXml) {
1040 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
1043 // Check validity of run number(s)
1048 TString schunk, schunk2;
1052 useTags = fDataPattern.Contains("tag");
1053 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
1055 if (useTags != fDataPattern.Contains("tag")) {
1056 Error("CheckInputData", "Cannot mix input files using/not using tags");
1059 if (fRunNumbers.Length()) {
1060 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
1061 arr = fRunNumbers.Tokenize(" ");
1063 while ((os=(TObjString*)next())) {
1064 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
1065 if (!DirectoryExists(path)) {
1066 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
1069 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
1070 TString msg = "\n##### file: ";
1072 msg += " type: xml_collection;";
1073 if (useTags) msg += " using_tags: Yes";
1074 else msg += " using_tags: No";
1075 Info("CheckDataType", "%s", msg.Data());
1076 if (fNrunsPerMaster<2) {
1077 AddDataFile(Form("%s.xml", os->GetString().Data()));
1080 if (((nruns-1)%fNrunsPerMaster) == 0) {
1081 schunk = os->GetString();
1083 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
1084 schunk += Form("_%s.xml", os->GetString().Data());
1085 AddDataFile(schunk);
1090 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1091 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1092 format = Form("%%s/%s ", fRunPrefix.Data());
1093 path = Form(format.Data(), fGridDataDir.Data(), irun);
1094 if (!DirectoryExists(path)) {
1097 format = Form("%%s/%s.xml", fRunPrefix.Data());
1098 path = Form(format.Data(), workdir.Data(),irun);
1099 TString msg = "\n##### file: ";
1101 msg += " type: xml_collection;";
1102 if (useTags) msg += " using_tags: Yes";
1103 else msg += " using_tags: No";
1104 Info("CheckDataType", "%s", msg.Data());
1105 if (fNrunsPerMaster<2) {
1106 format = Form("%s.xml", fRunPrefix.Data());
1107 AddDataFile(Form(format.Data(),irun));
1110 if (((nruns-1)%fNrunsPerMaster) == 0) {
1111 schunk = Form(fRunPrefix.Data(),irun);
1113 format = Form("_%s.xml", fRunPrefix.Data());
1114 schunk2 = Form(format.Data(), irun);
1115 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1117 AddDataFile(schunk);
1122 AddDataFile(schunk);
1128 //______________________________________________________________________________
1129 Int_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1131 // Copy data from the given grid directory according a pattern and make a local
1133 // 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
1135 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1138 if (!DirectoryExists(griddir)) {
1139 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1142 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1143 printf("Running command: %s\n", command.Data());
1144 TGridResult *res = gGrid->Command(command);
1145 Int_t nfound = res->GetEntries();
1147 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1150 printf("... found %d files. Copying locally ...\n", nfound);
1153 TObjArray* additionalArchives = 0;
1154 if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1155 additionalArchives = TString(archivefile).Tokenize(";");
1156 archivefile = additionalArchives->At(0)->GetName();
1157 additionalArchives->RemoveAt(0);
1158 additionalArchives->Compress();
1161 // Copy files locally
1163 out.open(output, ios::out);
1165 TString turl, dirname, filename, temp;
1166 TString cdir = gSystem->WorkingDirectory();
1167 gSystem->MakeDirectory(outputdir);
1168 gSystem->ChangeDirectory(outputdir);
1170 for (Int_t i=0; i<nfound; i++) {
1171 map = (TMap*)res->At(i);
1172 turl = map->GetValue("turl")->GetName();
1173 filename = gSystem->BaseName(turl.Data());
1174 dirname = gSystem->DirName(turl.Data());
1175 dirname = gSystem->BaseName(dirname.Data());
1176 gSystem->MakeDirectory(dirname);
1178 TString source(turl);
1179 TString targetFileName(filename);
1181 if (strlen(archivefile) > 0) {
1182 // TODO here the archive in which the file resides should be determined
1183 // however whereis returns only a guid, and guid2lfn does not work
1184 // Therefore we use the one provided as argument for now
1185 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1186 targetFileName = archivefile;
1188 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1189 Bool_t success = kTRUE;
1190 if (additionalArchives) {
1191 for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++) {
1193 target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1194 gSystem->MakeDirectory(gSystem->DirName(target));
1195 success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1200 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1201 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1206 gSystem->ChangeDirectory(cdir);
1208 delete additionalArchives;
1212 //______________________________________________________________________________
1213 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1215 // Create dataset for the grid data directory + run number.
1216 const Int_t gMaxEntries = 15000;
1217 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1219 Error("CreateDataset", "Cannot create dataset with no grid connection");
1224 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1225 TString workdir = gGrid->GetHomeDirectory();
1226 workdir += fGridWorkingDir;
1228 // Compose the 'find' command arguments
1231 TString delimiter = pattern;
1233 if (delimiter.Contains(" ")) delimiter = "";
1234 else delimiter = " ";
1235 TString options = "-x collection ";
1236 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1237 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1238 TString conditions = "";
1245 TString schunk, schunk2;
1246 TGridCollection *cbase=0, *cadd=0;
1247 if (!fRunNumbers.Length() && !fRunRange[0]) {
1248 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1249 // Make a single data collection from data directory.
1250 path = fGridDataDir;
1251 if (!DirectoryExists(path)) {
1252 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1256 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1257 else file = Form("%s.xml", gSystem->BaseName(path));
1258 // cholm - Identical loop - should be put in common function for code simplification
1262 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1264 command += Form("%s -o %d ",options.Data(), nstart);
1266 command += delimiter;
1268 command += conditions;
1269 printf("command: %s\n", command.Data());
1270 TGridResult *res = gGrid->Command(command);
1271 if (res) delete res;
1272 // Write standard output to file
1273 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1274 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1275 Bool_t nullFile = kFALSE;
1277 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1279 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1281 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1282 gSystem->Exec("rm -f __tmp*");
1290 gSystem->Exec("rm -f __tmp__");
1291 ncount = line.Atoi();
1294 if (ncount == gMaxEntries) {
1295 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1296 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1297 if (!cbase) cbase = cadd;
1299 // cholm - Avoid using very slow TAlienCollection
1300 // cbase->Add(cadd);
1301 // cholm - Use AddFast (via interpreter)
1302 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1308 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1309 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1310 // cholm - Avoid using very slow TAlienCollection
1311 // cbase->Add(cadd);
1312 // cholm - Use AddFast (via interpreter)
1313 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1315 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1316 delete cbase; cbase = 0;
1318 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1320 gSystem->Exec("rm -f __tmp*");
1321 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1325 Bool_t fileExists = FileExists(file);
1326 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1327 // Copy xml file to alien space
1328 if (fileExists) gGrid->Rm(file);
1329 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1330 if (!FileExists(file)) {
1331 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1334 // Update list of files to be processed.
1336 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1340 Bool_t nullResult = kTRUE;
1341 if (fRunNumbers.Length()) {
1342 TObjArray *arr = fRunNumbers.Tokenize(" ");
1345 while ((os=(TObjString*)next())) {
1348 path = Form("%s/%s", fGridDataDir.Data(), os->GetString().Data());
1349 if (!DirectoryExists(path)) continue;
1351 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1352 else file = Form("%s.xml", os->GetString().Data());
1353 // cholm - Identical loop - should be put in common function for code simplification
1354 // If local collection file does not exist, create it via 'find' command.
1358 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1360 command += Form("%s -o %d ",options.Data(), nstart);
1362 command += delimiter;
1364 command += conditions;
1365 TGridResult *res = gGrid->Command(command);
1366 if (res) delete res;
1367 // Write standard output to file
1368 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1369 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1370 Bool_t nullFile = kFALSE;
1372 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1374 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1376 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1377 gSystem->Exec("rm -f __tmp*");
1378 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1386 gSystem->Exec("rm -f __tmp__");
1387 ncount = line.Atoi();
1389 nullResult = kFALSE;
1391 if (ncount == gMaxEntries) {
1392 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1393 if (fNrunsPerMaster > 1) {
1394 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1395 file.Data(),gMaxEntries);
1398 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1399 if (!cbase) cbase = cadd;
1401 // cholm - Avoid using very slow TAlienCollection
1402 // cbase->Add(cadd);
1403 // cholm - Use AddFast (via interpreter)
1404 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1410 if (cbase && fNrunsPerMaster<2) {
1411 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1412 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1413 // cholm - Avoid using very slow TAlienCollection
1414 // cbase->Add(cadd);
1415 // cholm - Use AddFast (via interpreter)
1416 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1418 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1419 delete cbase; cbase = 0;
1421 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1423 gSystem->Exec("rm -f __tmp*");
1424 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1428 if (TestBit(AliAnalysisGrid::kTest)) break;
1429 // Check if there is one run per master job.
1430 if (fNrunsPerMaster<2) {
1431 if (FileExists(file)) {
1432 if (fOverwriteMode) gGrid->Rm(file);
1434 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1438 // Copy xml file to alien space
1439 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1440 if (!FileExists(file)) {
1441 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1447 if (((nruns-1)%fNrunsPerMaster) == 0) {
1448 schunk = os->GetString();
1449 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1451 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1452 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1453 // cholm - Avoid using very slow TAlienCollection
1454 // cbase->Add(cadd);
1455 // cholm - Use AddFast (via interpreter)
1456 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1459 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1462 schunk += Form("_%s.xml", os->GetString().Data());
1463 if (FileExists(schunk)) {
1464 if (fOverwriteMode) gGrid->Rm(file);
1466 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1470 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1471 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1472 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1473 if (!FileExists(schunk)) {
1474 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1482 Error("CreateDataset", "No valid dataset corresponding to the query!");
1486 // Process a full run range.
1487 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1488 format = Form("%%s/%s", fRunPrefix.Data());
1491 path = Form(format.Data(), fGridDataDir.Data(), irun);
1492 if (!DirectoryExists(path)) continue;
1494 format = Form("%s.xml", fRunPrefix.Data());
1495 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1496 else file = Form(format.Data(), irun);
1497 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1498 if (fOverwriteMode) gGrid->Rm(file);
1500 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1504 // cholm - Identical loop - should be put in common function for code simplification
1505 // If local collection file does not exist, create it via 'find' command.
1509 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1511 command += Form("%s -o %d ",options.Data(), nstart);
1513 command += delimiter;
1515 command += conditions;
1516 TGridResult *res = gGrid->Command(command);
1517 if (res) delete res;
1518 // Write standard output to file
1519 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1520 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1521 Bool_t nullFile = kFALSE;
1523 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1525 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1527 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1528 gSystem->Exec("rm -f __tmp*");
1536 gSystem->Exec("rm -f __tmp__");
1537 ncount = line.Atoi();
1539 nullResult = kFALSE;
1541 if (ncount == gMaxEntries) {
1542 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1543 if (fNrunsPerMaster > 1) {
1544 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1545 file.Data(),gMaxEntries);
1548 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1549 if (!cbase) cbase = cadd;
1551 // cholm - Avoid using very slow TAlienCollection
1552 // cbase->Add(cadd);
1553 // cholm - Use AddFast (via interpreter)
1554 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1559 if (cbase && fNrunsPerMaster<2) {
1560 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1561 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1562 // cholm - Avoid using very slow TAlienCollection
1563 // cbase->Add(cadd);
1564 // cholm - Use AddFast (via interpreter)
1565 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1567 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1568 delete cbase; cbase = 0;
1570 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1572 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1576 if (TestBit(AliAnalysisGrid::kTest)) break;
1577 // Check if there is one run per master job.
1578 if (fNrunsPerMaster<2) {
1579 if (FileExists(file)) {
1580 if (fOverwriteMode) gGrid->Rm(file);
1582 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1586 // Copy xml file to alien space
1587 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1588 if (!FileExists(file)) {
1589 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1594 // Check if the collection for the chunk exist locally.
1595 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1596 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1597 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1600 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1601 if (((nruns-1)%fNrunsPerMaster) == 0) {
1602 schunk = Form(fRunPrefix.Data(), irun);
1603 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1605 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1606 // cholm - Avoid using very slow TAlienCollection
1607 // cbase->Add(cadd);
1608 // cholm - Use AddFast (via interpreter)
1609 gROOT->ProcessLine(Form("((TAlienCollection*)%p)->AddFast((TGridCollection*)%p)",cbase,cadd));
1612 format = Form("%%s_%s.xml", fRunPrefix.Data());
1613 schunk2 = Form(format.Data(), schunk.Data(), irun);
1614 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1618 if (FileExists(schunk)) {
1619 if (fOverwriteMode) gGrid->Rm(schunk);
1621 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1625 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1626 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1627 if (FileExists(schunk)) {
1628 if (fOverwriteMode) gGrid->Rm(schunk);
1630 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1634 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1635 if (!FileExists(schunk)) {
1636 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1642 Error("CreateDataset", "No valid dataset corresponding to the query!");
1649 //______________________________________________________________________________
1650 Bool_t AliAnalysisAlien::CreateJDL()
1652 // Generate a JDL file according to current settings. The name of the file is
1653 // specified by fJDLName.
1654 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1655 Bool_t error = kFALSE;
1657 Bool_t copy = kTRUE;
1658 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1659 Bool_t generate = kTRUE;
1660 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1662 Error("CreateJDL", "Alien connection required");
1665 // Check validity of alien workspace
1667 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1668 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1669 workdir += fGridWorkingDir;
1672 if (!fInputFiles && !fMCLoop) {
1673 Error("CreateJDL()", "Define some input files for your analysis.");
1676 // Compose list of input files
1677 // Check if output files were defined
1678 if (!fOutputFiles.Length()) {
1679 Error("CreateJDL", "You must define at least one output file");
1682 // Check if an output directory was defined and valid
1683 if (!fGridOutputDir.Length()) {
1684 Error("CreateJDL", "You must define AliEn output directory");
1687 if (!fProductionMode) {
1688 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1689 if (!DirectoryExists(fGridOutputDir)) {
1690 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1691 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1693 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1697 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1702 // Exit if any error up to now
1703 if (error) return kFALSE;
1705 if (!fUser.IsNull()) {
1706 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1707 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1709 TString executable = fExecutable;
1710 if (!executable.BeginsWith("/"))
1711 executable.Prepend(Form("%s/", workdir.Data()));
1712 fGridJDL->SetExecutable(executable, "This is the startup script");
1713 TString mergeExec = executable;
1714 mergeExec.ReplaceAll(".sh", "_merge.sh");
1715 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1716 mergeExec.ReplaceAll(".sh", ".C");
1717 fMergingJDL->AddToInputSandbox(Form("LF:%s", mergeExec.Data()), "List of input files to be uploaded to workers");
1718 if (!fArguments.IsNull())
1719 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1720 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1722 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1723 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1726 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1727 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1728 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1729 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1731 if (fMaxInitFailed > 0) {
1732 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1733 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1735 if (fSplitMaxInputFileNumber > 0 && !fMCLoop) {
1736 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1737 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1739 if (!IsOneStageMerging()) {
1740 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1741 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1743 if (fSplitMode.Length()) {
1744 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1745 fGridJDL->SetDescription("Split", "We split per SE or file");
1747 fMergingJDL->SetValue("Split", "\"se\"");
1748 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1749 if (!fAliROOTVersion.IsNull()) {
1750 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1751 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1753 if (!fROOTVersion.IsNull()) {
1754 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1755 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1757 if (!fAPIVersion.IsNull()) {
1758 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1759 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1761 if (!fExternalPackages.IsNull()) {
1762 arr = fExternalPackages.Tokenize(" ");
1764 while ((os=(TObjString*)next())) {
1765 TString pkgname = os->GetString();
1766 Int_t index = pkgname.Index("::");
1767 TString pkgversion = pkgname(index+2, pkgname.Length());
1768 pkgname.Remove(index);
1769 fGridJDL->AddToPackages(pkgname, pkgversion);
1770 fMergingJDL->AddToPackages(pkgname, pkgversion);
1775 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1776 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1778 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1779 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1780 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1781 TString analysisFile = fExecutable;
1782 analysisFile.ReplaceAll(".sh", ".root");
1783 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1784 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1785 if (fAdditionalLibs.Length()) {
1786 arr = fAdditionalLibs.Tokenize(" ");
1788 while ((os=(TObjString*)next())) {
1789 if (os->GetString().Contains(".so") ||
1790 os->GetString().Contains(".dylib")) continue;
1791 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1792 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1797 TIter next(fPackages);
1799 while ((obj=next())) {
1800 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1801 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1804 const char *comment = "List of output files and archives";
1805 if (fOutputArchive.Length()) {
1806 TString outputArchive = fOutputArchive;
1807 if (!fRegisterExcludes.IsNull()) {
1808 arr = fRegisterExcludes.Tokenize(" ");
1810 while ((os=(TObjString*)next1())) {
1811 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1812 outputArchive.ReplaceAll(os->GetString(),"");
1816 arr = outputArchive.Tokenize(" ");
1818 Bool_t first = kTRUE;
1819 while ((os=(TObjString*)next())) {
1820 if (!os->GetString().Contains("@") && fCloseSE.Length())
1821 fGridJDL->AddToSet("Output", Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
1823 fGridJDL->AddToSet("Output", os->GetString());
1824 if (first) fGridJDL->AddToSetDescription("Output", comment);
1828 // Output archive for the merging jdl
1829 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1830 outputArchive = "log_archive.zip:std*@disk=1 ";
1831 // Add normal output files, extra files + terminate files
1833 if (IsMergeAOD()) files = GetListOfFiles("outaodextter");
1834 else files = GetListOfFiles("outextter");
1835 // Do not register files in fRegisterExcludes
1836 if (!fRegisterExcludes.IsNull()) {
1837 arr = fRegisterExcludes.Tokenize(" ");
1839 while ((os=(TObjString*)next1())) {
1840 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1841 files.ReplaceAll(os->GetString(),"");
1845 files.ReplaceAll(".root", "*.root");
1847 if (mgr->IsCollectThroughput())
1848 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d %s@disk=%d",files.Data(),fNreplicas, mgr->GetFileInfoLog(),fNreplicas);
1850 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1852 TString files = fOutputArchive;
1853 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1854 outputArchive = files;
1856 arr = outputArchive.Tokenize(" ");
1859 while ((os=(TObjString*)next2())) {
1860 TString currentfile = os->GetString();
1861 if (!currentfile.Contains("@") && fCloseSE.Length())
1862 fMergingJDL->AddToSet("Output", Form("%s@%s",currentfile.Data(), fCloseSE.Data()));
1864 fMergingJDL->AddToSet("Output", currentfile);
1865 if (first) fMergingJDL->AddToSetDescription("Output", comment);
1870 arr = fOutputFiles.Tokenize(",");
1872 Bool_t first = kTRUE;
1873 while ((os=(TObjString*)next())) {
1874 // Ignore ouputs in jdl that are also in outputarchive
1875 TString sout = os->GetString();
1876 sout.ReplaceAll("*", "");
1877 sout.ReplaceAll(".root", "");
1878 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1879 if (fOutputArchive.Contains(sout)) continue;
1880 // Ignore fRegisterExcludes
1881 if (fRegisterExcludes.Contains(sout)) continue;
1882 if (!first) comment = NULL;
1883 if (!os->GetString().Contains("@") && fCloseSE.Length())
1884 fGridJDL->AddToSet("Output", Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
1886 fGridJDL->AddToSet("Output", os->GetString());
1887 if (first) fGridJDL->AddToSetDescription("Output", comment);
1888 if (fMergeExcludes.Contains(sout)) continue;
1889 if (!os->GetString().Contains("@") && fCloseSE.Length())
1890 fMergingJDL->AddToSet("Output", Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
1892 fMergingJDL->AddToSet("Output", os->GetString());
1893 if (first) fMergingJDL->AddToSetDescription("Output", comment);
1897 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1898 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1899 TString validationScript = fValidationScript;
1900 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1901 validationScript.ReplaceAll(".sh", "_merge.sh");
1902 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1903 if (fMasterResubmitThreshold) {
1904 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1905 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1907 // Write a jdl with 2 input parameters: collection name and output dir name.
1910 // Copy jdl to grid workspace
1912 // Check if an output directory was defined and valid
1913 if (!fGridOutputDir.Length()) {
1914 Error("CreateJDL", "You must define AliEn output directory");
1917 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1918 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1919 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1920 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1922 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1928 if (TestBit(AliAnalysisGrid::kSubmit)) {
1929 TString mergeJDLName = fExecutable;
1930 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1931 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1932 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1933 if (fProductionMode) {
1934 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1935 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1937 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1938 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1939 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1940 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1941 Fatal("","Terminating");
1942 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1944 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1945 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1946 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1947 Fatal("","Terminating");
1950 if (fAdditionalLibs.Length()) {
1951 arr = fAdditionalLibs.Tokenize(" ");
1954 while ((os=(TObjString*)next())) {
1955 if (os->GetString().Contains(".so") ||
1956 os->GetString().Contains(".dylib")) continue;
1957 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1958 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1959 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1960 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1961 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1962 Fatal("","Terminating");
1967 TIter next(fPackages);
1969 while ((obj=next())) {
1970 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1971 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1972 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1973 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1974 Form("%s/%s", workdir.Data(), obj->GetName())))
1975 Fatal("","Terminating");
1982 //______________________________________________________________________________
1983 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1985 // Writes one or more JDL's corresponding to findex. If findex is negative,
1986 // all run numbers are considered in one go (jdl). For non-negative indices
1987 // they correspond to the indices in the array fInputFiles.
1988 if (!fInputFiles && !fMCLoop) return kFALSE;
1991 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1992 workdir += fGridWorkingDir;
1993 TString stageName = "$2";
1994 if (fProductionMode) stageName = "$4";
1995 if (!fMergeDirName.IsNull()) {
1996 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1997 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1999 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
2000 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
2002 if (fProductionMode) {
2003 TIter next(fInputFiles);
2004 while ((os=next())) {
2005 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
2007 if (!fOutputToRunNo)
2008 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
2010 fGridJDL->SetOutputDirectory(fGridOutputDir);
2012 if (!fRunNumbers.Length() && !fRunRange[0]) {
2013 // One jdl with no parameters in case input data is specified by name.
2014 TIter next(fInputFiles);
2016 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
2017 if (!fOutputSingle.IsNull())
2018 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
2020 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
2021 // fMergingJDL->SetOutputDirectory(fGridOutputDir);
2024 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
2025 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
2026 if (!fOutputSingle.IsNull()) {
2027 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
2028 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
2030 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
2035 // Generate the JDL as a string
2036 TString sjdl = fGridJDL->Generate();
2037 TString sjdl1 = fMergingJDL->Generate();
2039 if (!fMergeDirName.IsNull()) {
2040 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
2041 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
2043 fMergingJDL->SetOutputDirectory("$1", "Output directory");
2044 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
2046 TString sjdl2 = fMergingJDL->Generate();
2047 Int_t index, index1;
2048 sjdl.ReplaceAll("\",\"", "\",\n \"");
2049 sjdl.ReplaceAll("(member", "\n (member");
2050 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
2051 sjdl.ReplaceAll("{", "{\n ");
2052 sjdl.ReplaceAll("};", "\n};");
2053 sjdl.ReplaceAll("{\n \n", "{\n");
2054 sjdl.ReplaceAll("\n\n", "\n");
2055 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
2056 sjdl1.ReplaceAll("\",\"", "\",\n \"");
2057 sjdl1.ReplaceAll("(member", "\n (member");
2058 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
2059 sjdl1.ReplaceAll("{", "{\n ");
2060 sjdl1.ReplaceAll("};", "\n};");
2061 sjdl1.ReplaceAll("{\n \n", "{\n");
2062 sjdl1.ReplaceAll("\n\n", "\n");
2063 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
2064 sjdl2.ReplaceAll("\",\"", "\",\n \"");
2065 sjdl2.ReplaceAll("(member", "\n (member");
2066 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
2067 sjdl2.ReplaceAll("{", "{\n ");
2068 sjdl2.ReplaceAll("};", "\n};");
2069 sjdl2.ReplaceAll("{\n \n", "{\n");
2070 sjdl2.ReplaceAll("\n\n", "\n");
2071 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
2072 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
2073 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
2074 index = sjdl.Index("JDLVariables");
2075 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
2076 sjdl += "Workdirectorysize = {\"5000MB\"};";
2077 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
2078 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
2079 index = fJobTag.Index(":");
2080 if (index < 0) index = fJobTag.Length();
2081 TString jobTag = fJobTag;
2082 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
2083 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
2084 if (fProductionMode) {
2085 sjdl1.Prepend("# Generated merging jdl (production mode) \
2086 \n# $1 = full alien path to output directory to be merged \
2087 \n# $2 = train number \
2088 \n# $3 = production (like LHC10b) \
2089 \n# $4 = merging stage \
2090 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2091 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
2092 sjdl2.Prepend("# Generated merging jdl \
2093 \n# $1 = full alien path to output directory to be merged \
2094 \n# $2 = train number \
2095 \n# $3 = production (like LHC10b) \
2096 \n# $4 = merging stage \
2097 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2099 sjdl1.Prepend("# Generated merging jdl \
2100 \n# $1 = full alien path to output directory to be merged \
2101 \n# $2 = merging stage \
2102 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2103 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
2104 sjdl2.Prepend("# Generated merging jdl \
2105 \n# $1 = full alien path to output directory to be merged \
2106 \n# $2 = merging stage \
2107 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2109 index = sjdl1.Index("JDLVariables");
2110 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
2111 index = sjdl2.Index("JDLVariables");
2112 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
2113 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
2114 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
2115 index = sjdl2.Index("Split =");
2117 index1 = sjdl2.Index("\n", index);
2118 sjdl2.Remove(index, index1-index+1);
2120 index = sjdl2.Index("SplitMaxInputFileNumber");
2122 index1 = sjdl2.Index("\n", index);
2123 sjdl2.Remove(index, index1-index+1);
2125 index = sjdl2.Index("InputDataCollection");
2127 index1 = sjdl2.Index(";", index);
2128 sjdl2.Remove(index, index1-index+1);
2130 index = sjdl2.Index("InputDataListFormat");
2132 index1 = sjdl2.Index("\n", index);
2133 sjdl2.Remove(index, index1-index+1);
2135 index = sjdl2.Index("InputDataList");
2137 index1 = sjdl2.Index("\n", index);
2138 sjdl2.Remove(index, index1-index+1);
2140 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
2141 // Write jdl to file
2143 out.open(fJDLName.Data(), ios::out);
2145 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2148 out << sjdl << endl;
2150 TString mergeJDLName = fExecutable;
2151 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2154 out1.open(mergeJDLName.Data(), ios::out);
2156 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2159 out1 << sjdl1 << endl;
2162 TString finalJDL = mergeJDLName;
2163 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2164 out2.open(finalJDL.Data(), ios::out);
2166 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2169 out2 << sjdl2 << endl;
2173 // Copy jdl to grid workspace
2175 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2177 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2178 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2179 TString finalJDL = mergeJDLName;
2180 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2181 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2182 if (fProductionMode) {
2183 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2184 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2185 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2187 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2188 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2189 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2190 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2191 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2192 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2193 Fatal("","Terminating");
2195 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2196 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2197 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2198 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2199 Fatal("","Terminating");
2200 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2201 Fatal("","Terminating");
2207 //______________________________________________________________________________
2208 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2210 // Returns true if file exists.
2211 if (!gGrid) return kFALSE;
2213 slfn.ReplaceAll("alien://","");
2214 TGridResult *res = gGrid->Ls(slfn);
2215 if (!res) return kFALSE;
2216 TMap *map = dynamic_cast<TMap*>(res->At(0));
2221 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2222 if (!objs || !objs->GetString().Length()) {
2230 //______________________________________________________________________________
2231 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2233 // Returns true if directory exists. Can be also a path.
2234 // Since there is not API in TAlien, we use the Cd trick:
2235 if (!gGrid) return kFALSE;
2236 // Backup current path
2237 TString cpath = gGrid->Pwd();
2238 TString command = "cd ";
2239 TString sdir(dirname);
2240 sdir.ReplaceAll("alien://", "");
2242 TGridResult *res = gGrid->Command(command);
2247 TMap *map = (TMap*)res->At(0);
2253 TString sval = map->GetValue("__result__")->GetName();
2254 Bool_t retval = (Bool_t)sval.Atoi();
2260 //______________________________________________________________________________
2261 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2263 // Check input data type.
2264 isCollection = kFALSE;
2268 Error("CheckDataType", "No connection to grid");
2271 isCollection = IsCollection(lfn);
2272 TString msg = "\n##### file: ";
2275 msg += " type: raw_collection;";
2276 // special treatment for collections
2278 // check for tag files in the collection
2279 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2281 msg += " using_tags: No (unknown)";
2282 Info("CheckDataType", "%s", msg.Data());
2285 const char* typeStr = res->GetKey(0, "origLFN");
2286 if (!typeStr || !strlen(typeStr)) {
2287 msg += " using_tags: No (unknown)";
2288 Info("CheckDataType", "%s", msg.Data());
2291 TString file = typeStr;
2292 useTags = file.Contains(".tag");
2293 if (useTags) msg += " using_tags: Yes";
2294 else msg += " using_tags: No";
2295 Info("CheckDataType", "%s", msg.Data());
2300 isXml = slfn.Contains(".xml");
2302 // Open xml collection and check if there are tag files inside
2303 msg += " type: xml_collection;";
2304 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2306 msg += " using_tags: No (unknown)";
2307 Info("CheckDataType", "%s", msg.Data());
2310 TMap *map = coll->Next();
2312 msg += " using_tags: No (unknown)";
2313 Info("CheckDataType", "%s", msg.Data());
2316 map = (TMap*)map->GetValue("");
2318 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2319 useTags = file.Contains(".tag");
2321 if (useTags) msg += " using_tags: Yes";
2322 else msg += " using_tags: No";
2323 Info("CheckDataType", "%s", msg.Data());
2326 useTags = slfn.Contains(".tag");
2327 if (slfn.Contains(".root")) msg += " type: root file;";
2328 else msg += " type: unknown file;";
2329 if (useTags) msg += " using_tags: Yes";
2330 else msg += " using_tags: No";
2331 Info("CheckDataType", "%s", msg.Data());
2334 //______________________________________________________________________________
2335 void AliAnalysisAlien::EnablePackage(const char *package)
2337 // Enables a par file supposed to exist in the current directory.
2338 TString pkg(package);
2339 pkg.ReplaceAll(".par", "");
2341 if (gSystem->AccessPathName(pkg)) {
2342 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2345 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2346 Info("EnablePackage", "AliEn plugin will use .par packages");
2347 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2349 fPackages = new TObjArray();
2350 fPackages->SetOwner();
2352 fPackages->Add(new TObjString(pkg));
2355 //______________________________________________________________________________
2356 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2358 // Make a tree from files having the location specified in fFileForTestMode.
2359 // Inspired from JF's CreateESDChain.
2360 if (fFileForTestMode.IsNull()) {
2361 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2364 if (gSystem->AccessPathName(fFileForTestMode)) {
2365 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2370 in.open(fFileForTestMode);
2372 // Read the input list of files and add them to the chain
2374 TString streeName(treeName);
2375 if (IsUseMCchain()) streeName = "TE";
2376 TChain *chain = new TChain(streeName);
2377 TList *friends = new TList();
2378 TChain *cfriend = 0;
2379 if (!fFriendChainName.IsNull()) {
2380 TObjArray *list = fFriendChainName.Tokenize(" ");
2383 while((str=(TObjString*)next())) {
2384 cfriend = new TChain(streeName, str->GetName());
2385 friends->Add(cfriend);
2386 chain->AddFriend(cfriend);
2391 TIter nextfriend(friends);
2395 if (line.IsNull() || line.BeginsWith("#")) continue;
2396 if (count++ == fNtestFiles) break;
2397 TString esdFile(line);
2398 TFile *file = TFile::Open(esdFile);
2399 if (file && !file->IsZombie()) {
2400 chain->Add(esdFile);
2402 if (!fFriendChainName.IsNull()) {
2403 if (esdFile.Index("#") > -1)
2404 esdFile.Remove(esdFile.Index("#"));
2405 bpath = gSystem->DirName(esdFile);
2409 while ((cfriend=(TChain*)nextfriend())) {
2411 fileFriend += cfriend->GetTitle();
2412 file = TFile::Open(fileFriend);
2413 if (file && !file->IsZombie()) {
2415 cfriend->Add(fileFriend);
2417 Fatal("GetChainForTestMode", "Cannot open friend file: %s", fileFriend.Data());
2423 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2427 if (!chain->GetListOfFiles()->GetEntries()) {
2428 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2437 //______________________________________________________________________________
2438 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2440 // Get job status for all jobs with jobid>jobidstart.
2441 static char mstatus[20];
2447 TGridJobStatusList *list = gGrid->Ps("");
2448 if (!list) return mstatus;
2449 Int_t nentries = list->GetSize();
2450 TGridJobStatus *status;
2452 for (Int_t ijob=0; ijob<nentries; ijob++) {
2453 status = (TGridJobStatus *)list->At(ijob);
2454 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2455 if (pid<jobidstart) continue;
2456 if (pid == lastid) {
2457 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2459 switch (status->GetStatus()) {
2460 case TGridJobStatus::kWAITING:
2462 case TGridJobStatus::kRUNNING:
2464 case TGridJobStatus::kABORTED:
2465 case TGridJobStatus::kFAIL:
2466 case TGridJobStatus::kUNKNOWN:
2468 case TGridJobStatus::kDONE:
2477 //______________________________________________________________________________
2478 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2480 // Returns true if file is a collection. Functionality duplicated from
2481 // TAlien::Type() because we don't want to directly depend on TAlien.
2483 Error("IsCollection", "No connection to grid");
2486 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2487 if (!res) return kFALSE;
2488 const char* typeStr = res->GetKey(0, "type");
2489 if (!typeStr || !strlen(typeStr)) return kFALSE;
2490 if (!strcmp(typeStr, "collection")) return kTRUE;
2495 //______________________________________________________________________________
2496 Bool_t AliAnalysisAlien::IsSingleOutput() const
2498 // Check if single-ouput option is on.
2499 return (!fOutputSingle.IsNull());
2502 //______________________________________________________________________________
2503 Long64_t AliAnalysisAlien::RunMacroAndExtractLibs(const char* macro, const char *args, TString &libs)
2505 // Tries to run the specified macro and return the libraries that it loads.
2507 if (strlen(macro)) expname = gSystem->ExpandPathName(macro);
2508 if (expname.IsNull() || gSystem->AccessPathName(expname)) {
2509 ::Error("RunMacroAndExtractLibs","Cannot find macro %s in current directory", macro);
2512 TString oldlibs = gSystem->GetLibraries();
2515 Long64_t retval = m.Exec(args, &error);
2516 if (error != TInterpreter::kNoError)
2518 ::Error("RunMacroAndExtractLibs", "Macro interpretation %s failed", macro);
2521 libs = gSystem->GetLibraries();
2522 libs.ReplaceAll(oldlibs, "");
2523 libs.Strip(TString::kLeading);
2524 TObjArray *libTokens = libs.Tokenize(" ");
2526 for (Int_t i=0; i<libTokens->GetEntries(); i++) {
2527 if (!libs.IsNull()) libs += " ";
2528 libs += gSystem->BaseName(libTokens->At(i)->GetName());
2534 //______________________________________________________________________________
2535 void AliAnalysisAlien::Print(Option_t *) const
2537 // Print current plugin settings.
2538 printf("### AliEn analysis plugin current settings ###\n");
2539 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2540 if (mgr && mgr->IsProofMode()) {
2541 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2542 if (TestBit(AliAnalysisGrid::kTest))
2543 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2544 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2545 if (!fProofDataSet.IsNull())
2546 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2548 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2550 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2551 if (!fROOTVersion.IsNull())
2552 printf("= ROOT version requested________________________ %s\n", fROOTVersion.Data());
2554 printf("= ROOT version requested________________________ default\n");
2555 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2556 if (!fAliRootMode.IsNull())
2557 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2559 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2560 if (fNproofWorkersPerSlave)
2561 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2562 if (TestSpecialBit(kClearPackages))
2563 printf("= ClearPackages requested...\n");
2564 if (fIncludePath.Data())
2565 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2566 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2567 if (fPackages && fPackages->GetEntries()) {
2568 TIter next(fPackages);
2571 while ((obj=next())) list += obj->GetName();
2572 printf("= Par files to be used: ________________________ %s\n", list.Data());
2574 if (TestSpecialBit(kProofConnectGrid))
2575 printf("= Requested PROOF connection to grid\n");
2578 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2579 if (fOverwriteMode) {
2580 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2581 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2583 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2584 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO:Print");
2585 printf("= Production mode:______________________________ %d\n", fProductionMode);
2586 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2587 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2588 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2590 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2591 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2592 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2593 TString basedatadir = fGridDataDir;
2594 TString pattern = fDataPattern;
2596 Int_t ind = pattern.Index(" ");
2598 basedatadir += "/%run%/";
2599 basedatadir += pattern(0, ind);
2600 pattern = pattern(ind+1, pattern.Length());
2602 printf("= Data base directory path requested: __________ %s\n", basedatadir.Data());
2603 printf("= Data search pattern: _________________________ %s\n", pattern.Data());
2604 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2605 if (fRunNumbers.Length())
2606 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2608 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2609 if (!fRunRange[0] && !fRunNumbers.Length()) {
2610 TIter next(fInputFiles);
2613 while ((obj=next())) list += obj->GetName();
2614 printf("= Input files to be processed: _________________ %s\n", list.Data());
2616 if (TestBit(AliAnalysisGrid::kTest))
2617 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2618 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2619 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2620 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2621 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2622 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2623 printf("=====================================================================\n");
2624 printf("= Job price: ___________________________________ %d\n", fPrice);
2625 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2626 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2627 if (fMaxInitFailed>0)
2628 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2629 if (fMasterResubmitThreshold>0)
2630 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2631 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2632 if (fNrunsPerMaster>0)
2633 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2634 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2635 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2636 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2637 if (fArguments.Length())
2638 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2639 if (fExecutableArgs.Length())
2640 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2641 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2642 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2643 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2644 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2646 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2647 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2648 if (fIncludePath.Data())
2649 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2650 if (fCloseSE.Length())
2651 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2652 if (fFriendChainName.Length())
2653 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2654 if (fPackages && fPackages->GetEntries()) {
2655 TIter next(fPackages);
2658 while ((obj=next())) list += obj->GetName();
2659 printf("= Par files to be used: ________________________ %s\n", list.Data());
2663 //______________________________________________________________________________
2664 void AliAnalysisAlien::SetDefaults()
2666 // Set default values for everything. What cannot be filled will be left empty.
2667 if (fGridJDL) delete fGridJDL;
2668 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2669 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2672 fSplitMaxInputFileNumber = 100;
2674 fMasterResubmitThreshold = 0;
2680 fNrunsPerMaster = 1;
2681 fMaxMergeFiles = 100;
2683 fExecutable = "analysis.sh";
2684 fExecutableCommand = "root -b -q -x";
2686 fExecutableArgs = "";
2687 fAnalysisMacro = "myAnalysis.C";
2688 fAnalysisSource = "";
2689 fAdditionalLibs = "";
2693 fAliROOTVersion = "";
2694 fUser = ""; // Your alien user name
2695 fGridWorkingDir = "";
2696 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2697 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2698 fFriendChainName = "";
2699 fGridOutputDir = "output";
2700 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2701 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2702 fInputFormat = "xml-single";
2703 fJDLName = "analysis.jdl";
2704 fJobTag = "Automatically generated analysis JDL";
2705 fMergeExcludes = "";
2708 SetCheckCopy(kTRUE);
2709 SetDefaultOutputs(kTRUE);
2713 //______________________________________________________________________________
2714 void AliAnalysisAlien::SetFriendChainName(const char *name, const char *libnames)
2716 // Set file name for the chain of friends and optionally additional libs to be loaded.
2717 // Libs should be separated by blancs.
2718 fFriendChainName = name;
2719 fFriendChainName.ReplaceAll(",", " ");
2720 fFriendChainName.Strip();
2721 fFriendChainName.ReplaceAll(" ", " ");
2723 fFriendLibs = libnames;
2724 if (fFriendLibs.Length()) {
2725 if(!fFriendLibs.Contains(".so") &&
2726 !fFriendLibs.Contains(".dylib"))
2727 Fatal("SetFriendChainName()", "You should provide explicit library names (with extension)");
2728 fFriendLibs.ReplaceAll(",", " ");
2729 fFriendLibs.Strip();
2730 fFriendLibs.ReplaceAll(" ", " ");
2734 //______________________________________________________________________________
2735 void AliAnalysisAlien::SetRootVersionForProof(const char *version)
2737 // Obsolete method. Use SetROOTVersion instead
2738 Warning("SetRootVersionForProof", "Obsolete. Use SetROOTVersion instead");
2739 if (fROOTVersion.IsNull()) SetROOTVersion(version);
2740 else Error("SetRootVersionForProof", "ROOT version already set to %s", fROOTVersion.Data());
2743 //______________________________________________________________________________
2744 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2746 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2747 // First check if the result is already in the output directory.
2748 if (FileExists(Form("%s/%s",aliendir,filename))) {
2749 printf("Final merged results found. Not merging again.\n");
2752 // Now check the last stage done.
2755 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2758 // Next stage of merging
2760 TString pattern = "*root_archive.zip";
2761 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2762 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2763 if (res) delete res;
2764 // Write standard output to file
2765 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2766 // Count the number of files inside
2768 ifile.open(Form("Stage_%d.xml",stage));
2769 if (!ifile.good()) {
2770 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2775 while (!ifile.eof()) {
2777 if (line.Contains("/event")) nfiles++;
2781 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2784 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2786 // Copy the file in the output directory
2787 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2788 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2789 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2790 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2791 // Check if this is the last stage to be done.
2792 Bool_t laststage = (nfiles<nperchunk);
2793 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2796 printf("### Submiting final merging stage %d\n", stage);
2797 TString finalJDL = jdl;
2798 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2799 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2800 jobId = SubmitSingleJob(query);
2802 printf("### Submiting merging stage %d\n", stage);
2803 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2804 jobId = SubmitSingleJob(query);
2806 if (!jobId) return kFALSE;
2808 if (!fGridJobIDs.IsNull()) fGridJobIDs.Append(" ");
2809 fGridJobIDs.Append(Form("%d", jobId));
2810 if (!fGridStages.IsNull()) fGridStages.Append(" ");
2811 fGridStages.Append(Form("%s_merge_stage%d",
2812 laststage ? "final" : "partial", stage));
2817 //______________________________________________________________________________
2818 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2820 // Loat the analysis manager from a file.
2821 TFile *file = TFile::Open(fname);
2823 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2826 TIter nextkey(file->GetListOfKeys());
2827 AliAnalysisManager *mgr = 0;
2829 while ((key=(TKey*)nextkey())) {
2830 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2831 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2834 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2838 //______________________________________________________________________________
2839 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2841 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2842 if (!gGrid) return 0;
2843 printf("=> %s ------> ",query);
2844 TGridResult *res = gGrid->Command(query);
2846 TString jobId = res->GetKey(0,"jobId");
2848 if (jobId.IsNull()) {
2849 printf("submission failed. Reason:\n");
2852 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2855 Int_t ijobId = jobId.Atoi();
2856 printf(" Job id: '%s' (%d)\n", jobId.Data(), ijobId);
2860 //______________________________________________________________________________
2861 Bool_t AliAnalysisAlien::MergeInfo(const char *output, const char *collection)
2863 // Merges a collection of output files using concatenation.
2864 TString scoll(collection);
2865 if (!scoll.Contains(".xml")) return kFALSE;
2866 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", collection));
2868 ::Error("MergeInfo", "Input XML %s collection empty.", collection);
2871 // Iterate grid collection
2873 Bool_t merged = kFALSE;
2875 while (coll->Next()) {
2876 TString fname = gSystem->DirName(coll->GetTURL());
2879 outtmp = Form("%d_%s", ifile, output);
2880 if (!TFile::Cp(fname, outtmp)) {
2881 ::Error("MergeInfo", "Could not copy %s", fname.Data());
2886 gSystem->Exec(Form("cp %s lastmerged", outtmp.Data()));
2889 gSystem->Exec(Form("cat lastmerged %s > tempmerged", outtmp.Data()));
2890 gSystem->Exec("cp tempmerged lastmerged");
2893 gSystem->Exec(Form("cp lastmerged %s", output));
2894 gSystem->Exec(Form("rm tempmerged lastmerged *_%s", output));
2900 //______________________________________________________________________________
2901 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2903 // Merge given output files from basedir. Basedir can be an alien output directory
2904 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2905 // files in a group (ignored for xml input). Merging can be done in stages:
2906 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2907 // stage=1 : works with an xml of all root_archive.zip in the output directory
2908 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2909 TString outputFile = output;
2911 TString outputChunk;
2912 TString previousChunk = "";
2913 TObjArray *listoffiles = new TObjArray();
2914 // listoffiles->SetOwner();
2915 Int_t countChunk = 0;
2916 Int_t countZero = nmaxmerge;
2917 Bool_t merged = kTRUE;
2918 Bool_t isGrid = kTRUE;
2919 Int_t index = outputFile.Index("@");
2920 if (index > 0) outputFile.Remove(index);
2921 TString inputFile = outputFile;
2922 TString sbasedir = basedir;
2923 if (sbasedir.Contains(".xml")) {
2924 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2925 nmaxmerge = 9999999;
2926 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2928 ::Error("MergeOutput", "Input XML collection empty.");
2931 // Iterate grid collection
2932 while (coll->Next()) {
2933 TString fname = gSystem->DirName(coll->GetTURL());
2936 listoffiles->Add(new TNamed(fname.Data(),""));
2938 } else if (sbasedir.Contains(".txt")) {
2939 // The file having the .txt extension is expected to contain a list of
2940 // folders where the output files will be looked. For alien folders,
2941 // the full folder LFN is expected (starting with alien://)
2942 // Assume lfn's on each line
2947 ::Error("MergeOutput", "File %s cannot be opened. Merging stopped." ,sbasedir.Data());
2953 if (line.IsNull() || line.BeginsWith("#")) continue;
2955 if (!line.Contains("alien:")) isGrid = kFALSE;
2959 listoffiles->Add(new TNamed(line.Data(),""));
2963 ::Error("MergeOutput","Input file %s contains no files to be merged\n", sbasedir.Data());
2968 command = Form("find %s/ *%s", basedir, inputFile.Data());
2969 printf("command: %s\n", command.Data());
2970 TGridResult *res = gGrid->Command(command);
2972 ::Error("MergeOutput","No result for the find command\n");
2978 while ((map=(TMap*)nextmap())) {
2979 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2980 if (!objs || !objs->GetString().Length()) {
2981 // Nothing found - skip this output
2986 listoffiles->Add(new TNamed(objs->GetName(),""));
2990 if (!listoffiles->GetEntries()) {
2991 ::Error("MergeOutput","No result for the find command\n");
2996 TFileMerger *fm = 0;
2997 TIter next0(listoffiles);
2998 TObjArray *listoffilestmp = new TObjArray();
2999 listoffilestmp->SetOwner();
3002 // Keep only the files at upper level
3003 Int_t countChar = 0;
3004 while ((nextfile=next0())) {
3005 snextfile = nextfile->GetName();
3006 Int_t crtCount = snextfile.CountChar('/');
3007 if (nextfile == listoffiles->First()) countChar = crtCount;
3008 if (crtCount < countChar) countChar = crtCount;
3011 while ((nextfile=next0())) {
3012 snextfile = nextfile->GetName();
3013 Int_t crtCount = snextfile.CountChar('/');
3014 if (crtCount > countChar) {
3018 listoffilestmp->Add(nextfile);
3021 listoffiles = listoffilestmp; // Now contains 'good' files
3022 listoffiles->Print();
3023 TIter next(listoffiles);
3024 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
3025 outputChunk = outputFile;
3026 outputChunk.ReplaceAll(".root", "_*.root");
3027 // Check for existent temporary merge files
3028 // Check overwrite mode and remove previous partial results if needed
3029 // Preserve old merging functionality for stage 0.
3031 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
3033 // Skip as many input files as in a chunk
3034 for (Int_t counter=0; counter<nmaxmerge; counter++) {
3037 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
3041 snextfile = nextfile->GetName();
3043 outputChunk = outputFile;
3044 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
3046 if (gSystem->AccessPathName(outputChunk)) continue;
3047 // Merged file with chunks up to <countChunk> found
3048 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
3049 previousChunk = outputChunk;
3053 countZero = nmaxmerge;
3055 while ((nextfile=next())) {
3056 snextfile = nextfile->GetName();
3057 // Loop 'find' results and get next LFN
3058 if (countZero == nmaxmerge) {
3059 // First file in chunk - create file merger and add previous chunk if any.
3060 fm = new TFileMerger(isGrid);
3061 fm->SetFastMethod(kTRUE);
3062 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
3063 outputChunk = outputFile;
3064 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
3066 // If last file found, put merged results in the output file
3067 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
3068 // Add file to be merged and decrement chunk counter.
3069 fm->AddFile(snextfile);
3071 if (countZero==0 || nextfile == listoffiles->Last()) {
3072 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
3073 // Nothing found - skip this output
3074 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
3078 fm->OutputFile(outputChunk);
3079 // Merge the outputs, then go to next chunk
3081 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
3085 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
3086 gSystem->Unlink(previousChunk);
3088 if (nextfile == listoffiles->Last()) break;
3090 countZero = nmaxmerge;
3091 previousChunk = outputChunk;
3098 // Merging stage different than 0.
3099 // Move to the begining of the requested chunk.
3100 fm = new TFileMerger(isGrid);
3101 fm->SetFastMethod(kTRUE);
3102 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
3104 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
3105 // Nothing found - skip this output
3106 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
3110 fm->OutputFile(outputFile);
3111 // Merge the outputs
3113 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
3117 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
3123 //______________________________________________________________________________
3124 Bool_t AliAnalysisAlien::MergeOutputs()
3126 // Merge analysis outputs existing in the AliEn space.
3127 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
3128 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3130 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
3134 if (!TestBit(AliAnalysisGrid::kMerge)) {
3135 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
3138 if (fProductionMode) {
3139 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
3142 Info("MergeOutputs", "Submitting merging JDL");
3143 if (!SubmitMerging()) return kFALSE;
3144 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
3145 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
3148 // Get the output path
3149 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3150 if (!DirectoryExists(fGridOutputDir)) {
3151 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
3154 if (!fOutputFiles.Length()) {
3155 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3158 // Check if fast read option was requested
3159 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
3160 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
3161 if (fFastReadOption) {
3162 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
3163 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3164 gEnv->SetValue("XNet.ConnectTimeout",50);
3165 gEnv->SetValue("XNet.RequestTimeout",50);
3166 gEnv->SetValue("XNet.MaxRedirectCount",2);
3167 gEnv->SetValue("XNet.ReconnectTimeout",50);
3168 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
3170 // Make sure we change the temporary directory
3171 gSystem->Setenv("TMPDIR", gSystem->pwd());
3172 // Set temporary compilation directory to current one
3173 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
3174 TObjArray *list = fOutputFiles.Tokenize(",");
3178 Bool_t merged = kTRUE;
3179 while((str=(TObjString*)next())) {
3180 outputFile = str->GetString();
3181 Int_t index = outputFile.Index("@");
3182 if (index > 0) outputFile.Remove(index);
3183 TString outputChunk = outputFile;
3184 outputChunk.ReplaceAll(".root", "_*.root");
3185 // Skip already merged outputs
3186 if (!gSystem->AccessPathName(outputFile)) {
3187 if (fOverwriteMode) {
3188 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
3189 gSystem->Unlink(outputFile);
3190 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
3191 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
3192 outputChunk.Data());
3193 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
3196 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
3200 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
3201 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
3202 outputChunk.Data());
3203 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
3206 if (fMergeExcludes.Contains(outputFile.Data()) ||
3207 fRegisterExcludes.Contains(outputFile.Data())) continue;
3208 // Perform a 'find' command in the output directory, looking for registered outputs
3209 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
3211 Error("MergeOutputs", "Terminate() will NOT be executed");
3215 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
3216 if (fileOpened) fileOpened->Close();
3222 //______________________________________________________________________________
3223 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
3225 // Use the output files connected to output containers from the analysis manager
3226 // rather than the files defined by SetOutputFiles
3227 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
3228 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
3229 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
3232 //______________________________________________________________________________
3233 void AliAnalysisAlien::SetOutputFiles(const char *list)
3235 // Manually set the output files list.
3236 // Removes duplicates. Not allowed if default outputs are not disabled.
3237 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3238 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
3241 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
3243 TString slist = list;
3244 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
3245 TObjArray *arr = slist.Tokenize(" ");
3249 while ((os=(TObjString*)next())) {
3250 sout = os->GetString();
3251 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
3252 if (fOutputFiles.Contains(sout)) continue;
3253 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3254 fOutputFiles += sout;
3259 //______________________________________________________________________________
3260 void AliAnalysisAlien::SetOutputArchive(const char *list)
3262 // Manually set the output archive list. Free text - you are on your own...
3263 // Not allowed if default outputs are not disabled.
3264 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3265 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
3268 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
3269 fOutputArchive = list;
3272 //______________________________________________________________________________
3273 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
3275 // Set some PROOF special parameter.
3276 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
3278 TObject *old = pair->Key();
3279 TObject *val = pair->Value();
3280 fProofParam.Remove(old);
3284 fProofParam.Add(new TObjString(pname), new TObjString(value));
3287 //______________________________________________________________________________
3288 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
3290 // Returns a special PROOF parameter.
3291 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
3292 if (!pair) return 0;
3293 return pair->Value()->GetName();
3296 //______________________________________________________________________________
3297 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
3299 // Start remote grid analysis.
3300 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3301 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
3302 if (!mgr || !mgr->IsInitialized()) {
3303 Error("StartAnalysis", "You need an initialized analysis manager for this");
3306 // Are we in PROOF mode ?
3307 if (mgr->IsProofMode()) {
3308 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
3309 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3310 if (fProofCluster.IsNull()) {
3311 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3314 if (fProofDataSet.IsNull() && !testMode) {
3315 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3318 // Set the needed environment
3319 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3320 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3321 if (fProofReset && !testMode) {
3322 if (fProofReset==1) {
3323 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3324 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3326 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3327 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3329 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3334 // Check if there is an old active session
3335 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3337 Error("StartAnalysis","You have to reset your old session first\n");
3341 // Do we need to change the ROOT version ? The success of this cannot be checked.
3342 if (!fROOTVersion.IsNull() && !testMode) {
3343 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"VO_ALICE@ROOT::%s\");",
3344 fProofCluster.Data(), fROOTVersion.Data()));
3346 // Connect to PROOF and check the status
3349 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3350 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3352 if (!sworkers.IsNull())
3353 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3355 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3357 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3359 Error("StartAnalysis", "Could not start PROOF in test mode");
3364 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3367 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3368 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3369 // Set proof special parameters if any
3370 TIter nextpp(&fProofParam);
3371 TObject *proofparam;
3372 while ((proofparam=nextpp())) {
3373 TString svalue = GetProofParameter(proofparam->GetName());
3374 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3376 // Is dataset existing ?
3378 TString dataset = fProofDataSet;
3379 Int_t index = dataset.Index("#");
3380 if (index>=0) dataset.Remove(index);
3381 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3382 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3385 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3387 // Is ClearPackages() needed ?
3388 if (TestSpecialBit(kClearPackages)) {
3389 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3390 gROOT->ProcessLine("gProof->ClearPackages();");
3392 // Is a given aliroot mode requested ?
3395 if (!fAliRootMode.IsNull()) {
3396 TString alirootMode = fAliRootMode;
3397 if (alirootMode == "default") alirootMode = "";
3398 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3399 optionsList.SetOwner();
3400 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3401 // Check the additional libs to be loaded
3403 Bool_t parMode = kFALSE;
3404 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3405 // Parse the extra libs for .so or .dylib
3406 if (fAdditionalLibs.Length()) {
3407 TString additionalLibs = fAdditionalLibs;
3408 additionalLibs.Strip();
3409 if (additionalLibs.Length() && fFriendLibs.Length())
3410 additionalLibs += " ";
3411 additionalLibs += fFriendLibs;
3412 TObjArray *list = additionalLibs.Tokenize(" ");
3415 while((str=(TObjString*)next())) {
3416 if (str->GetString().Contains(".so") ||
3417 str->GetString().Contains(".dylib") ) {
3419 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());
3422 TString stmp = str->GetName();
3423 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3424 stmp.ReplaceAll(".so","");
3425 stmp.ReplaceAll(".dylib","");
3426 if (!extraLibs.IsNull()) extraLibs += ":";
3430 if (str->GetString().Contains(".par")) {
3431 // The first par file found in the list will not allow any further .so
3433 if (!parLibs.IsNull()) parLibs += ":";
3434 parLibs += str->GetName();
3438 if (list) delete list;
3440 if (!extraLibs.IsNull()) {
3441 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3442 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3444 // Check extra includes
3445 if (!fIncludePath.IsNull()) {
3446 TString includePath = fIncludePath;
3447 includePath.ReplaceAll(" ",":");
3448 includePath.ReplaceAll("$ALICE_ROOT/","");
3449 includePath.ReplaceAll("${ALICE_ROOT}/","");
3450 includePath.ReplaceAll("-I","");
3451 includePath.Remove(TString::kTrailing, ':');
3452 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3453 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3455 // Check if connection to grid is requested
3456 if (TestSpecialBit(kProofConnectGrid))
3457 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3458 // Enable AliRoot par
3460 // Enable proof lite package
3461 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3462 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3463 TNamed *obj = (TNamed*)optionsList.At(i);
3464 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3466 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3467 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3468 Info("StartAnalysis", "AliRootProofLite enabled");
3470 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3474 if ( ! fAliROOTVersion.IsNull() ) {
3475 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3476 fAliROOTVersion.Data(), &optionsList))) {
3477 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3482 // Enable first par files from fAdditionalLibs
3483 if (!parLibs.IsNull()) {
3484 TObjArray *list = parLibs.Tokenize(":");
3486 TObjString *package;
3487 while((package=(TObjString*)next())) {
3488 TString spkg = package->GetName();
3489 spkg.ReplaceAll(".par", "");
3490 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3491 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3492 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3493 if (gROOT->ProcessLine(enablePackage)) {
3494 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3498 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3502 if (list) delete list;
3505 if ((fAdditionalLibs.Contains(".so") || fAdditionalLibs.Contains(".dylib")) &&
3507 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3508 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3512 // Enable par files if requested
3513 if (fPackages && fPackages->GetEntries()) {
3514 TIter next(fPackages);
3516 while ((package=next())) {
3517 // Skip packages already enabled
3518 if (parLibs.Contains(package->GetName())) continue;
3519 TString spkg = package->GetName();
3520 spkg.ReplaceAll(".par", "");
3521 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3522 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3523 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3524 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3528 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3533 // Do we need to load analysis source files ?
3534 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3535 if (fAnalysisSource.Length()) {
3536 TObjArray *list = fAnalysisSource.Tokenize(" ");
3539 while((str=(TObjString*)next())) {
3540 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3542 if (list) delete list;
3545 // Register dataset to proof lite.
3546 if (fFileForTestMode.IsNull()) {
3547 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3550 if (gSystem->AccessPathName(fFileForTestMode)) {
3551 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3554 TFileCollection *coll = new TFileCollection();
3555 coll->AddFromFile(fFileForTestMode);
3556 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3557 gROOT->ProcessLine("gProof->ShowDataSets()");
3562 // Check if output files have to be taken from the analysis manager
3563 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3564 // Add output files and AOD files
3565 fOutputFiles = GetListOfFiles("outaod");
3566 // Add extra files registered to the analysis manager
3567 TString extra = GetListOfFiles("ext");
3568 if (!extra.IsNull()) {
3569 extra.ReplaceAll(".root", "*.root");
3570 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3571 fOutputFiles += extra;
3573 // Compose the output archive.
3574 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3575 if (mgr->IsCollectThroughput())
3576 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d %s@disk=%d",fOutputFiles.Data(),fNreplicas, mgr->GetFileInfoLog(),fNreplicas);
3578 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3580 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3581 if (TestBit(AliAnalysisGrid::kOffline)) {
3582 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3583 \n there nor any job run. You can revise the JDL and analysis \
3584 \n macro then run the same in \"submit\" mode.");
3585 } else if (TestBit(AliAnalysisGrid::kTest)) {
3586 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3588 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3589 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3590 \n space and job submitted.");
3591 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3592 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3593 if (fMergeViaJDL) CheckInputData();
3596 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3601 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3604 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3605 if (!CheckInputData()) {
3606 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3609 if (!CreateDataset(fDataPattern)) {
3611 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3612 if (fRunNumbers.Length()) serror = "run numbers";
3613 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3614 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3615 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3618 WriteAnalysisFile();
3619 WriteAnalysisMacro();
3621 WriteValidationScript();
3623 WriteMergingMacro();
3624 WriteMergeExecutable();
3625 WriteValidationScript(kTRUE);
3627 if (!CreateJDL()) return kFALSE;
3628 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3630 // Locally testing the analysis
3631 Info("StartAnalysis", "\n_______________________________________________________________________ \
3632 \n Running analysis script in a daughter shell as on a worker node \
3633 \n_______________________________________________________________________");
3634 TObjArray *list = fOutputFiles.Tokenize(",");
3638 while((str=(TObjString*)next())) {
3639 outputFile = str->GetString();
3640 Int_t index = outputFile.Index("@");
3641 if (index > 0) outputFile.Remove(index);
3642 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3645 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3646 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3647 // gSystem->Exec("cat stdout");
3650 // Check if submitting is managed by LPM manager
3651 if (fProductionMode) {
3652 //TString prodfile = fJDLName;
3653 //prodfile.ReplaceAll(".jdl", ".prod");
3654 //WriteProductionFile(prodfile);
3655 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3658 // Submit AliEn job(s)
3659 gGrid->Cd(fGridOutputDir);
3664 if (!fRunNumbers.Length() && !fRunRange[0]) {
3665 // Submit a given xml or a set of runs
3666 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3667 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3669 const char *cjobId = res->GetKey(0,"jobId");
3673 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3676 Info("StartAnalysis", "\n_______________________________________________________________________ \
3677 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3678 \n_______________________________________________________________________",
3679 fJDLName.Data(), cjobId);
3682 if (!fGridJobIDs.IsNull()) fGridJobIDs.Append(" ");
3683 fGridJobIDs.Append(jobID);
3684 if (!fGridStages.IsNull()) fGridStages.Append(" ");
3685 fGridStages.Append("full");
3690 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3694 // Submit for a range of enumeration of runs.
3695 if (!Submit()) return kFALSE;
3696 jobID = fGridJobIDs;
3700 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3701 \n You may exit at any time and terminate the job later using the option <terminate> \
3702 \n ##################################################################################", jobID.Data());
3703 gSystem->Exec("aliensh");
3705 Info("StartAnalysis", "\n#### SUBMITTED JOB %s TO ALIEN QUEUE #### \
3706 \n Remember to terminate the job later using the option <terminate> \
3707 \n ##################################################################################", jobID.Data());
3712 //______________________________________________________________________________
3713 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3715 // Get a comma-separated list of output files of the requested type.
3716 // Type can be (case unsensitive):
3717 // aod - list of aod files (std, extensions and filters)
3718 // out - list of output files connected to containers (but not aod's or extras)
3719 // ext - list of extra files registered to the manager
3720 // ter - list of files produced in terminate
3721 static TString files;
3723 TString stype = type;
3725 TString aodfiles, extra;
3726 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3728 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3729 return files.Data();
3731 if (mgr->GetOutputEventHandler()) {
3733 if (mgr->GetOutputEventHandler()->GetFillAOD())
3734 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3735 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs(kTRUE);
3736 if (!extraaod.IsNull() && mgr->GetOutputEventHandler()->GetFillExtension()) {
3737 if (!aodfiles.IsNull()) aodfiles += ",";
3738 aodfiles += extraaod;
3741 if (stype.Contains("aod")) {
3743 if (stype == "aod") return files.Data();
3745 // Add output files that are not in the list of AOD files
3746 TString outputfiles = "";
3747 TIter next(mgr->GetOutputs());
3748 AliAnalysisDataContainer *output;
3749 const char *filename = 0;
3750 while ((output=(AliAnalysisDataContainer*)next())) {
3751 filename = output->GetFileName();
3752 if (!(strcmp(filename, "default"))) continue;
3753 if (outputfiles.Contains(filename)) continue;
3754 if (aodfiles.Contains(filename)) continue;
3755 if (!outputfiles.IsNull() && strlen(filename)) outputfiles += ",";
3756 outputfiles += filename;
3758 if (stype.Contains("out")) {
3759 if (!files.IsNull() && !outputfiles.IsNull()) files += ",";
3760 files += outputfiles;
3761 if (stype == "out") return files.Data();
3763 // Add extra files registered to the analysis manager
3765 extra = mgr->GetExtraFiles();
3766 if (!extra.IsNull()) {
3768 extra.ReplaceAll(" ", ",");
3769 TObjArray *fextra = extra.Tokenize(",");
3770 TIter nextx(fextra);
3772 while ((obj=nextx())) {
3773 if (aodfiles.Contains(obj->GetName())) continue;
3774 if (outputfiles.Contains(obj->GetName())) continue;
3775 if (sextra.Contains(obj->GetName())) continue;
3776 if (!sextra.IsNull()) sextra += ",";
3777 sextra += obj->GetName();
3780 if (stype.Contains("ext")) {
3781 if (!files.IsNull() && !sextra.IsNull()) files += ",";
3785 if (stype == "ext") return files.Data();
3787 if (!fTerminateFiles.IsNull()) {
3788 fTerminateFiles.Strip();
3789 fTerminateFiles.ReplaceAll(" ",",");
3790 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3791 TIter nextx(fextra);
3793 while ((obj=nextx())) {
3794 if (aodfiles.Contains(obj->GetName())) continue;
3795 if (outputfiles.Contains(obj->GetName())) continue;
3796 if (termfiles.Contains(obj->GetName())) continue;
3797 if (sextra.Contains(obj->GetName())) continue;
3798 if (!termfiles.IsNull()) termfiles += ",";
3799 termfiles += obj->GetName();
3803 if (stype.Contains("ter")) {
3804 if (!files.IsNull() && !termfiles.IsNull()) {
3809 return files.Data();
3812 //______________________________________________________________________________
3813 Bool_t AliAnalysisAlien::Submit()
3815 // Submit all master jobs.
3816 Int_t nmasterjobs = fInputFiles->GetEntries();
3817 Long_t tshoot = gSystem->Now();
3818 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3819 while (fNsubmitted < nmasterjobs) {
3820 Long_t now = gSystem->Now();
3821 if ((now-tshoot)>30000) {
3823 if (!SubmitNext()) return kFALSE;
3829 //______________________________________________________________________________
3830 Bool_t AliAnalysisAlien::SubmitMerging()
3832 // Submit all merging jobs.
3833 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3834 gGrid->Cd(fGridOutputDir);
3835 TString mergeJDLName = fExecutable;
3836 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3838 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3841 Int_t ntosubmit = fInputFiles->GetEntries();
3842 for (Int_t i=0; i<ntosubmit; i++) {
3843 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3844 runOutDir.ReplaceAll(".xml", "");
3845 if (fOutputToRunNo) {
3846 // The output directory is the run number
3847 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3848 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3850 if (!fRunNumbers.Length() && !fRunRange[0]) {
3851 // The output directory is the grid outdir
3852 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3853 runOutDir = fGridOutputDir;
3855 // The output directory is the master number in 3 digits format
3856 printf("### Submitting merging job for master <%03d>\n", i);
3857 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3860 // Check now the number of merging stages.
3861 TObjArray *list = fOutputFiles.Tokenize(",");
3865 while((str=(TObjString*)next())) {
3866 outputFile = str->GetString();
3867 Int_t index = outputFile.Index("@");
3868 if (index > 0) outputFile.Remove(index);
3869 if (!fMergeExcludes.Contains(outputFile) &&
3870 !fRegisterExcludes.Contains(outputFile)) break;
3873 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3874 if (!done && (i==ntosubmit-1)) return kFALSE;
3875 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3877 if (!ntosubmit) return kTRUE;
3879 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3880 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3881 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3882 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3883 \n ################################################################################################################");
3884 gSystem->Exec("aliensh");
3886 Info("StartAnalysis", "\n #### STARTED MERGING JOBS FOR YOU #### \
3887 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL') \
3888 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3889 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3890 \n ################################################################################################################");
3895 //______________________________________________________________________________
3896 Bool_t AliAnalysisAlien::SubmitNext()
3898 // Submit next bunch of master jobs if the queue is free. The first master job is
3899 // submitted right away, while the next will not be unless the previous was split.
3900 // The plugin will not submit new master jobs if there are more that 500 jobs in
3902 static Bool_t iscalled = kFALSE;
3903 static Int_t firstmaster = 0;
3904 static Int_t lastmaster = 0;
3905 static Int_t npermaster = 0;
3906 if (iscalled) return kTRUE;
3908 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3909 Int_t ntosubmit = 0;
3912 Int_t nmasterjobs = fInputFiles->GetEntries();
3915 if (!IsUseSubmitPolicy()) {
3917 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3918 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3919 ntosubmit = nmasterjobs;
3922 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3923 printf("=== master %d: %s\n", lastmaster, status.Data());
3924 // If last master not split, just return
3925 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3926 // No more than 100 waiting jobs
3927 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3928 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3929 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3930 if (!ntosubmit) ntosubmit = 1;
3931 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3932 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3934 for (Int_t i=0; i<ntosubmit; i++) {
3935 // Submit for a range of enumeration of runs.
3936 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3938 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3939 runOutDir.ReplaceAll(".xml", "");
3941 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3943 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3944 printf("********* %s\n",query.Data());
3945 res = gGrid->Command(query);
3947 TString cjobId1 = res->GetKey(0,"jobId");
3948 if (!cjobId1.Length()) {
3952 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3955 Info("StartAnalysis", "\n_______________________________________________________________________ \
3956 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3957 \n_______________________________________________________________________",
3958 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3959 if (!fGridJobIDs.IsNull()) fGridJobIDs.Append(" ");
3960 fGridJobIDs.Append(cjobId1);
3961 if (!fGridStages.IsNull()) fGridStages.Append(" ");
3962 fGridStages.Append("full");
3965 lastmaster = cjobId1.Atoi();
3966 if (!firstmaster) firstmaster = lastmaster;
3971 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3979 //______________________________________________________________________________
3980 void AliAnalysisAlien::WriteAnalysisFile()
3982 // Write current analysis manager into the file <analysisFile>
3983 TString analysisFile = fExecutable;
3984 analysisFile.ReplaceAll(".sh", ".root");
3985 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3986 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3987 if (!mgr || !mgr->IsInitialized()) {
3988 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3991 // Check analysis type
3993 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3994 handler = (TObject*)mgr->GetInputEventHandler();
3996 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3997 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3998 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3999 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
4001 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
4002 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
4005 TDirectory *cdir = gDirectory;
4006 TFile *file = TFile::Open(analysisFile, "RECREATE");
4008 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
4009 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
4010 // Unless merging makes no sense
4011 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
4014 // Enable termination for local jobs
4015 mgr->SetSkipTerminate(kFALSE);
4017 if (cdir) cdir->cd();
4018 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
4020 Bool_t copy = kTRUE;
4021 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4024 TString workdir = gGrid->GetHomeDirectory();
4025 workdir += fGridWorkingDir;
4026 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
4027 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
4028 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
4029 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
4033 //______________________________________________________________________________
4034 void AliAnalysisAlien::WriteAnalysisMacro()
4036 // Write the analysis macro that will steer the analysis in grid mode.
4037 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4039 out.open(fAnalysisMacro.Data(), ios::out);
4041 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4044 Bool_t hasSTEERBase = kFALSE;
4045 Bool_t hasESD = kFALSE;
4046 Bool_t hasAOD = kFALSE;
4047 Bool_t hasANALYSIS = kFALSE;
4048 Bool_t hasOADB = kFALSE;
4049 Bool_t hasANALYSISalice = kFALSE;
4050 Bool_t hasCORRFW = kFALSE;
4051 TString func = fAnalysisMacro;
4052 TString type = "ESD";
4053 TString comment = "// Analysis using ";
4058 if (IsUseMCchain()) {
4062 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
4063 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
4069 if (type!="AOD" && fFriendChainName!="") {
4070 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
4073 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
4074 else comment += " data";
4075 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
4076 func.ReplaceAll(".C", "");
4077 out << "void " << func.Data() << "()" << endl;
4079 out << comment.Data() << endl;
4080 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
4081 out << " TStopwatch timer;" << endl;
4082 out << " timer.Start();" << endl << endl;
4083 // Change temp directory to current one
4084 if (!IsLocalTest()) {
4085 out << "// connect to AliEn and make the chain" << endl;
4086 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4088 out << "// Set temporary merging directory to current one" << endl;
4089 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4090 out << "// Set temporary compilation directory to current one" << endl;
4091 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4092 // Reset existing include path
4093 out << "// Reset existing include path and add current directory first in the search" << endl;
4094 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4095 if (!fExecutableCommand.Contains("aliroot")) {
4096 out << "// load base root libraries" << endl;
4097 out << " gSystem->Load(\"libTree\");" << endl;
4098 out << " gSystem->Load(\"libGeom\");" << endl;
4099 out << " gSystem->Load(\"libVMC\");" << endl;
4100 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4101 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4103 if (fAdditionalRootLibs.Length()) {
4104 // in principle libtree /lib geom libvmc etc. can go into this list, too
4105 out << "// Add aditional libraries" << endl;
4106 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4109 while((str=(TObjString*)next())) {
4110 if (str->GetString().Contains(".so") || str->GetString().Contains(".dylib"))
4111 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4113 if (list) delete list;
4115 out << "// Load analysis framework libraries" << endl;
4116 TString setupPar = "AliAnalysisAlien::SetupPar";
4118 if (!fExecutableCommand.Contains("aliroot")) {
4119 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4120 out << " gSystem->Load(\"libESD\");" << endl;
4121 out << " gSystem->Load(\"libAOD\");" << endl;
4123 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4124 out << " gSystem->Load(\"libOADB\");" << endl;
4125 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4126 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4128 TIter next(fPackages);
4131 while ((obj=next())) {
4132 pkgname = obj->GetName();
4133 if (pkgname == "STEERBase" ||
4134 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4135 if (pkgname == "ESD" ||
4136 pkgname == "ESD.par") hasESD = kTRUE;
4137 if (pkgname == "AOD" ||
4138 pkgname == "AOD.par") hasAOD = kTRUE;
4139 if (pkgname == "ANALYSIS" ||
4140 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4141 if (pkgname == "OADB" ||
4142 pkgname == "OADB.par") hasOADB = kTRUE;
4143 if (pkgname == "ANALYSISalice" ||
4144 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4145 if (pkgname == "CORRFW" ||
4146 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4148 if (hasANALYSISalice) setupPar = "SetupPar";
4149 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4150 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4151 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4152 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4153 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4154 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4155 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4156 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4157 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4158 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4159 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4160 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4161 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4162 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4163 out << "// Compile other par packages" << endl;
4165 while ((obj=next())) {
4166 pkgname = obj->GetName();
4167 if (pkgname == "STEERBase" ||
4168 pkgname == "STEERBase.par" ||
4170 pkgname == "ESD.par" ||
4172 pkgname == "AOD.par" ||
4173 pkgname == "ANALYSIS" ||
4174 pkgname == "ANALYSIS.par" ||
4175 pkgname == "OADB" ||
4176 pkgname == "OADB.par" ||
4177 pkgname == "ANALYSISalice" ||
4178 pkgname == "ANALYSISalice.par" ||
4179 pkgname == "CORRFW" ||
4180 pkgname == "CORRFW.par") continue;
4181 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4184 out << "// include path" << endl;
4185 // Get the include path from the interpreter and remove entries pointing to AliRoot
4186 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4187 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4188 out << " TIter nextpath(listpaths);" << endl;
4189 out << " TObjString *pname;" << endl;
4190 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4191 out << " TString current = pname->GetName();" << endl;
4192 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4193 out << " gSystem->AddIncludePath(current);" << endl;
4194 out << " }" << endl;
4195 out << " if (listpaths) delete listpaths;" << endl;
4196 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4197 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4198 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4199 if (fMCLoop && !fGeneratorLibs.IsNull()) {
4200 out << "// MC generator libraries" << endl;
4201 TObjArray *list = fGeneratorLibs.Tokenize(" ");
4204 while((str=(TObjString*)next())) {
4205 out << " gSystem->Load(\"" << str->GetName() << "\");" << endl;
4209 if (fAdditionalLibs.Length()) {
4210 out << "// Add aditional AliRoot libraries" << endl;
4211 TString additionalLibs = fAdditionalLibs;
4212 additionalLibs.Strip();
4213 if (additionalLibs.Length() && fFriendLibs.Length())
4214 additionalLibs += " ";
4215 additionalLibs += fFriendLibs;
4216 TObjArray *list = additionalLibs.Tokenize(" ");
4219 while((str=(TObjString*)next())) {
4220 if (str->GetString().Contains(".so") || str->GetString().Contains(".dylib"))
4221 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4222 if (str->GetString().Contains(".par"))
4223 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
4228 out << "// analysis source to be compiled at runtime (if any)" << endl;
4229 if (fAnalysisSource.Length()) {
4230 TObjArray *list = fAnalysisSource.Tokenize(" ");
4233 while((str=(TObjString*)next())) {
4234 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4236 if (list) delete list;
4239 // out << " printf(\"Currently load libraries:\\n\");" << endl;
4240 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
4241 if (fFastReadOption) {
4242 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 !!! \
4243 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
4244 out << "// fast xrootd reading enabled" << endl;
4245 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4246 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4247 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4248 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4249 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4250 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4252 out << "// read the analysis manager from file" << endl;
4253 TString analysisFile = fExecutable;
4254 analysisFile.ReplaceAll(".sh", ".root");
4255 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4256 << analysisFile << "\");" << endl;
4257 out << " if (!mgr) return;" << endl;
4258 if (IsLocalTest()) {
4259 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
4260 out << " plugin->SetRunMode(\"test\");" << endl;
4261 if (fFileForTestMode.IsNull())
4262 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
4264 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
4265 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
4266 if (!fFriendChainName.IsNull())
4267 out << " plugin->SetFriendChainName(\"" << fFriendChainName << "\",\"" << fFriendLibs << "\");" << endl;
4269 out << " plugin->SetUseMCchain();" << endl;
4271 out << " plugin->SetMCLoop(kTRUE);" << endl;
4272 out << " mgr->SetGridHandler(plugin);" << endl;
4273 if (AliAnalysisManager::GetAnalysisManager()) {
4274 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
4275 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
4277 out << " mgr->SetDebugLevel(10);" << endl;
4278 out << " mgr->SetNSysInfo(100);" << endl;
4281 out << " mgr->PrintStatus();" << endl;
4282 if (AliAnalysisManager::GetAnalysisManager()) {
4283 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4284 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4286 if (TestBit(AliAnalysisGrid::kTest))
4287 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4289 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4292 if (!IsLocalTest()) {
4294 out << " mgr->SetCacheSize(0);" << endl;
4295 out << " mgr->EventLoop(" << fNMCevents << ");" << endl;
4297 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
4298 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
4302 out << " mgr->SetCacheSize(0);" << endl;
4303 out << " mgr->EventLoop(" << fNMCevents << ");" << endl;
4305 out << " mgr->StartAnalysis(\"localfile\");" << endl;
4308 out << " timer.Stop();" << endl;
4309 out << " timer.Print();" << endl;
4310 out << "}" << endl << endl;
4311 if (!IsLocalTest() && !fMCLoop) {
4312 out <<"//________________________________________________________________________________" << endl;
4313 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
4315 out << "// Create a chain using url's from xml file" << endl;
4316 out << " TString filename;" << endl;
4317 out << " Int_t run = 0;" << endl;
4318 if (IsUseMCchain()) {
4319 out << " TString treename = \"TE\";" << endl;
4321 if (!fTreeName.IsNull()) {
4322 out << " TString treename = \"" << fTreeName << "\";" << endl;
4324 out << " TString treename = type;" << endl;
4325 out << " treename.ToLower();" << endl;
4326 out << " treename += \"Tree\";" << endl;
4329 out << " printf(\"***************************************\\n\");" << endl;
4330 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
4331 out << " printf(\"***************************************\\n\");" << endl;
4332 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
4333 out << " if (!coll) {" << endl;
4334 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
4335 out << " return NULL;" << endl;
4336 out << " }" << endl;
4337 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
4338 out << " TChain *chain = new TChain(treename);" << endl;
4339 if(!fFriendChainName.IsNull()) {
4340 out << " TList *friends = new TList();" << endl;
4341 out << " TIter nextfriend(friends);" << endl;
4342 out << " TChain *cfriend = 0;" << endl;
4343 TObjArray *list = fFriendChainName.Tokenize(" ");
4346 while((str=(TObjString*)next())) {
4347 out << " cfriend = new TChain(treename, \"" << str->GetName() << "\");" << endl;
4348 out << " friends->Add(cfriend);" << endl;
4349 out << " chain->AddFriend(cfriend);" << endl;
4352 // out << " TChain *chainFriend = new TChain(treename);" << endl;
4354 out << " coll->Reset();" << endl;
4355 out << " while (coll->Next()) {" << endl;
4356 out << " filename = coll->GetTURL("");" << endl;
4357 out << " if (mgr) {" << endl;
4358 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
4359 out << " if (nrun && nrun != run) {" << endl;
4360 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
4361 out << " mgr->SetRunFromPath(nrun);" << endl;
4362 out << " run = nrun;" << endl;
4363 out << " }" << endl;
4364 out << " }" << endl;
4365 out << " chain->Add(filename);" << endl;
4366 if(!fFriendChainName.IsNull()) {
4367 out << " TString bpath=coll->GetTURL(\"\");" << endl;
4368 out << " if (bpath.Index(\"#\") > -1) bpath.Remove(bpath.Index(\"#\"));" << endl;
4369 out << " bpath = gSystem->DirName(bpath);" << endl;
4370 out << " bpath += \"/\";" << endl;
4371 out << " TString fileFriend;" << endl;
4372 out << " nextfriend.Reset();" << endl;
4373 out << " while ((cfriend=(TChain*)nextfriend())) {" << endl;
4374 out << " fileFriend = bpath;" << endl;
4375 out << " fileFriend += cfriend->GetTitle();" << endl;
4376 out << " TFile *file = TFile::Open(fileFriend);" << endl;
4377 out << " if (file) {" << endl;
4378 out << " file->Close();" << endl;
4379 out << " cfriend->Add(fileFriend.Data());" << endl;
4380 out << " } else {" << endl;
4381 out << " ::Fatal(\"CreateChain\", \"Cannot open friend file: %s\", fileFriend.Data());" << endl;
4382 out << " return 0;" << endl;
4383 out << " }" << endl;
4384 out << " }" << endl;
4386 out << " }" << endl;
4387 out << " if (!chain->GetNtrees()) {" << endl;
4388 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
4389 out << " return NULL;" << endl;
4390 out << " }" << endl;
4391 out << " return chain;" << endl;
4392 out << "}" << endl << endl;
4394 if (hasANALYSISalice) {
4395 out <<"//________________________________________________________________________________" << endl;
4396 out << "Bool_t SetupPar(const char *package) {" << endl;
4397 out << "// Compile the package and set it up." << endl;
4398 out << " TString pkgdir = package;" << endl;
4399 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4400 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4401 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4402 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4403 out << " // Check for BUILD.sh and execute" << endl;
4404 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4405 out << " printf(\"*******************************\\n\");" << endl;
4406 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4407 out << " printf(\"*******************************\\n\");" << endl;
4408 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4409 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4410 out << " gSystem->ChangeDirectory(cdir);" << endl;
4411 out << " return kFALSE;" << endl;
4412 out << " }" << endl;
4413 out << " } else {" << endl;
4414 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4415 out << " gSystem->ChangeDirectory(cdir);" << endl;
4416 out << " return kFALSE;" << endl;
4417 out << " }" << endl;
4418 out << " // Check for SETUP.C and execute" << endl;
4419 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4420 out << " printf(\"*******************************\\n\");" << endl;
4421 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4422 out << " printf(\"*******************************\\n\");" << endl;
4423 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4424 out << " } else {" << endl;
4425 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4426 out << " gSystem->ChangeDirectory(cdir);" << endl;
4427 out << " return kFALSE;" << endl;
4428 out << " }" << endl;
4429 out << " // Restore original workdir" << endl;
4430 out << " gSystem->ChangeDirectory(cdir);" << endl;
4431 out << " return kTRUE;" << endl;
4434 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4436 Bool_t copy = kTRUE;
4437 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4440 TString workdir = gGrid->GetHomeDirectory();
4441 workdir += fGridWorkingDir;
4442 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4443 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4444 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4445 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4446 Form("alien://%s/%s", workdir.Data(),
4447 fAnalysisMacro.Data()))) Fatal("","Terminating");
4451 //______________________________________________________________________________
4452 void AliAnalysisAlien::WriteMergingMacro()
4454 // Write a macro to merge the outputs per master job.
4455 if (!fMergeViaJDL) return;
4456 if (!fOutputFiles.Length()) {
4457 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4460 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
4461 TString mergingMacro = fExecutable;
4462 mergingMacro.ReplaceAll(".sh","_merge.C");
4463 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4464 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4466 out.open(mergingMacro.Data(), ios::out);
4468 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4471 Bool_t hasSTEERBase = kFALSE;
4472 Bool_t hasESD = kFALSE;
4473 Bool_t hasAOD = kFALSE;
4474 Bool_t hasANALYSIS = kFALSE;
4475 Bool_t hasOADB = kFALSE;
4476 Bool_t hasANALYSISalice = kFALSE;
4477 Bool_t hasCORRFW = kFALSE;
4478 TString func = mergingMacro;
4480 func.ReplaceAll(".C", "");
4481 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4483 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4484 out << " TStopwatch timer;" << endl;
4485 out << " timer.Start();" << endl << endl;
4486 // Reset existing include path
4487 out << "// Reset existing include path and add current directory first in the search" << endl;
4488 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4489 if (!fExecutableCommand.Contains("aliroot")) {
4490 out << "// load base root libraries" << endl;
4491 out << " gSystem->Load(\"libTree\");" << endl;
4492 out << " gSystem->Load(\"libGeom\");" << endl;
4493 out << " gSystem->Load(\"libVMC\");" << endl;
4494 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4495 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4497 if (fAdditionalRootLibs.Length()) {
4498 // in principle libtree /lib geom libvmc etc. can go into this list, too
4499 out << "// Add aditional libraries" << endl;
4500 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4503 while((str=(TObjString*)next())) {
4504 if (str->GetString().Contains(".so") || str->GetString().Contains(".dylib"))
4505 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4507 if (list) delete list;
4509 out << "// Load analysis framework libraries" << endl;
4511 if (!fExecutableCommand.Contains("aliroot")) {
4512 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4513 out << " gSystem->Load(\"libESD\");" << endl;
4514 out << " gSystem->Load(\"libAOD\");" << endl;
4516 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4517 out << " gSystem->Load(\"libOADB\");" << endl;
4518 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4519 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4521 TIter next(fPackages);
4524 TString setupPar = "AliAnalysisAlien::SetupPar";
4525 while ((obj=next())) {
4526 pkgname = obj->GetName();
4527 if (pkgname == "STEERBase" ||
4528 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4529 if (pkgname == "ESD" ||
4530 pkgname == "ESD.par") hasESD = kTRUE;
4531 if (pkgname == "AOD" ||
4532 pkgname == "AOD.par") hasAOD = kTRUE;
4533 if (pkgname == "ANALYSIS" ||
4534 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4535 if (pkgname == "OADB" ||
4536 pkgname == "OADB.par") hasOADB = kTRUE;
4537 if (pkgname == "ANALYSISalice" ||
4538 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4539 if (pkgname == "CORRFW" ||
4540 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4542 if (hasANALYSISalice) setupPar = "SetupPar";
4543 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4544 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4545 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4546 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4547 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4548 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4549 out << " gSystem->Load(\"libOADB\");" << endl;
4550 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4551 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4552 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4553 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4554 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4555 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4556 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4557 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4558 out << "// Compile other par packages" << endl;
4560 while ((obj=next())) {
4561 pkgname = obj->GetName();
4562 if (pkgname == "STEERBase" ||
4563 pkgname == "STEERBase.par" ||
4565 pkgname == "ESD.par" ||
4567 pkgname == "AOD.par" ||
4568 pkgname == "ANALYSIS" ||
4569 pkgname == "ANALYSIS.par" ||
4570 pkgname == "OADB" ||
4571 pkgname == "OADB.par" ||
4572 pkgname == "ANALYSISalice" ||
4573 pkgname == "ANALYSISalice.par" ||
4574 pkgname == "CORRFW" ||
4575 pkgname == "CORRFW.par") continue;
4576 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4579 out << "// include path" << endl;
4580 // Get the include path from the interpreter and remove entries pointing to AliRoot
4581 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4582 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4583 out << " TIter nextpath(listpaths);" << endl;
4584 out << " TObjString *pname;" << endl;
4585 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4586 out << " TString current = pname->GetName();" << endl;
4587 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4588 out << " gSystem->AddIncludePath(current);" << endl;
4589 out << " }" << endl;
4590 out << " if (listpaths) delete listpaths;" << endl;
4591 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4592 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4593 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4594 if (fMCLoop && !fGeneratorLibs.IsNull()) {
4595 out << "// MC generator libraries" << endl;
4596 TObjArray *list = fGeneratorLibs.Tokenize(" ");
4599 while((str=(TObjString*)next())) {
4600 out << " gSystem->Load(\"" << str->GetName() << "\");" << endl;
4604 if (fAdditionalLibs.Length()) {
4605 out << "// Add aditional AliRoot libraries" << endl;
4606 TString additionalLibs = fAdditionalLibs;
4607 additionalLibs.Strip();
4608 if (additionalLibs.Length() && fFriendLibs.Length())
4609 additionalLibs += " ";
4610 additionalLibs += fFriendLibs;
4611 TObjArray *list = additionalLibs.Tokenize(" ");
4614 while((str=(TObjString*)next())) {
4615 if (str->GetString().Contains(".so") || str->GetString().Contains(".dylib"))
4616 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4618 if (list) delete list;
4621 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4622 if (fAnalysisSource.Length()) {
4623 TObjArray *list = fAnalysisSource.Tokenize(" ");
4626 while((str=(TObjString*)next())) {
4627 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4629 if (list) delete list;
4633 if (fFastReadOption) {
4634 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 !!!");
4635 out << "// fast xrootd reading enabled" << endl;
4636 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4637 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4638 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4639 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4640 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4641 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4643 // Change temp directory to current one
4644 out << "// Connect to AliEn" << endl;
4645 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4646 out << "// Set temporary merging directory to current one" << endl;
4647 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4648 out << "// Set temporary compilation directory to current one" << endl;
4649 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4650 out << " TString outputDir = dir;" << endl;
4652 out << " TString outputFiles = \"" << GetListOfFiles("outaod") << "\";" << endl;
4654 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4655 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4656 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4657 out << " TIter *iter = new TIter(list);" << endl;
4658 out << " TObjString *str;" << endl;
4659 out << " TString outputFile;" << endl;
4660 out << " Bool_t merged = kTRUE;" << endl;
4661 TString analysisFile = fExecutable;
4662 analysisFile.ReplaceAll(".sh", ".root");
4663 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4664 << analysisFile << "\");" << endl;
4665 out << " if (!mgr) {" << endl;
4666 out << " printf(\"ERROR: Analysis manager could not be extracted from file \");" << endl;
4667 out << " return;" << endl;
4668 out << " }" << endl;
4669 if (IsLocalTest()) {
4670 out << " printf(\"===================================\\n\");" << endl;
4671 out << " printf(\"Testing merging...\\n\");" << endl;
4672 out << " printf(\"===================================\\n\");" << endl;
4674 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4675 out << " outputFile = str->GetString();" << endl;
4676 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4677 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4678 out << " if (index > 0) outputFile.Remove(index);" << endl;
4679 out << " // Skip already merged outputs" << endl;
4680 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4681 out << " printf(\"Output file <%s> found. Not merging again.\\n\",outputFile.Data());" << endl;
4682 out << " continue;" << endl;
4683 out << " }" << endl;
4684 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4685 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4686 out << " if (!merged) {" << endl;
4687 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4688 out << " return;" << endl;
4689 out << " }" << endl;
4690 out << " }" << endl;
4691 if (mgr && mgr->IsCollectThroughput() && !IsLocalTest()) {
4692 out << " TString infolog = \"" << mgr->GetFileInfoLog() << "\";" << endl;
4693 out << " AliAnalysisAlien::MergeInfo(infolog, outputDir);" << endl;
4695 out << " // all outputs merged, validate" << endl;
4696 out << " ofstream out;" << endl;
4697 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4698 out << " out.close();" << endl;
4699 out << " // read the analysis manager from file" << endl;
4700 if (IsLocalTest()) {
4701 out << " printf(\"===================================\\n\");" << endl;
4702 out << " printf(\"Testing Terminate()...\\n\");" << endl;
4703 out << " printf(\"===================================\\n\");" << endl;
4705 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4707 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4708 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4709 out << " mgr->PrintStatus();" << endl;
4711 if (mgr->GetDebugLevel()>3) {
4712 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4714 if (TestBit(AliAnalysisGrid::kTest))
4715 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4717 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4720 out << " TTree *tree = NULL;" << endl;
4721 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4722 out << "}" << endl << endl;
4723 if (hasANALYSISalice) {
4724 out <<"//________________________________________________________________________________" << endl;
4725 out << "Bool_t SetupPar(const char *package) {" << endl;
4726 out << "// Compile the package and set it up." << endl;
4727 out << " TString pkgdir = package;" << endl;
4728 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4729 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4730 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4731 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4732 out << " // Check for BUILD.sh and execute" << endl;
4733 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4734 out << " printf(\"*******************************\\n\");" << endl;
4735 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4736 out << " printf(\"*******************************\\n\");" << endl;
4737 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4738 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4739 out << " gSystem->ChangeDirectory(cdir);" << endl;
4740 out << " return kFALSE;" << endl;
4741 out << " }" << endl;
4742 out << " } else {" << endl;
4743 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4744 out << " gSystem->ChangeDirectory(cdir);" << endl;
4745 out << " return kFALSE;" << endl;
4746 out << " }" << endl;
4747 out << " // Check for SETUP.C and execute" << endl;
4748 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4749 out << " printf(\"*******************************\\n\");" << endl;
4750 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4751 out << " printf(\"*******************************\\n\");" << endl;
4752 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4753 out << " } else {" << endl;
4754 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4755 out << " gSystem->ChangeDirectory(cdir);" << endl;
4756 out << " return kFALSE;" << endl;
4757 out << " }" << endl;
4758 out << " // Restore original workdir" << endl;
4759 out << " gSystem->ChangeDirectory(cdir);" << endl;
4760 out << " return kTRUE;" << endl;
4764 Bool_t copy = kTRUE;
4765 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4768 TString workdir = gGrid->GetHomeDirectory();
4769 workdir += fGridWorkingDir;
4770 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4771 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4772 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4773 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4774 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4778 //______________________________________________________________________________
4779 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4781 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4782 // Note that for loading the compiled library. The current directory should have precedence in
4784 TString pkgdir = package;
4785 pkgdir.ReplaceAll(".par","");
4786 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4787 TString cdir = gSystem->WorkingDirectory();
4788 gSystem->ChangeDirectory(pkgdir);
4789 // Check for BUILD.sh and execute
4790 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4791 printf("**************************************************\n");
4792 printf("*** Building PAR archive %s\n", package);
4793 printf("**************************************************\n");
4794 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4795 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4796 gSystem->ChangeDirectory(cdir);
4800 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4801 gSystem->ChangeDirectory(cdir);
4804 // Check for SETUP.C and execute
4805 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4806 printf("**************************************************\n");
4807 printf("*** Setup PAR archive %s\n", package);
4808 printf("**************************************************\n");
4809 gROOT->Macro("PROOF-INF/SETUP.C");
4810 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4812 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4813 gSystem->ChangeDirectory(cdir);
4816 // Restore original workdir
4817 gSystem->ChangeDirectory(cdir);
4821 //______________________________________________________________________________
4822 void AliAnalysisAlien::WriteExecutable()
4824 // Generate the alien executable script.
4825 // Patch executable with -x to catch error code
4826 if (fExecutableCommand.Contains("root") &&
4827 fExecutableCommand.Contains("-q") &&
4828 !fExecutableCommand.Contains("-x")) fExecutableCommand += " -x";
4829 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4831 out.open(fExecutable.Data(), ios::out);
4833 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4836 out << "#!/bin/bash" << endl;
4837 // Make sure we can properly compile par files
4838 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4839 out << "echo \"=========================================\"" << endl;
4840 out << "echo \"############## PATH : ##############\"" << endl;
4841 out << "echo $PATH" << endl;
4842 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4843 out << "echo $LD_LIBRARY_PATH" << endl;
4844 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4845 out << "echo $ROOTSYS" << endl;
4846 out << "echo \"############## which root : ##############\"" << endl;
4847 out << "which root" << endl;
4848 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4849 out << "echo $ALICE_ROOT" << endl;
4850 out << "echo \"############## which aliroot : ##############\"" << endl;
4851 out << "which aliroot" << endl;
4852 out << "echo \"############## system limits : ##############\"" << endl;
4853 out << "ulimit -a" << endl;
4854 out << "echo \"############## memory : ##############\"" << endl;
4855 out << "free -m" << endl;
4856 out << "echo \"=========================================\"" << endl << endl;
4857 out << fExecutableCommand << " ";
4858 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4859 out << "RET=$?" << endl;
4860 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4861 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4862 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4863 out << " let sig=\"$RET - 128\""<<endl;
4864 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4865 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4866 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4867 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4868 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4869 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4871 out << " exit $RET"<< endl;
4872 out << "fi" << endl << endl ;
4873 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4874 out << "echo \"############## memory after: ##############\"" << endl;
4875 out << "free -m" << endl;
4877 Bool_t copy = kTRUE;
4878 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4881 TString workdir = gGrid->GetHomeDirectory();
4882 workdir += fGridWorkingDir;
4883 TString executable = TString::Format("%s/%s", workdir.Data(), fExecutable.Data());
4884 if (FileExists(executable)) gGrid->Rm(executable);
4885 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4886 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4887 executable.Data())) Fatal("","Terminating");
4891 //______________________________________________________________________________
4892 void AliAnalysisAlien::WriteMergeExecutable()
4894 // Generate the alien executable script for the merging job.
4895 if (!fMergeViaJDL) return;
4896 TString mergeExec = fExecutable;
4897 mergeExec.ReplaceAll(".sh", "_merge.sh");
4898 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4900 out.open(mergeExec.Data(), ios::out);
4902 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4905 out << "#!/bin/bash" << endl;
4906 // Make sure we can properly compile par files
4907 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4908 out << "echo \"=========================================\"" << endl;
4909 out << "echo \"############## PATH : ##############\"" << endl;
4910 out << "echo $PATH" << endl;
4911 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4912 out << "echo $LD_LIBRARY_PATH" << endl;
4913 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4914 out << "echo $ROOTSYS" << endl;
4915 out << "echo \"############## which root : ##############\"" << endl;
4916 out << "which root" << endl;
4917 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4918 out << "echo $ALICE_ROOT" << endl;
4919 out << "echo \"############## which aliroot : ##############\"" << endl;
4920 out << "which aliroot" << endl;
4921 out << "echo \"############## system limits : ##############\"" << endl;
4922 out << "ulimit -a" << endl;
4923 out << "echo \"############## memory : ##############\"" << endl;
4924 out << "free -m" << endl;
4925 out << "echo \"=========================================\"" << endl << endl;
4926 TString mergeMacro = fExecutable;
4927 mergeMacro.ReplaceAll(".sh", "_merge.C");
4928 if (IsOneStageMerging())
4929 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4931 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4932 out << fExecutableCommand << " " << "$ARG" << endl;
4933 out << "RET=$?" << endl;
4934 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4935 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4936 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4937 out << " let sig=\"$RET - 128\""<<endl;
4938 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4939 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4940 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4941 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4942 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4943 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4945 out << " exit $RET"<< endl;
4946 out << "fi" << endl << endl ;
4947 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4948 out << "echo \"############## memory after: ##############\"" << endl;
4949 out << "free -m" << endl;
4951 Bool_t copy = kTRUE;
4952 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4955 TString workdir = gGrid->GetHomeDirectory();
4956 workdir += fGridWorkingDir;
4957 TString executable = TString::Format("%s/%s", workdir.Data(), mergeExec.Data());
4958 if (FileExists(executable)) gGrid->Rm(executable);
4959 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4960 if (!copyLocal2Alien("WriteMergeExecutable",mergeExec.Data(),
4961 executable.Data())) Fatal("","Terminating");
4965 //______________________________________________________________________________
4966 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4968 // Write the production file to be submitted by LPM manager. The format is:
4969 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4970 // Next lines: full_path_to_dataset XXX (XXX is a string)
4971 // To submit, one has to: submit jdl XXX for all lines
4973 out.open(filename, ios::out);
4975 Error("WriteProductionFile", "Bad file name: %s", filename);
4979 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4980 workdir = gGrid->GetHomeDirectory();
4981 workdir += fGridWorkingDir;
4982 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4983 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4984 out << locjdl << " " << njobspermaster << endl;
4985 Int_t nmasterjobs = fInputFiles->GetEntries();
4986 for (Int_t i=0; i<nmasterjobs; i++) {
4987 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4988 runOutDir.ReplaceAll(".xml", "");
4990 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4992 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4995 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4996 if (FileExists(filename)) gGrid->Rm(filename);
4997 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4998 if (!copyLocal2Alien("WriteProductionFile", filename,
4999 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
5003 //______________________________________________________________________________
5004 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
5006 // Generate the alien validation script.
5007 // Generate the validation script
5009 if (fValidationScript.IsNull()) {
5010 fValidationScript = fExecutable;
5011 fValidationScript.ReplaceAll(".sh", "_validation.sh");
5013 TString validationScript = fValidationScript;
5014 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
5016 Error("WriteValidationScript", "Alien connection required");
5019 if (!fTerminateFiles.IsNull()) {
5020 fTerminateFiles.Strip();
5021 fTerminateFiles.ReplaceAll(" ",",");
5023 TString outStream = "";
5024 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
5025 if (!TestBit(AliAnalysisGrid::kSubmit)) {
5027 out.open(validationScript, ios::out);
5028 out << "#!/bin/bash" << endl;
5029 out << "##################################################" << endl;
5030 out << "validateout=`dirname $0`" << endl;
5031 out << "validatetime=`date`" << endl;
5032 out << "validated=\"0\";" << endl;
5033 out << "error=0" << endl;
5034 out << "if [ -z $validateout ]" << endl;
5035 out << "then" << endl;
5036 out << " validateout=\".\"" << endl;
5037 out << "fi" << endl << endl;
5038 out << "cd $validateout;" << endl;
5039 out << "validateworkdir=`pwd`;" << endl << endl;
5040 out << "echo \"*******************************************************\"" << outStream << endl;
5041 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
5043 out << "echo \"* Time: $validatetime \"" << outStream << endl;
5044 out << "echo \"* Dir: $validateout\"" << outStream << endl;
5045 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
5046 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
5047 out << "ls -la ./" << outStream << endl;
5048 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
5049 out << "##################################################" << endl;
5052 out << "if [ ! -f stderr ] ; then" << endl;
5053 out << " error=1" << endl;
5054 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
5055 out << " echo \"Error = $error\" " << outStream << endl;
5056 out << "fi" << endl;
5058 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
5059 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
5060 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
5061 out << "glibcErr=`grep -Ei '\\*\\*\\* glibc detected \\*\\*\\*' stderr`" << endl;
5064 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
5065 out << " error=1" << endl;
5066 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
5067 out << " echo \"$parArch\" " << outStream << endl;
5068 out << " echo \"Error = $error\" " << outStream << endl;
5069 out << "fi" << endl;
5071 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
5072 out << " error=1" << endl;
5073 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
5074 out << " echo \"$segViol\" " << outStream << endl;
5075 out << " echo \"Error = $error\" " << outStream << endl;
5076 out << "fi" << endl;
5078 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
5079 out << " error=1" << endl;
5080 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
5081 out << " echo \"$segFault\" " << outStream << endl;
5082 out << " echo \"Error = $error\" " << outStream << endl;
5083 out << "fi" << endl;
5085 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
5086 out << " error=1" << endl;
5087 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
5088 out << " echo \"$glibcErr\" " << outStream << endl;
5089 out << " echo \"Error = $error\" " << outStream << endl;
5090 out << "fi" << endl;
5092 // Part dedicated to the specific analyses running into the train
5094 TString outputFiles = fOutputFiles;
5095 if (merge && !fTerminateFiles.IsNull()) {
5096 if (!outputFiles.IsNull()) outputFiles += ",";
5097 outputFiles += fTerminateFiles;
5099 TObjArray *arr = outputFiles.Tokenize(",");
5102 while (!merge && (os=(TObjString*)next1())) {
5103 // No need to validate outputs produced by merging since the merging macro does this
5104 outputFile = os->GetString();
5105 Int_t index = outputFile.Index("@");
5106 if (index > 0) outputFile.Remove(index);
5107 if (fTerminateFiles.Contains(outputFile)) continue;
5108 if (outputFile.Contains("*")) continue;
5109 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
5110 out << " error=1" << endl;
5111 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
5112 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
5113 out << "fi" << endl;
5116 out << "if ! [ -f outputs_valid ] ; then" << endl;
5117 out << " error=1" << endl;
5118 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
5119 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
5120 out << "fi" << endl;
5122 out << "if [ $error = 0 ] ; then" << endl;
5123 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
5124 if (!IsKeepLogs()) {
5125 out << " echo \"* === Logs std* will be deleted === \"" << endl;
5127 out << " rm -f std*" << endl;
5129 out << "fi" << endl;
5131 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
5132 out << "echo \"*******************************************************\"" << outStream << endl;
5133 out << "cd -" << endl;
5134 out << "exit $error" << endl;
5136 Bool_t copy = kTRUE;
5137 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
5140 TString workdir = gGrid->GetHomeDirectory();
5141 workdir += fGridWorkingDir;
5142 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
5143 if (FileExists(validationScript)) gGrid->Rm(validationScript);
5144 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
5145 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
5146 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");