1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "AliAnalysisAlien.h"
25 #include "Riostream.h"
33 #include "TFileCollection.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
39 #include "TGridResult.h"
40 #include "TGridCollection.h"
42 #include "TGridJobStatusList.h"
43 #include "TGridJobStatus.h"
44 #include "TFileMerger.h"
45 #include "AliAnalysisManager.h"
46 #include "AliAnalysisTaskCfg.h"
47 #include "AliVEventHandler.h"
48 #include "AliAnalysisDataContainer.h"
49 #include "AliMultiInputEventHandler.h"
55 ClassImp(AliAnalysisAlien)
61 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
63 TString sl(Form("file:%s", loc));
64 TString sr(Form("alien://%s", rem));
65 Bool_t ret = TFile::Cp(sl, sr);
67 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
73 //______________________________________________________________________________
74 AliAnalysisAlien::AliAnalysisAlien()
80 fSplitMaxInputFileNumber(0),
82 fMasterResubmitThreshold(0),
95 fNproofWorkersPerSlave(0),
105 fAdditionalRootLibs(),
151 //______________________________________________________________________________
152 AliAnalysisAlien::AliAnalysisAlien(const char *name)
153 :AliAnalysisGrid(name),
158 fSplitMaxInputFileNumber(0),
160 fMasterResubmitThreshold(0),
173 fNproofWorkersPerSlave(0),
177 fExecutableCommand(),
183 fAdditionalRootLibs(),
229 //______________________________________________________________________________
230 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
231 :AliAnalysisGrid(other),
234 fPrice(other.fPrice),
236 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
237 fMaxInitFailed(other.fMaxInitFailed),
238 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
239 fNtestFiles(other.fNtestFiles),
240 fNrunsPerMaster(other.fNrunsPerMaster),
241 fMaxMergeFiles(other.fMaxMergeFiles),
242 fMaxMergeStages(other.fMaxMergeStages),
243 fNsubmitted(other.fNsubmitted),
244 fProductionMode(other.fProductionMode),
245 fOutputToRunNo(other.fOutputToRunNo),
246 fMergeViaJDL(other.fMergeViaJDL),
247 fFastReadOption(other.fFastReadOption),
248 fOverwriteMode(other.fOverwriteMode),
249 fNreplicas(other.fNreplicas),
250 fNproofWorkers(other.fNproofWorkers),
251 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
252 fProofReset(other.fProofReset),
253 fRunNumbers(other.fRunNumbers),
254 fExecutable(other.fExecutable),
255 fExecutableCommand(other.fExecutableCommand),
256 fArguments(other.fArguments),
257 fExecutableArgs(other.fExecutableArgs),
258 fAnalysisMacro(other.fAnalysisMacro),
259 fAnalysisSource(other.fAnalysisSource),
260 fValidationScript(other.fValidationScript),
261 fAdditionalRootLibs(other.fAdditionalRootLibs),
262 fAdditionalLibs(other.fAdditionalLibs),
263 fSplitMode(other.fSplitMode),
264 fAPIVersion(other.fAPIVersion),
265 fROOTVersion(other.fROOTVersion),
266 fAliROOTVersion(other.fAliROOTVersion),
267 fExternalPackages(other.fExternalPackages),
269 fGridWorkingDir(other.fGridWorkingDir),
270 fGridDataDir(other.fGridDataDir),
271 fDataPattern(other.fDataPattern),
272 fGridOutputDir(other.fGridOutputDir),
273 fOutputArchive(other.fOutputArchive),
274 fOutputFiles(other.fOutputFiles),
275 fInputFormat(other.fInputFormat),
276 fDatasetName(other.fDatasetName),
277 fJDLName(other.fJDLName),
278 fTerminateFiles(other.fTerminateFiles),
279 fMergeExcludes(other.fMergeExcludes),
280 fRegisterExcludes(other.fRegisterExcludes),
281 fIncludePath(other.fIncludePath),
282 fCloseSE(other.fCloseSE),
283 fFriendChainName(other.fFriendChainName),
284 fJobTag(other.fJobTag),
285 fOutputSingle(other.fOutputSingle),
286 fRunPrefix(other.fRunPrefix),
287 fProofCluster(other.fProofCluster),
288 fProofDataSet(other.fProofDataSet),
289 fFileForTestMode(other.fFileForTestMode),
290 fAliRootMode(other.fAliRootMode),
291 fProofProcessOpt(other.fProofProcessOpt),
292 fMergeDirName(other.fMergeDirName),
297 fDropToShell(other.fDropToShell),
298 fGridJobIDs(other.fGridJobIDs),
299 fGridStages(other.fGridStages),
300 fFriendLibs(other.fFriendLibs),
301 fTreeName(other.fTreeName)
304 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
305 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
306 fRunRange[0] = other.fRunRange[0];
307 fRunRange[1] = other.fRunRange[1];
308 if (other.fInputFiles) {
309 fInputFiles = new TObjArray();
310 TIter next(other.fInputFiles);
312 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
313 fInputFiles->SetOwner();
315 if (other.fPackages) {
316 fPackages = new TObjArray();
317 TIter next(other.fPackages);
319 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
320 fPackages->SetOwner();
322 if (other.fModules) {
323 fModules = new TObjArray();
324 fModules->SetOwner();
325 TIter next(other.fModules);
326 AliAnalysisTaskCfg *mod, *crt;
327 while ((crt=(AliAnalysisTaskCfg*)next())) {
328 mod = new AliAnalysisTaskCfg(*crt);
334 //______________________________________________________________________________
335 AliAnalysisAlien::~AliAnalysisAlien()
343 fProofParam.DeleteAll();
346 //______________________________________________________________________________
347 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
350 if (this != &other) {
351 AliAnalysisGrid::operator=(other);
352 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
353 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
354 fPrice = other.fPrice;
356 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
357 fMaxInitFailed = other.fMaxInitFailed;
358 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
359 fNtestFiles = other.fNtestFiles;
360 fNrunsPerMaster = other.fNrunsPerMaster;
361 fMaxMergeFiles = other.fMaxMergeFiles;
362 fMaxMergeStages = other.fMaxMergeStages;
363 fNsubmitted = other.fNsubmitted;
364 fProductionMode = other.fProductionMode;
365 fOutputToRunNo = other.fOutputToRunNo;
366 fMergeViaJDL = other.fMergeViaJDL;
367 fFastReadOption = other.fFastReadOption;
368 fOverwriteMode = other.fOverwriteMode;
369 fNreplicas = other.fNreplicas;
370 fNproofWorkers = other.fNproofWorkers;
371 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
372 fProofReset = other.fProofReset;
373 fRunNumbers = other.fRunNumbers;
374 fExecutable = other.fExecutable;
375 fExecutableCommand = other.fExecutableCommand;
376 fArguments = other.fArguments;
377 fExecutableArgs = other.fExecutableArgs;
378 fAnalysisMacro = other.fAnalysisMacro;
379 fAnalysisSource = other.fAnalysisSource;
380 fValidationScript = other.fValidationScript;
381 fAdditionalRootLibs = other.fAdditionalRootLibs;
382 fAdditionalLibs = other.fAdditionalLibs;
383 fSplitMode = other.fSplitMode;
384 fAPIVersion = other.fAPIVersion;
385 fROOTVersion = other.fROOTVersion;
386 fAliROOTVersion = other.fAliROOTVersion;
387 fExternalPackages = other.fExternalPackages;
389 fGridWorkingDir = other.fGridWorkingDir;
390 fGridDataDir = other.fGridDataDir;
391 fDataPattern = other.fDataPattern;
392 fGridOutputDir = other.fGridOutputDir;
393 fOutputArchive = other.fOutputArchive;
394 fOutputFiles = other.fOutputFiles;
395 fInputFormat = other.fInputFormat;
396 fDatasetName = other.fDatasetName;
397 fJDLName = other.fJDLName;
398 fTerminateFiles = other.fTerminateFiles;
399 fMergeExcludes = other.fMergeExcludes;
400 fRegisterExcludes = other.fRegisterExcludes;
401 fIncludePath = other.fIncludePath;
402 fCloseSE = other.fCloseSE;
403 fFriendChainName = other.fFriendChainName;
404 fJobTag = other.fJobTag;
405 fOutputSingle = other.fOutputSingle;
406 fRunPrefix = other.fRunPrefix;
407 fProofCluster = other.fProofCluster;
408 fProofDataSet = other.fProofDataSet;
409 fFileForTestMode = other.fFileForTestMode;
410 fAliRootMode = other.fAliRootMode;
411 fProofProcessOpt = other.fProofProcessOpt;
412 fMergeDirName = other.fMergeDirName;
413 fDropToShell = other.fDropToShell;
414 fGridJobIDs = other.fGridJobIDs;
415 fGridStages = other.fGridStages;
416 fFriendLibs = other.fFriendLibs;
417 fTreeName = other.fTreeName;
418 if (other.fInputFiles) {
419 fInputFiles = new TObjArray();
420 TIter next(other.fInputFiles);
422 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
423 fInputFiles->SetOwner();
425 if (other.fPackages) {
426 fPackages = new TObjArray();
427 TIter next(other.fPackages);
429 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
430 fPackages->SetOwner();
432 if (other.fModules) {
433 fModules = new TObjArray();
434 fModules->SetOwner();
435 TIter next(other.fModules);
436 AliAnalysisTaskCfg *mod, *crt;
437 while ((crt=(AliAnalysisTaskCfg*)next())) {
438 mod = new AliAnalysisTaskCfg(*crt);
446 //______________________________________________________________________________
447 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
449 // Add a single additional library to be loaded. Extension must be present.
451 if (!lib.Contains(".")) {
452 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
455 if (fAdditionalLibs.Contains(name)) {
456 Warning("AddAdditionalLibrary", "Library %s already added.", name);
459 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
460 fAdditionalLibs += lib;
463 //______________________________________________________________________________
464 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
466 // Adding a module. Checks if already existing. Becomes owned by this.
468 if (GetModule(module->GetName())) {
469 Error("AddModule", "A module having the same name %s already added", module->GetName());
473 fModules = new TObjArray();
474 fModules->SetOwner();
476 fModules->Add(module);
479 //______________________________________________________________________________
480 void AliAnalysisAlien::AddModules(TObjArray *list)
482 // Adding a list of modules. Checks if already existing. Becomes owned by this.
484 AliAnalysisTaskCfg *module;
485 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
488 //______________________________________________________________________________
489 Bool_t AliAnalysisAlien::CheckDependencies()
491 // Check if all dependencies are satisfied. Reorder modules if needed.
492 Int_t nmodules = GetNmodules();
494 Warning("CheckDependencies", "No modules added yet to check their dependencies");
497 AliAnalysisTaskCfg *mod = 0;
498 AliAnalysisTaskCfg *dep = 0;
501 for (i=0; i<nmodules; i++) {
502 mod = (AliAnalysisTaskCfg*) fModules->At(i);
503 Int_t ndeps = mod->GetNdeps();
505 for (j=0; j<ndeps; j++) {
506 depname = mod->GetDependency(j);
507 dep = GetModule(depname);
509 Error("CheckDependencies","Dependency %s not added for module %s",
510 depname.Data(), mod->GetName());
513 if (dep->NeedsDependency(mod->GetName())) {
514 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
515 mod->GetName(), dep->GetName());
518 Int_t idep = fModules->IndexOf(dep);
519 // The dependency task must come first
521 // Remove at idep and move all objects below up one slot
522 // down to index i included.
523 fModules->RemoveAt(idep);
524 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
525 fModules->AddAt(dep, i++);
527 //Redo from istart if dependencies were inserted
528 if (i>istart) i=istart-1;
534 //______________________________________________________________________________
535 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
537 // Create the analysis manager and optionally execute the macro in filename.
538 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
540 mgr = new AliAnalysisManager(name);
541 mgr->SetGridHandler((AliAnalysisGrid*)this);
542 if (strlen(filename)) {
543 TString line = gSystem->ExpandPathName(filename);
545 gROOT->ProcessLine(line.Data());
550 //______________________________________________________________________________
551 Int_t AliAnalysisAlien::GetNmodules() const
553 // Get number of modules.
554 if (!fModules) return 0;
555 return fModules->GetEntries();
558 //______________________________________________________________________________
559 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
561 // Get a module by name.
562 if (!fModules) return 0;
563 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
566 //______________________________________________________________________________
567 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
569 // Load a given module.
570 if (mod->IsLoaded()) return kTRUE;
571 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
573 Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
576 Int_t ndeps = mod->GetNdeps();
578 for (Int_t j=0; j<ndeps; j++) {
579 depname = mod->GetDependency(j);
580 AliAnalysisTaskCfg *dep = GetModule(depname);
582 Error("LoadModule","Dependency %s not existing for module %s",
583 depname.Data(), mod->GetName());
586 if (!LoadModule(dep)) {
587 Error("LoadModule","Dependency %s for module %s could not be loaded",
588 depname.Data(), mod->GetName());
592 // Load libraries for the module
593 if (!mod->CheckLoadLibraries()) {
594 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
597 // Check if a custom file name was requested
598 if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
600 // Check if a custom terminate file name was requested
601 if (strlen(mod->GetTerminateFileName())) {
602 if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
603 fTerminateFiles += mod->GetTerminateFileName();
607 if (mod->ExecuteMacro()<0) {
608 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
609 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
612 // Configure dependencies
613 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
614 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
615 mod->GetConfigMacro()->GetTitle(), mod->GetName());
618 // Adjust extra libraries
619 Int_t nlibs = mod->GetNlibs();
621 for (Int_t i=0; i<nlibs; i++) {
622 lib = mod->GetLibrary(i);
623 lib = Form("lib%s.so", lib.Data());
624 if (fAdditionalLibs.Contains(lib)) continue;
625 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
626 fAdditionalLibs += lib;
631 //______________________________________________________________________________
632 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
634 // Generate the full train.
635 fAdditionalLibs = "";
636 if (!LoadModules()) return kFALSE;
637 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
638 if (!mgr->InitAnalysis()) return kFALSE;
641 Int_t productionMode = fProductionMode;
643 TString macro = fAnalysisMacro;
644 TString executable = fExecutable;
645 TString validation = fValidationScript;
646 TString execCommand = fExecutableCommand;
647 SetAnalysisMacro(Form("%s.C", name));
648 SetExecutable(Form("%s.sh", name));
649 // SetExecutableCommand("aliroot -b -q ");
650 SetValidationScript(Form("%s_validation.sh", name));
652 SetProductionMode(productionMode);
653 fAnalysisMacro = macro;
654 fExecutable = executable;
655 fExecutableCommand = execCommand;
656 fValidationScript = validation;
660 //______________________________________________________________________________
661 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
663 // Generate test macros for a single module or for the full train.
664 fAdditionalLibs = "";
665 if (strlen(modname)) {
666 if (!CheckDependencies()) return kFALSE;
667 AliAnalysisTaskCfg *mod = GetModule(modname);
669 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
672 if (!LoadModule(mod)) return kFALSE;
673 if (!LoadFriendLibs()) return kFALSE;
674 } else if (!LoadModules()) return kFALSE;
675 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
676 if (!mgr->InitAnalysis()) return kFALSE;
680 Int_t productionMode = fProductionMode;
682 TString macro = fAnalysisMacro;
683 TString executable = fExecutable;
684 TString validation = fValidationScript;
685 TString execCommand = fExecutableCommand;
686 SetAnalysisMacro(Form("%s.C", name));
687 SetExecutable(Form("%s.sh", name));
688 fOutputFiles = GetListOfFiles("outaod");
689 // Add extra files registered to the analysis manager
690 TString extra = GetListOfFiles("ext");
691 if (!extra.IsNull()) {
692 extra.ReplaceAll(".root", "*.root");
693 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
694 fOutputFiles += extra;
696 // SetExecutableCommand("aliroot -b -q ");
697 SetValidationScript(Form("%s_validation.sh", name));
699 WriteAnalysisMacro();
701 WriteValidationScript();
703 WriteMergeExecutable();
704 WriteValidationScript(kTRUE);
705 SetLocalTest(kFALSE);
706 SetProductionMode(productionMode);
707 fAnalysisMacro = macro;
708 fExecutable = executable;
709 fExecutableCommand = execCommand;
710 fValidationScript = validation;
714 //______________________________________________________________________________
715 Bool_t AliAnalysisAlien::LoadModules()
717 // Load all modules by executing the AddTask macros. Checks first the dependencies.
718 fAdditionalLibs = "";
719 Int_t nmodules = GetNmodules();
721 Warning("LoadModules", "No module to be loaded");
724 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
726 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
729 if (!CheckDependencies()) return kFALSE;
730 nmodules = GetNmodules();
731 AliAnalysisTaskCfg *mod;
732 for (Int_t imod=0; imod<nmodules; imod++) {
733 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
734 if (!LoadModule(mod)) return kFALSE;
736 // Load additional friend libraries
737 return LoadFriendLibs();
740 //______________________________________________________________________________
741 Bool_t AliAnalysisAlien::LoadFriendLibs() const
743 // Load libraries required for reading friends.
744 if (fFriendLibs.Length()) {
747 if (fFriendLibs.Contains(",")) list = fFriendLibs.Tokenize(",");
748 else list = fFriendLibs.Tokenize(" ");
749 for (Int_t ilib=0; ilib<list->GetEntriesFast(); ilib++) {
750 lib = list->At(ilib)->GetName();
751 lib.ReplaceAll(".so","");
752 lib.ReplaceAll(" ","");
753 if (lib.BeginsWith("lib")) lib.Remove(0, 3);
755 Int_t loaded = strlen(gSystem->GetLibraries(lib,"",kFALSE));
756 if (!loaded) loaded = gSystem->Load(lib);
758 Error("LoadModules", "Cannot load library for friends %s", lib.Data());
767 //______________________________________________________________________________
768 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
770 // Set the run number format. Can be a prefix or a format like "%09d"
772 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
775 //______________________________________________________________________________
776 void AliAnalysisAlien::AddIncludePath(const char *path)
778 // Add include path in the remote analysis macro.
780 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
781 else fIncludePath += Form("-I%s ", path);
784 //______________________________________________________________________________
785 void AliAnalysisAlien::AddRunNumber(Int_t run)
787 // Add a run number to the list of runs to be processed.
788 if (fRunNumbers.Length()) fRunNumbers += " ";
789 fRunNumbers += Form(fRunPrefix.Data(), run);
792 //______________________________________________________________________________
793 void AliAnalysisAlien::AddRunList(const char* runList)
795 // Add several runs into the list of runs; they are expected to be separated by a blank character.
796 TString sList = runList;
797 TObjArray *list = sList.Tokenize(" ");
798 Int_t n = list->GetEntries();
799 for (Int_t i = 0; i < n; i++) {
800 TObjString *os = (TObjString*)list->At(i);
801 AddRunNumber(os->GetString().Atoi());
806 //______________________________________________________________________________
807 void AliAnalysisAlien::AddRunNumber(const char* run)
809 // Add a run number to the list of runs to be processed.
812 TObjArray *arr = runs.Tokenize(" ");
815 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
816 while ((os=(TObjString*)next())){
817 if (fRunNumbers.Length()) fRunNumbers += " ";
818 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
823 //______________________________________________________________________________
824 void AliAnalysisAlien::AddDataFile(const char *lfn)
826 // Adds a data file to the input to be analysed. The file should be a valid LFN
827 // or point to an existing file in the alien workdir.
828 if (!fInputFiles) fInputFiles = new TObjArray();
829 fInputFiles->Add(new TObjString(lfn));
832 //______________________________________________________________________________
833 void AliAnalysisAlien::AddExternalPackage(const char *package)
835 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
836 if (fExternalPackages) fExternalPackages += " ";
837 fExternalPackages += package;
840 //______________________________________________________________________________
841 Bool_t AliAnalysisAlien::Connect()
843 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
844 if (gGrid && gGrid->IsConnected()) return kTRUE;
845 if (fProductionMode) return kTRUE;
847 Info("Connect", "Trying to connect to AliEn ...");
848 TGrid::Connect("alien://");
850 if (!gGrid || !gGrid->IsConnected()) {
851 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
854 fUser = gGrid->GetUser();
855 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
859 //______________________________________________________________________________
860 void AliAnalysisAlien::CdWork()
862 // Check validity of alien workspace. Create directory if possible.
864 Error("CdWork", "Alien connection required");
867 TString homedir = gGrid->GetHomeDirectory();
868 TString workdir = homedir + fGridWorkingDir;
869 if (DirectoryExists(workdir)) {
873 // Work directory not existing - create it
875 if (gGrid->Mkdir(workdir, "-p")) {
876 gGrid->Cd(fGridWorkingDir);
877 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
879 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
880 workdir.Data(), homedir.Data());
881 fGridWorkingDir = "";
885 //______________________________________________________________________________
886 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
888 // Check if file copying is possible.
889 if (fProductionMode) return kTRUE;
890 TString salienpath(alienpath);
891 if (salienpath.Contains(" ")) {
892 Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
896 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
899 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
900 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
901 // Check if alien_CLOSE_SE is defined
902 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
903 if (!closeSE.IsNull()) {
904 Info("CheckFileCopy", "Your current close storage is pointing to: \
905 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
907 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
909 // Check if grid directory exists.
910 if (!DirectoryExists(alienpath)) {
911 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
914 TString stest = "plugin_test_copy";
915 TFile f(stest, "RECREATE");
916 // User may not have write permissions to current directory
918 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
919 gSystem->WorkingDirectory());
923 if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
924 if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
925 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
926 \n# 1. Make sure you have write permissions there. If this is the case: \
927 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
928 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
929 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
930 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
931 gSystem->Unlink(stest.Data());
934 gSystem->Unlink(stest.Data());
935 gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
936 Info("CheckFileCopy", "### ...SUCCESS ###");
940 //______________________________________________________________________________
941 Bool_t AliAnalysisAlien::CheckInputData()
943 // Check validity of input data. If necessary, create xml files.
944 if (fProductionMode) return kTRUE;
945 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
946 if (!fGridDataDir.Length()) {
947 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
951 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
954 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
955 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
956 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
959 // Process declared files
960 Bool_t isCollection = kFALSE;
961 Bool_t isXml = kFALSE;
962 Bool_t useTags = kFALSE;
963 Bool_t checked = kFALSE;
964 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
966 TString workdir = gGrid->GetHomeDirectory();
967 workdir += fGridWorkingDir;
970 TIter next(fInputFiles);
971 while ((objstr=(TObjString*)next())) {
974 file += objstr->GetString();
975 // Store full lfn path
976 if (FileExists(file)) objstr->SetString(file);
978 file = objstr->GetName();
979 if (!FileExists(objstr->GetName())) {
980 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
981 objstr->GetName(), workdir.Data());
985 Bool_t iscoll, isxml, usetags;
986 CheckDataType(file, iscoll, isxml, usetags);
989 isCollection = iscoll;
992 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
994 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
995 Error("CheckInputData", "Some conflict was found in the types of inputs");
1001 // Process requested run numbers
1002 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
1003 // Check validity of alien data directory
1004 if (!fGridDataDir.Length()) {
1005 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
1008 if (!DirectoryExists(fGridDataDir)) {
1009 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
1013 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
1017 if (checked && !isXml) {
1018 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
1021 // Check validity of run number(s)
1026 TString schunk, schunk2;
1030 useTags = fDataPattern.Contains("tag");
1031 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
1033 if (useTags != fDataPattern.Contains("tag")) {
1034 Error("CheckInputData", "Cannot mix input files using/not using tags");
1037 if (fRunNumbers.Length()) {
1038 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
1039 arr = fRunNumbers.Tokenize(" ");
1041 while ((os=(TObjString*)next())) {
1042 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
1043 if (!DirectoryExists(path)) {
1044 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
1047 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
1048 TString msg = "\n##### file: ";
1050 msg += " type: xml_collection;";
1051 if (useTags) msg += " using_tags: Yes";
1052 else msg += " using_tags: No";
1053 Info("CheckDataType", "%s", msg.Data());
1054 if (fNrunsPerMaster<2) {
1055 AddDataFile(Form("%s.xml", os->GetString().Data()));
1058 if (((nruns-1)%fNrunsPerMaster) == 0) {
1059 schunk = os->GetString();
1061 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
1062 schunk += Form("_%s.xml", os->GetString().Data());
1063 AddDataFile(schunk);
1068 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1069 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1070 format = Form("%%s/%s ", fRunPrefix.Data());
1071 path = Form(format.Data(), fGridDataDir.Data(), irun);
1072 if (!DirectoryExists(path)) {
1075 format = Form("%%s/%s.xml", fRunPrefix.Data());
1076 path = Form(format.Data(), workdir.Data(),irun);
1077 TString msg = "\n##### file: ";
1079 msg += " type: xml_collection;";
1080 if (useTags) msg += " using_tags: Yes";
1081 else msg += " using_tags: No";
1082 Info("CheckDataType", "%s", msg.Data());
1083 if (fNrunsPerMaster<2) {
1084 format = Form("%s.xml", fRunPrefix.Data());
1085 AddDataFile(Form(format.Data(),irun));
1088 if (((nruns-1)%fNrunsPerMaster) == 0) {
1089 schunk = Form(fRunPrefix.Data(),irun);
1091 format = Form("_%s.xml", fRunPrefix.Data());
1092 schunk2 = Form(format.Data(), irun);
1093 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1095 AddDataFile(schunk);
1100 AddDataFile(schunk);
1106 //______________________________________________________________________________
1107 Int_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1109 // Copy data from the given grid directory according a pattern and make a local
1111 // 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
1113 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1116 if (!DirectoryExists(griddir)) {
1117 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1120 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1121 printf("Running command: %s\n", command.Data());
1122 TGridResult *res = gGrid->Command(command);
1123 Int_t nfound = res->GetEntries();
1125 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1128 printf("... found %d files. Copying locally ...\n", nfound);
1131 TObjArray* additionalArchives = 0;
1132 if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1133 additionalArchives = TString(archivefile).Tokenize(";");
1134 archivefile = additionalArchives->At(0)->GetName();
1135 additionalArchives->RemoveAt(0);
1136 additionalArchives->Compress();
1139 // Copy files locally
1141 out.open(output, ios::out);
1143 TString turl, dirname, filename, temp;
1144 TString cdir = gSystem->WorkingDirectory();
1145 gSystem->MakeDirectory(outputdir);
1146 gSystem->ChangeDirectory(outputdir);
1148 for (Int_t i=0; i<nfound; i++) {
1149 map = (TMap*)res->At(i);
1150 turl = map->GetValue("turl")->GetName();
1151 filename = gSystem->BaseName(turl.Data());
1152 dirname = gSystem->DirName(turl.Data());
1153 dirname = gSystem->BaseName(dirname.Data());
1154 gSystem->MakeDirectory(dirname);
1156 TString source(turl);
1157 TString targetFileName(filename);
1159 if (strlen(archivefile) > 0) {
1160 // TODO here the archive in which the file resides should be determined
1161 // however whereis returns only a guid, and guid2lfn does not work
1162 // Therefore we use the one provided as argument for now
1163 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1164 targetFileName = archivefile;
1166 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1167 Bool_t success = kTRUE;
1168 if (additionalArchives) {
1169 for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++) {
1171 target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1172 gSystem->MakeDirectory(gSystem->DirName(target));
1173 success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1178 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1179 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1184 gSystem->ChangeDirectory(cdir);
1186 delete additionalArchives;
1190 //______________________________________________________________________________
1191 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1193 // Create dataset for the grid data directory + run number.
1194 const Int_t gMaxEntries = 15000;
1195 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1197 Error("CreateDataset", "Cannot create dataset with no grid connection");
1202 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1203 TString workdir = gGrid->GetHomeDirectory();
1204 workdir += fGridWorkingDir;
1206 // Compose the 'find' command arguments
1209 TString delimiter = pattern;
1211 if (delimiter.Contains(" ")) delimiter = "";
1212 else delimiter = " ";
1213 TString options = "-x collection ";
1214 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1215 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1216 TString conditions = "";
1223 TString schunk, schunk2;
1224 TGridCollection *cbase=0, *cadd=0;
1225 if (!fRunNumbers.Length() && !fRunRange[0]) {
1226 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1227 // Make a single data collection from data directory.
1228 path = fGridDataDir;
1229 if (!DirectoryExists(path)) {
1230 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1234 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1235 else file = Form("%s.xml", gSystem->BaseName(path));
1239 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1241 command += Form("%s -o %d ",options.Data(), nstart);
1243 command += delimiter;
1245 command += conditions;
1246 printf("command: %s\n", command.Data());
1247 TGridResult *res = gGrid->Command(command);
1248 if (res) delete res;
1249 // Write standard output to file
1250 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1251 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1252 Bool_t nullFile = kFALSE;
1254 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1256 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1258 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1259 gSystem->Exec("rm -f __tmp*");
1267 gSystem->Exec("rm -f __tmp__");
1268 ncount = line.Atoi();
1271 if (ncount == gMaxEntries) {
1272 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1273 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1274 if (!cbase) cbase = cadd;
1282 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1283 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1286 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1287 delete cbase; cbase = 0;
1289 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1291 gSystem->Exec("rm -f __tmp*");
1292 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1296 Bool_t fileExists = FileExists(file);
1297 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1298 // Copy xml file to alien space
1299 if (fileExists) gGrid->Rm(file);
1300 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1301 if (!FileExists(file)) {
1302 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1305 // Update list of files to be processed.
1307 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1311 Bool_t nullResult = kTRUE;
1312 if (fRunNumbers.Length()) {
1313 TObjArray *arr = fRunNumbers.Tokenize(" ");
1316 while ((os=(TObjString*)next())) {
1319 path = Form("%s/%s/", fGridDataDir.Data(), os->GetString().Data());
1320 if (!DirectoryExists(path)) continue;
1322 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1323 else file = Form("%s.xml", os->GetString().Data());
1324 // If local collection file does not exist, create it via 'find' command.
1328 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1330 command += Form("%s -o %d ",options.Data(), nstart);
1332 command += delimiter;
1334 command += conditions;
1335 TGridResult *res = gGrid->Command(command);
1336 if (res) delete res;
1337 // Write standard output to file
1338 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1339 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1340 Bool_t nullFile = kFALSE;
1342 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1344 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1346 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1347 gSystem->Exec("rm -f __tmp*");
1348 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1356 gSystem->Exec("rm -f __tmp__");
1357 ncount = line.Atoi();
1359 nullResult = kFALSE;
1361 if (ncount == gMaxEntries) {
1362 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1363 if (fNrunsPerMaster > 1) {
1364 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1365 file.Data(),gMaxEntries);
1368 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1369 if (!cbase) cbase = cadd;
1376 if (cbase && fNrunsPerMaster<2) {
1377 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1378 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1381 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1382 delete cbase; cbase = 0;
1384 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1386 gSystem->Exec("rm -f __tmp*");
1387 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1391 if (TestBit(AliAnalysisGrid::kTest)) break;
1392 // Check if there is one run per master job.
1393 if (fNrunsPerMaster<2) {
1394 if (FileExists(file)) {
1395 if (fOverwriteMode) gGrid->Rm(file);
1397 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1401 // Copy xml file to alien space
1402 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1403 if (!FileExists(file)) {
1404 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1410 if (((nruns-1)%fNrunsPerMaster) == 0) {
1411 schunk = os->GetString();
1412 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1414 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1415 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1419 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1422 schunk += Form("_%s.xml", os->GetString().Data());
1423 if (FileExists(schunk)) {
1424 if (fOverwriteMode) gGrid->Rm(file);
1426 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1430 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1431 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1432 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1433 if (!FileExists(schunk)) {
1434 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1442 Error("CreateDataset", "No valid dataset corresponding to the query!");
1446 // Process a full run range.
1447 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1448 format = Form("%%s/%s/", fRunPrefix.Data());
1451 path = Form(format.Data(), fGridDataDir.Data(), irun);
1452 if (!DirectoryExists(path)) continue;
1454 format = Form("%s.xml", fRunPrefix.Data());
1455 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1456 else file = Form(format.Data(), irun);
1457 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1458 if (fOverwriteMode) gGrid->Rm(file);
1460 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1464 // If local collection file does not exist, create it via 'find' command.
1468 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1470 command += Form("%s -o %d ",options.Data(), nstart);
1472 command += delimiter;
1474 command += conditions;
1475 TGridResult *res = gGrid->Command(command);
1476 if (res) delete res;
1477 // Write standard output to file
1478 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1479 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1480 Bool_t nullFile = kFALSE;
1482 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1484 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1486 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1487 gSystem->Exec("rm -f __tmp*");
1495 gSystem->Exec("rm -f __tmp__");
1496 ncount = line.Atoi();
1498 nullResult = kFALSE;
1500 if (ncount == gMaxEntries) {
1501 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1502 if (fNrunsPerMaster > 1) {
1503 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1504 file.Data(),gMaxEntries);
1507 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1508 if (!cbase) cbase = cadd;
1515 if (cbase && fNrunsPerMaster<2) {
1516 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1517 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1520 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1521 delete cbase; cbase = 0;
1523 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1525 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1529 if (TestBit(AliAnalysisGrid::kTest)) break;
1530 // Check if there is one run per master job.
1531 if (fNrunsPerMaster<2) {
1532 if (FileExists(file)) {
1533 if (fOverwriteMode) gGrid->Rm(file);
1535 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1539 // Copy xml file to alien space
1540 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1541 if (!FileExists(file)) {
1542 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1547 // Check if the collection for the chunk exist locally.
1548 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1549 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1550 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1553 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1554 if (((nruns-1)%fNrunsPerMaster) == 0) {
1555 schunk = Form(fRunPrefix.Data(), irun);
1556 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1558 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1562 format = Form("%%s_%s.xml", fRunPrefix.Data());
1563 schunk2 = Form(format.Data(), schunk.Data(), irun);
1564 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1568 if (FileExists(schunk)) {
1569 if (fOverwriteMode) gGrid->Rm(schunk);
1571 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1575 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1576 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1577 if (FileExists(schunk)) {
1578 if (fOverwriteMode) gGrid->Rm(schunk);
1580 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1584 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1585 if (!FileExists(schunk)) {
1586 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1592 Error("CreateDataset", "No valid dataset corresponding to the query!");
1599 //______________________________________________________________________________
1600 Bool_t AliAnalysisAlien::CreateJDL()
1602 // Generate a JDL file according to current settings. The name of the file is
1603 // specified by fJDLName.
1604 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1605 Bool_t error = kFALSE;
1607 Bool_t copy = kTRUE;
1608 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1609 Bool_t generate = kTRUE;
1610 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1612 Error("CreateJDL", "Alien connection required");
1615 // Check validity of alien workspace
1617 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1618 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1619 workdir += fGridWorkingDir;
1623 Error("CreateJDL()", "Define some input files for your analysis.");
1626 // Compose list of input files
1627 // Check if output files were defined
1628 if (!fOutputFiles.Length()) {
1629 Error("CreateJDL", "You must define at least one output file");
1632 // Check if an output directory was defined and valid
1633 if (!fGridOutputDir.Length()) {
1634 Error("CreateJDL", "You must define AliEn output directory");
1637 if (!fProductionMode) {
1638 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1639 if (!DirectoryExists(fGridOutputDir)) {
1640 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1641 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1643 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1647 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1652 // Exit if any error up to now
1653 if (error) return kFALSE;
1655 if (!fUser.IsNull()) {
1656 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1657 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1659 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1660 TString mergeExec = fExecutable;
1661 mergeExec.ReplaceAll(".sh", "_merge.sh");
1662 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1663 mergeExec.ReplaceAll(".sh", ".C");
1664 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1665 if (!fArguments.IsNull())
1666 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1667 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1669 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1670 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1673 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1674 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1675 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1676 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1678 if (fMaxInitFailed > 0) {
1679 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1680 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1682 if (fSplitMaxInputFileNumber > 0) {
1683 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1684 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1686 if (!IsOneStageMerging()) {
1687 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1688 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1690 if (fSplitMode.Length()) {
1691 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1692 fGridJDL->SetDescription("Split", "We split per SE or file");
1694 fMergingJDL->SetValue("Split", "\"se\"");
1695 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1696 if (!fAliROOTVersion.IsNull()) {
1697 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1698 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1700 if (!fROOTVersion.IsNull()) {
1701 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1702 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1704 if (!fAPIVersion.IsNull()) {
1705 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1706 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1708 if (!fExternalPackages.IsNull()) {
1709 arr = fExternalPackages.Tokenize(" ");
1711 while ((os=(TObjString*)next())) {
1712 TString pkgname = os->GetString();
1713 Int_t index = pkgname.Index("::");
1714 TString pkgversion = pkgname(index+2, pkgname.Length());
1715 pkgname.Remove(index);
1716 fGridJDL->AddToPackages(pkgname, pkgversion);
1717 fMergingJDL->AddToPackages(pkgname, pkgversion);
1721 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1722 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1723 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1724 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1725 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1726 TString analysisFile = fExecutable;
1727 analysisFile.ReplaceAll(".sh", ".root");
1728 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1729 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1730 if (fAdditionalLibs.Length()) {
1731 arr = fAdditionalLibs.Tokenize(" ");
1733 while ((os=(TObjString*)next())) {
1734 if (os->GetString().Contains(".so")) continue;
1735 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1736 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1741 TIter next(fPackages);
1743 while ((obj=next())) {
1744 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1745 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1748 const char *comment = "List of output files and archives";
1749 if (fOutputArchive.Length()) {
1750 TString outputArchive = fOutputArchive;
1751 if (!fRegisterExcludes.IsNull()) {
1752 arr = fRegisterExcludes.Tokenize(" ");
1754 while ((os=(TObjString*)next1())) {
1755 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1756 outputArchive.ReplaceAll(os->GetString(),"");
1760 arr = outputArchive.Tokenize(" ");
1762 Bool_t first = kTRUE;
1763 while ((os=(TObjString*)next())) {
1764 if (!os->GetString().Contains("@") && fCloseSE.Length())
1765 fGridJDL->AddToSet("Output", Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
1767 fGridJDL->AddToSet("Output", os->GetString());
1768 if (first) fGridJDL->AddToSetDescription("Output", comment);
1772 // Output archive for the merging jdl
1773 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1774 outputArchive = "log_archive.zip:std*@disk=1 ";
1775 // Add normal output files, extra files + terminate files
1776 TString files = GetListOfFiles("outextter");
1777 // Do not register files in fRegisterExcludes
1778 if (!fRegisterExcludes.IsNull()) {
1779 arr = fRegisterExcludes.Tokenize(" ");
1781 while ((os=(TObjString*)next1())) {
1782 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1783 files.ReplaceAll(os->GetString(),"");
1787 files.ReplaceAll(".root", "*.root");
1789 if (mgr->IsCollectThroughput())
1790 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d %s@disk=%d",files.Data(),fNreplicas, mgr->GetFileInfoLog(),fNreplicas);
1792 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1794 TString files = fOutputArchive;
1795 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1796 outputArchive = files;
1798 arr = outputArchive.Tokenize(" ");
1801 while ((os=(TObjString*)next2())) {
1802 TString currentfile = os->GetString();
1803 if (!currentfile.Contains("@") && fCloseSE.Length())
1804 fMergingJDL->AddToSet("Output", Form("%s@%s",currentfile.Data(), fCloseSE.Data()));
1806 fMergingJDL->AddToSet("Output", currentfile);
1807 if (first) fMergingJDL->AddToSetDescription("Output", comment);
1812 arr = fOutputFiles.Tokenize(",");
1814 Bool_t first = kTRUE;
1815 while ((os=(TObjString*)next())) {
1816 // Ignore ouputs in jdl that are also in outputarchive
1817 TString sout = os->GetString();
1818 sout.ReplaceAll("*", "");
1819 sout.ReplaceAll(".root", "");
1820 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1821 if (fOutputArchive.Contains(sout)) continue;
1822 // Ignore fRegisterExcludes
1823 if (fRegisterExcludes.Contains(sout)) continue;
1824 if (!first) comment = NULL;
1825 if (!os->GetString().Contains("@") && fCloseSE.Length())
1826 fGridJDL->AddToSet("Output", Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
1828 fGridJDL->AddToSet("Output", os->GetString());
1829 if (first) fGridJDL->AddToSetDescription("Output", comment);
1830 if (fMergeExcludes.Contains(sout)) continue;
1831 if (!os->GetString().Contains("@") && fCloseSE.Length())
1832 fMergingJDL->AddToSet("Output", Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
1834 fMergingJDL->AddToSet("Output", os->GetString());
1835 if (first) fMergingJDL->AddToSetDescription("Output", comment);
1839 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1840 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1841 TString validationScript = fValidationScript;
1842 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1843 validationScript.ReplaceAll(".sh", "_merge.sh");
1844 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1845 if (fMasterResubmitThreshold) {
1846 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1847 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1849 // Write a jdl with 2 input parameters: collection name and output dir name.
1852 // Copy jdl to grid workspace
1854 // Check if an output directory was defined and valid
1855 if (!fGridOutputDir.Length()) {
1856 Error("CreateJDL", "You must define AliEn output directory");
1859 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1860 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1861 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1862 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1864 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1870 if (TestBit(AliAnalysisGrid::kSubmit)) {
1871 TString mergeJDLName = fExecutable;
1872 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1873 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1874 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1875 if (fProductionMode) {
1876 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1877 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1879 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1880 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1881 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1882 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1883 Fatal("","Terminating");
1884 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1886 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1887 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1888 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1889 Fatal("","Terminating");
1892 if (fAdditionalLibs.Length()) {
1893 arr = fAdditionalLibs.Tokenize(" ");
1896 while ((os=(TObjString*)next())) {
1897 if (os->GetString().Contains(".so")) continue;
1898 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1899 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1900 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1901 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1902 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1903 Fatal("","Terminating");
1908 TIter next(fPackages);
1910 while ((obj=next())) {
1911 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1912 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1913 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1914 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1915 Form("%s/%s", workdir.Data(), obj->GetName())))
1916 Fatal("","Terminating");
1923 //______________________________________________________________________________
1924 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1926 // Writes one or more JDL's corresponding to findex. If findex is negative,
1927 // all run numbers are considered in one go (jdl). For non-negative indices
1928 // they correspond to the indices in the array fInputFiles.
1929 if (!fInputFiles) return kFALSE;
1932 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1933 workdir += fGridWorkingDir;
1934 TString stageName = "$2";
1935 if (fProductionMode) stageName = "$4";
1936 if (!fMergeDirName.IsNull()) {
1937 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1938 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1940 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1941 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1943 if (fProductionMode) {
1944 TIter next(fInputFiles);
1945 while ((os=next())) {
1946 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1948 if (!fOutputToRunNo)
1949 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1951 fGridJDL->SetOutputDirectory(fGridOutputDir);
1953 if (!fRunNumbers.Length() && !fRunRange[0]) {
1954 // One jdl with no parameters in case input data is specified by name.
1955 TIter next(fInputFiles);
1957 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1958 if (!fOutputSingle.IsNull())
1959 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1961 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1962 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1965 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1966 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1967 if (!fOutputSingle.IsNull()) {
1968 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1969 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1971 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1976 // Generate the JDL as a string
1977 TString sjdl = fGridJDL->Generate();
1978 TString sjdl1 = fMergingJDL->Generate();
1980 if (!fMergeDirName.IsNull()) {
1981 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1982 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1984 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1985 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1987 TString sjdl2 = fMergingJDL->Generate();
1988 Int_t index, index1;
1989 sjdl.ReplaceAll("\",\"", "\",\n \"");
1990 sjdl.ReplaceAll("(member", "\n (member");
1991 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1992 sjdl.ReplaceAll("{", "{\n ");
1993 sjdl.ReplaceAll("};", "\n};");
1994 sjdl.ReplaceAll("{\n \n", "{\n");
1995 sjdl.ReplaceAll("\n\n", "\n");
1996 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1997 sjdl1.ReplaceAll("\",\"", "\",\n \"");
1998 sjdl1.ReplaceAll("(member", "\n (member");
1999 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
2000 sjdl1.ReplaceAll("{", "{\n ");
2001 sjdl1.ReplaceAll("};", "\n};");
2002 sjdl1.ReplaceAll("{\n \n", "{\n");
2003 sjdl1.ReplaceAll("\n\n", "\n");
2004 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
2005 sjdl2.ReplaceAll("\",\"", "\",\n \"");
2006 sjdl2.ReplaceAll("(member", "\n (member");
2007 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
2008 sjdl2.ReplaceAll("{", "{\n ");
2009 sjdl2.ReplaceAll("};", "\n};");
2010 sjdl2.ReplaceAll("{\n \n", "{\n");
2011 sjdl2.ReplaceAll("\n\n", "\n");
2012 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
2013 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
2014 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
2015 index = sjdl.Index("JDLVariables");
2016 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
2017 sjdl += "Workdirectorysize = {\"5000MB\"};";
2018 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
2019 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
2020 index = fJobTag.Index(":");
2021 if (index < 0) index = fJobTag.Length();
2022 TString jobTag = fJobTag;
2023 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
2024 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
2025 if (fProductionMode) {
2026 sjdl1.Prepend("# Generated merging jdl (production mode) \
2027 \n# $1 = full alien path to output directory to be merged \
2028 \n# $2 = train number \
2029 \n# $3 = production (like LHC10b) \
2030 \n# $4 = merging stage \
2031 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2032 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
2033 sjdl2.Prepend("# Generated merging jdl \
2034 \n# $1 = full alien path to output directory to be merged \
2035 \n# $2 = train number \
2036 \n# $3 = production (like LHC10b) \
2037 \n# $4 = merging stage \
2038 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2040 sjdl1.Prepend("# Generated merging jdl \
2041 \n# $1 = full alien path to output directory to be merged \
2042 \n# $2 = merging stage \
2043 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2044 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
2045 sjdl2.Prepend("# Generated merging jdl \
2046 \n# $1 = full alien path to output directory to be merged \
2047 \n# $2 = merging stage \
2048 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
2050 index = sjdl1.Index("JDLVariables");
2051 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
2052 index = sjdl2.Index("JDLVariables");
2053 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
2054 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
2055 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
2056 index = sjdl2.Index("Split =");
2058 index1 = sjdl2.Index("\n", index);
2059 sjdl2.Remove(index, index1-index+1);
2061 index = sjdl2.Index("SplitMaxInputFileNumber");
2063 index1 = sjdl2.Index("\n", index);
2064 sjdl2.Remove(index, index1-index+1);
2066 index = sjdl2.Index("InputDataCollection");
2068 index1 = sjdl2.Index(";", index);
2069 sjdl2.Remove(index, index1-index+1);
2071 index = sjdl2.Index("InputDataListFormat");
2073 index1 = sjdl2.Index("\n", index);
2074 sjdl2.Remove(index, index1-index+1);
2076 index = sjdl2.Index("InputDataList");
2078 index1 = sjdl2.Index("\n", index);
2079 sjdl2.Remove(index, index1-index+1);
2081 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
2082 // Write jdl to file
2084 out.open(fJDLName.Data(), ios::out);
2086 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2089 out << sjdl << endl;
2091 TString mergeJDLName = fExecutable;
2092 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2095 out1.open(mergeJDLName.Data(), ios::out);
2097 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2100 out1 << sjdl1 << endl;
2103 TString finalJDL = mergeJDLName;
2104 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2105 out2.open(finalJDL.Data(), ios::out);
2107 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2110 out2 << sjdl2 << endl;
2114 // Copy jdl to grid workspace
2116 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2118 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2119 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2120 TString finalJDL = mergeJDLName;
2121 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2122 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2123 if (fProductionMode) {
2124 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2125 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2126 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2128 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2129 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2130 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2131 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2132 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2133 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2134 Fatal("","Terminating");
2136 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2137 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2138 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2139 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2140 Fatal("","Terminating");
2141 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2142 Fatal("","Terminating");
2148 //______________________________________________________________________________
2149 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2151 // Returns true if file exists.
2152 if (!gGrid) return kFALSE;
2154 slfn.ReplaceAll("alien://","");
2155 TGridResult *res = gGrid->Ls(slfn);
2156 if (!res) return kFALSE;
2157 TMap *map = dynamic_cast<TMap*>(res->At(0));
2162 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2163 if (!objs || !objs->GetString().Length()) {
2171 //______________________________________________________________________________
2172 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2174 // Returns true if directory exists. Can be also a path.
2175 if (!gGrid) return kFALSE;
2176 // Check if dirname is a path
2177 TString dirstripped = dirname;
2178 dirstripped = dirstripped.Strip();
2179 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2180 TString dir = gSystem->BaseName(dirstripped);
2182 TString path = gSystem->DirName(dirstripped);
2183 TGridResult *res = gGrid->Ls(path, "-F");
2184 if (!res) return kFALSE;
2188 while ((map=dynamic_cast<TMap*>(next()))) {
2189 obj = map->GetValue("name");
2191 if (dir == obj->GetName()) {
2200 //______________________________________________________________________________
2201 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2203 // Check input data type.
2204 isCollection = kFALSE;
2208 Error("CheckDataType", "No connection to grid");
2211 isCollection = IsCollection(lfn);
2212 TString msg = "\n##### file: ";
2215 msg += " type: raw_collection;";
2216 // special treatment for collections
2218 // check for tag files in the collection
2219 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2221 msg += " using_tags: No (unknown)";
2222 Info("CheckDataType", "%s", msg.Data());
2225 const char* typeStr = res->GetKey(0, "origLFN");
2226 if (!typeStr || !strlen(typeStr)) {
2227 msg += " using_tags: No (unknown)";
2228 Info("CheckDataType", "%s", msg.Data());
2231 TString file = typeStr;
2232 useTags = file.Contains(".tag");
2233 if (useTags) msg += " using_tags: Yes";
2234 else msg += " using_tags: No";
2235 Info("CheckDataType", "%s", msg.Data());
2240 isXml = slfn.Contains(".xml");
2242 // Open xml collection and check if there are tag files inside
2243 msg += " type: xml_collection;";
2244 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2246 msg += " using_tags: No (unknown)";
2247 Info("CheckDataType", "%s", msg.Data());
2250 TMap *map = coll->Next();
2252 msg += " using_tags: No (unknown)";
2253 Info("CheckDataType", "%s", msg.Data());
2256 map = (TMap*)map->GetValue("");
2258 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2259 useTags = file.Contains(".tag");
2261 if (useTags) msg += " using_tags: Yes";
2262 else msg += " using_tags: No";
2263 Info("CheckDataType", "%s", msg.Data());
2266 useTags = slfn.Contains(".tag");
2267 if (slfn.Contains(".root")) msg += " type: root file;";
2268 else msg += " type: unknown file;";
2269 if (useTags) msg += " using_tags: Yes";
2270 else msg += " using_tags: No";
2271 Info("CheckDataType", "%s", msg.Data());
2274 //______________________________________________________________________________
2275 void AliAnalysisAlien::EnablePackage(const char *package)
2277 // Enables a par file supposed to exist in the current directory.
2278 TString pkg(package);
2279 pkg.ReplaceAll(".par", "");
2281 if (gSystem->AccessPathName(pkg)) {
2282 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2285 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2286 Info("EnablePackage", "AliEn plugin will use .par packages");
2287 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2289 fPackages = new TObjArray();
2290 fPackages->SetOwner();
2292 fPackages->Add(new TObjString(pkg));
2295 //______________________________________________________________________________
2296 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2298 // Make a tree from files having the location specified in fFileForTestMode.
2299 // Inspired from JF's CreateESDChain.
2300 if (fFileForTestMode.IsNull()) {
2301 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2304 if (gSystem->AccessPathName(fFileForTestMode)) {
2305 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2310 in.open(fFileForTestMode);
2312 // Read the input list of files and add them to the chain
2314 TString streeName(treeName);
2315 if (IsUseMCchain()) streeName = "TE";
2316 TChain *chain = new TChain(streeName);
2317 TList *friends = new TList();
2318 TChain *cfriend = 0;
2319 if (!fFriendChainName.IsNull()) {
2320 TObjArray *list = fFriendChainName.Tokenize(" ");
2323 while((str=(TObjString*)next())) {
2324 cfriend = new TChain(streeName, str->GetName());
2325 friends->Add(cfriend);
2326 chain->AddFriend(cfriend);
2331 TIter nextfriend(friends);
2335 if (line.IsNull() || line.BeginsWith("#")) continue;
2336 if (count++ == fNtestFiles) break;
2337 TString esdFile(line);
2338 TFile *file = TFile::Open(esdFile);
2339 if (file && !file->IsZombie()) {
2340 chain->Add(esdFile);
2342 if (!fFriendChainName.IsNull()) {
2343 if (esdFile.Index("#") > -1)
2344 esdFile.Remove(esdFile.Index("#"));
2345 bpath = gSystem->DirName(esdFile);
2349 while ((cfriend=(TChain*)nextfriend())) {
2351 fileFriend += cfriend->GetTitle();
2352 file = TFile::Open(fileFriend);
2353 if (file && !file->IsZombie()) {
2355 cfriend->Add(fileFriend);
2357 Fatal("GetChainForTestMode", "Cannot open friend file: %s", fileFriend.Data());
2363 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2367 if (!chain->GetListOfFiles()->GetEntries()) {
2368 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2377 //______________________________________________________________________________
2378 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2380 // Get job status for all jobs with jobid>jobidstart.
2381 static char mstatus[20];
2387 TGridJobStatusList *list = gGrid->Ps("");
2388 if (!list) return mstatus;
2389 Int_t nentries = list->GetSize();
2390 TGridJobStatus *status;
2392 for (Int_t ijob=0; ijob<nentries; ijob++) {
2393 status = (TGridJobStatus *)list->At(ijob);
2394 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2395 if (pid<jobidstart) continue;
2396 if (pid == lastid) {
2397 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2399 switch (status->GetStatus()) {
2400 case TGridJobStatus::kWAITING:
2402 case TGridJobStatus::kRUNNING:
2404 case TGridJobStatus::kABORTED:
2405 case TGridJobStatus::kFAIL:
2406 case TGridJobStatus::kUNKNOWN:
2408 case TGridJobStatus::kDONE:
2417 //______________________________________________________________________________
2418 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2420 // Returns true if file is a collection. Functionality duplicated from
2421 // TAlien::Type() because we don't want to directly depend on TAlien.
2423 Error("IsCollection", "No connection to grid");
2426 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2427 if (!res) return kFALSE;
2428 const char* typeStr = res->GetKey(0, "type");
2429 if (!typeStr || !strlen(typeStr)) return kFALSE;
2430 if (!strcmp(typeStr, "collection")) return kTRUE;
2435 //______________________________________________________________________________
2436 Bool_t AliAnalysisAlien::IsSingleOutput() const
2438 // Check if single-ouput option is on.
2439 return (!fOutputSingle.IsNull());
2442 //______________________________________________________________________________
2443 void AliAnalysisAlien::Print(Option_t *) const
2445 // Print current plugin settings.
2446 printf("### AliEn analysis plugin current settings ###\n");
2447 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2448 if (mgr && mgr->IsProofMode()) {
2449 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2450 if (TestBit(AliAnalysisGrid::kTest))
2451 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2452 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2453 if (!fProofDataSet.IsNull())
2454 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2456 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2458 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2459 if (!fROOTVersion.IsNull())
2460 printf("= ROOT version requested________________________ %s\n", fROOTVersion.Data());
2462 printf("= ROOT version requested________________________ default\n");
2463 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2464 if (!fAliRootMode.IsNull())
2465 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2467 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2468 if (fNproofWorkersPerSlave)
2469 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2470 if (TestSpecialBit(kClearPackages))
2471 printf("= ClearPackages requested...\n");
2472 if (fIncludePath.Data())
2473 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2474 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2475 if (fPackages && fPackages->GetEntries()) {
2476 TIter next(fPackages);
2479 while ((obj=next())) list += obj->GetName();
2480 printf("= Par files to be used: ________________________ %s\n", list.Data());
2482 if (TestSpecialBit(kProofConnectGrid))
2483 printf("= Requested PROOF connection to grid\n");
2486 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2487 if (fOverwriteMode) {
2488 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2489 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2491 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2492 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO:Print");
2493 printf("= Production mode:______________________________ %d\n", fProductionMode);
2494 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2495 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2496 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2498 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2499 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2500 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2501 TString basedatadir = fGridDataDir;
2502 TString pattern = fDataPattern;
2504 Int_t ind = pattern.Index(" ");
2506 basedatadir += "/%run%/";
2507 basedatadir += pattern(0, ind);
2508 pattern = pattern(ind+1, pattern.Length());
2510 printf("= Data base directory path requested: __________ %s\n", basedatadir.Data());
2511 printf("= Data search pattern: _________________________ %s\n", pattern.Data());
2512 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2513 if (fRunNumbers.Length())
2514 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2516 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2517 if (!fRunRange[0] && !fRunNumbers.Length()) {
2518 TIter next(fInputFiles);
2521 while ((obj=next())) list += obj->GetName();
2522 printf("= Input files to be processed: _________________ %s\n", list.Data());
2524 if (TestBit(AliAnalysisGrid::kTest))
2525 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2526 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2527 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2528 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2529 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2530 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2531 printf("=====================================================================\n");
2532 printf("= Job price: ___________________________________ %d\n", fPrice);
2533 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2534 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2535 if (fMaxInitFailed>0)
2536 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2537 if (fMasterResubmitThreshold>0)
2538 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2539 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2540 if (fNrunsPerMaster>0)
2541 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2542 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2543 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2544 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2545 if (fArguments.Length())
2546 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2547 if (fExecutableArgs.Length())
2548 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2549 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2550 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2551 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2552 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2554 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2555 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2556 if (fIncludePath.Data())
2557 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2558 if (fCloseSE.Length())
2559 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2560 if (fFriendChainName.Length())
2561 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2562 if (fPackages && fPackages->GetEntries()) {
2563 TIter next(fPackages);
2566 while ((obj=next())) list += obj->GetName();
2567 printf("= Par files to be used: ________________________ %s\n", list.Data());
2571 //______________________________________________________________________________
2572 void AliAnalysisAlien::SetDefaults()
2574 // Set default values for everything. What cannot be filled will be left empty.
2575 if (fGridJDL) delete fGridJDL;
2576 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2577 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2580 fSplitMaxInputFileNumber = 100;
2582 fMasterResubmitThreshold = 0;
2588 fNrunsPerMaster = 1;
2589 fMaxMergeFiles = 100;
2591 fExecutable = "analysis.sh";
2592 fExecutableCommand = "root -b -q -x";
2594 fExecutableArgs = "";
2595 fAnalysisMacro = "myAnalysis.C";
2596 fAnalysisSource = "";
2597 fAdditionalLibs = "";
2601 fAliROOTVersion = "";
2602 fUser = ""; // Your alien user name
2603 fGridWorkingDir = "";
2604 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2605 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2606 fFriendChainName = "";
2607 fGridOutputDir = "output";
2608 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2609 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2610 fInputFormat = "xml-single";
2611 fJDLName = "analysis.jdl";
2612 fJobTag = "Automatically generated analysis JDL";
2613 fMergeExcludes = "";
2616 SetCheckCopy(kTRUE);
2617 SetDefaultOutputs(kTRUE);
2621 //______________________________________________________________________________
2622 void AliAnalysisAlien::SetFriendChainName(const char *name, const char *libnames)
2624 // Set file name for the chain of friends and optionally additional libs to be loaded.
2625 // Libs should be separated by blancs.
2626 fFriendChainName = name;
2627 fFriendChainName.ReplaceAll(",", " ");
2628 fFriendChainName.Strip();
2629 fFriendChainName.ReplaceAll(" ", " ");
2631 fFriendLibs = libnames;
2632 if (fFriendLibs.Length()) {
2633 if(!fFriendLibs.Contains(".so"))
2634 Fatal("SetFriendChainName()", "You should provide explicit library names (with extension)");
2635 fFriendLibs.ReplaceAll(",", " ");
2636 fFriendLibs.Strip();
2637 fFriendLibs.ReplaceAll(" ", " ");
2641 //______________________________________________________________________________
2642 void AliAnalysisAlien::SetRootVersionForProof(const char *version)
2644 // Obsolete method. Use SetROOTVersion instead
2645 Warning("SetRootVersionForProof", "Obsolete. Use SetROOTVersion instead");
2646 if (fROOTVersion.IsNull()) SetROOTVersion(version);
2647 else Error("SetRootVersionForProof", "ROOT version already set to %s", fROOTVersion.Data());
2650 //______________________________________________________________________________
2651 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2653 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2654 // First check if the result is already in the output directory.
2655 if (FileExists(Form("%s/%s",aliendir,filename))) {
2656 printf("Final merged results found. Not merging again.\n");
2659 // Now check the last stage done.
2662 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2665 // Next stage of merging
2667 TString pattern = "*root_archive.zip";
2668 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2669 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2670 if (res) delete res;
2671 // Write standard output to file
2672 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2673 // Count the number of files inside
2675 ifile.open(Form("Stage_%d.xml",stage));
2676 if (!ifile.good()) {
2677 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2682 while (!ifile.eof()) {
2684 if (line.Contains("/event")) nfiles++;
2688 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2691 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2693 // Copy the file in the output directory
2694 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2695 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2696 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2697 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2698 // Check if this is the last stage to be done.
2699 Bool_t laststage = (nfiles<nperchunk);
2700 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2703 printf("### Submiting final merging stage %d\n", stage);
2704 TString finalJDL = jdl;
2705 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2706 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2707 jobId = SubmitSingleJob(query);
2709 printf("### Submiting merging stage %d\n", stage);
2710 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2711 jobId = SubmitSingleJob(query);
2713 if (!jobId) return kFALSE;
2715 if (!fGridJobIDs.IsNull()) fGridJobIDs.Append(" ");
2716 fGridJobIDs.Append(Form("%d", jobId));
2717 if (!fGridStages.IsNull()) fGridStages.Append(" ");
2718 fGridStages.Append(Form("%s_merge_stage%d",
2719 laststage ? "final" : "partial", stage));
2724 //______________________________________________________________________________
2725 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2727 // Loat the analysis manager from a file.
2728 TFile *file = TFile::Open(fname);
2730 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2733 TIter nextkey(file->GetListOfKeys());
2734 AliAnalysisManager *mgr = 0;
2736 while ((key=(TKey*)nextkey())) {
2737 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2738 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2741 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2745 //______________________________________________________________________________
2746 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2748 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2749 if (!gGrid) return 0;
2750 printf("=> %s ------> ",query);
2751 TGridResult *res = gGrid->Command(query);
2753 TString jobId = res->GetKey(0,"jobId");
2755 if (jobId.IsNull()) {
2756 printf("submission failed. Reason:\n");
2759 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2762 Int_t ijobId = jobId.Atoi();
2763 printf(" Job id: '%s' (%d)\n", jobId.Data(), ijobId);
2767 //______________________________________________________________________________
2768 Bool_t AliAnalysisAlien::MergeInfo(const char *output, const char *collection)
2770 // Merges a collection of output files using concatenation.
2771 TString scoll(collection);
2772 if (!scoll.Contains(".xml")) return kFALSE;
2773 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", collection));
2775 ::Error("MergeInfo", "Input XML %s collection empty.", collection);
2778 // Iterate grid collection
2780 Bool_t merged = kFALSE;
2782 while (coll->Next()) {
2783 TString fname = gSystem->DirName(coll->GetTURL());
2786 outtmp = Form("%d_%s", ifile, output);
2787 if (!TFile::Cp(fname, outtmp)) {
2788 ::Error("MergeInfo", "Could not copy %s", fname.Data());
2793 gSystem->Exec(Form("cp %s lastmerged", outtmp.Data()));
2796 gSystem->Exec(Form("cat lastmerged %s > tempmerged", outtmp.Data()));
2797 gSystem->Exec("cp tempmerged lastmerged");
2800 gSystem->Exec(Form("cp lastmerged %s", output));
2801 gSystem->Exec(Form("rm tempmerged lastmerged *_%s", output));
2807 //______________________________________________________________________________
2808 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2810 // Merge given output files from basedir. Basedir can be an alien output directory
2811 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2812 // files in a group (ignored for xml input). Merging can be done in stages:
2813 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2814 // stage=1 : works with an xml of all root_archive.zip in the output directory
2815 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2816 TString outputFile = output;
2818 TString outputChunk;
2819 TString previousChunk = "";
2820 TObjArray *listoffiles = new TObjArray();
2821 // listoffiles->SetOwner();
2822 Int_t countChunk = 0;
2823 Int_t countZero = nmaxmerge;
2824 Bool_t merged = kTRUE;
2825 Bool_t isGrid = kTRUE;
2826 Int_t index = outputFile.Index("@");
2827 if (index > 0) outputFile.Remove(index);
2828 TString inputFile = outputFile;
2829 TString sbasedir = basedir;
2830 if (sbasedir.Contains(".xml")) {
2831 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2832 nmaxmerge = 9999999;
2833 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2835 ::Error("MergeOutput", "Input XML collection empty.");
2838 // Iterate grid collection
2839 while (coll->Next()) {
2840 TString fname = gSystem->DirName(coll->GetTURL());
2843 listoffiles->Add(new TNamed(fname.Data(),""));
2845 } else if (sbasedir.Contains(".txt")) {
2846 // The file having the .txt extension is expected to contain a list of
2847 // folders where the output files will be looked. For alien folders,
2848 // the full folder LFN is expected (starting with alien://)
2849 // Assume lfn's on each line
2854 ::Error("MergeOutput", "File %s cannot be opened. Merging stopped." ,sbasedir.Data());
2860 if (line.IsNull() || line.BeginsWith("#")) continue;
2862 if (!line.Contains("alien:")) isGrid = kFALSE;
2866 listoffiles->Add(new TNamed(line.Data(),""));
2870 ::Error("MergeOutput","Input file %s contains no files to be merged\n", sbasedir.Data());
2875 command = Form("find %s/ *%s", basedir, inputFile.Data());
2876 printf("command: %s\n", command.Data());
2877 TGridResult *res = gGrid->Command(command);
2879 ::Error("MergeOutput","No result for the find command\n");
2885 while ((map=(TMap*)nextmap())) {
2886 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2887 if (!objs || !objs->GetString().Length()) {
2888 // Nothing found - skip this output
2893 listoffiles->Add(new TNamed(objs->GetName(),""));
2897 if (!listoffiles->GetEntries()) {
2898 ::Error("MergeOutput","No result for the find command\n");
2903 TFileMerger *fm = 0;
2904 TIter next0(listoffiles);
2905 TObjArray *listoffilestmp = new TObjArray();
2906 listoffilestmp->SetOwner();
2909 // Keep only the files at upper level
2910 Int_t countChar = 0;
2911 while ((nextfile=next0())) {
2912 snextfile = nextfile->GetName();
2913 Int_t crtCount = snextfile.CountChar('/');
2914 if (nextfile == listoffiles->First()) countChar = crtCount;
2915 if (crtCount < countChar) countChar = crtCount;
2918 while ((nextfile=next0())) {
2919 snextfile = nextfile->GetName();
2920 Int_t crtCount = snextfile.CountChar('/');
2921 if (crtCount > countChar) {
2925 listoffilestmp->Add(nextfile);
2928 listoffiles = listoffilestmp; // Now contains 'good' files
2929 listoffiles->Print();
2930 TIter next(listoffiles);
2931 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2932 outputChunk = outputFile;
2933 outputChunk.ReplaceAll(".root", "_*.root");
2934 // Check for existent temporary merge files
2935 // Check overwrite mode and remove previous partial results if needed
2936 // Preserve old merging functionality for stage 0.
2938 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2940 // Skip as many input files as in a chunk
2941 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2944 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2948 snextfile = nextfile->GetName();
2950 outputChunk = outputFile;
2951 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2953 if (gSystem->AccessPathName(outputChunk)) continue;
2954 // Merged file with chunks up to <countChunk> found
2955 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2956 previousChunk = outputChunk;
2960 countZero = nmaxmerge;
2962 while ((nextfile=next())) {
2963 snextfile = nextfile->GetName();
2964 // Loop 'find' results and get next LFN
2965 if (countZero == nmaxmerge) {
2966 // First file in chunk - create file merger and add previous chunk if any.
2967 fm = new TFileMerger(isGrid);
2968 fm->SetFastMethod(kTRUE);
2969 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2970 outputChunk = outputFile;
2971 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2973 // If last file found, put merged results in the output file
2974 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2975 // Add file to be merged and decrement chunk counter.
2976 fm->AddFile(snextfile);
2978 if (countZero==0 || nextfile == listoffiles->Last()) {
2979 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2980 // Nothing found - skip this output
2981 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2985 fm->OutputFile(outputChunk);
2986 // Merge the outputs, then go to next chunk
2988 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2992 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2993 gSystem->Unlink(previousChunk);
2995 if (nextfile == listoffiles->Last()) break;
2997 countZero = nmaxmerge;
2998 previousChunk = outputChunk;
3005 // Merging stage different than 0.
3006 // Move to the begining of the requested chunk.
3007 fm = new TFileMerger(isGrid);
3008 fm->SetFastMethod(kTRUE);
3009 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
3011 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
3012 // Nothing found - skip this output
3013 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
3017 fm->OutputFile(outputFile);
3018 // Merge the outputs
3020 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
3024 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
3030 //______________________________________________________________________________
3031 Bool_t AliAnalysisAlien::MergeOutputs()
3033 // Merge analysis outputs existing in the AliEn space.
3034 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
3035 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3037 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
3041 if (!TestBit(AliAnalysisGrid::kMerge)) {
3042 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
3045 if (fProductionMode) {
3046 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
3049 Info("MergeOutputs", "Submitting merging JDL");
3050 if (!SubmitMerging()) return kFALSE;
3051 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
3052 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
3055 // Get the output path
3056 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3057 if (!DirectoryExists(fGridOutputDir)) {
3058 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
3061 if (!fOutputFiles.Length()) {
3062 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3065 // Check if fast read option was requested
3066 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
3067 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
3068 if (fFastReadOption) {
3069 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
3070 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3071 gEnv->SetValue("XNet.ConnectTimeout",50);
3072 gEnv->SetValue("XNet.RequestTimeout",50);
3073 gEnv->SetValue("XNet.MaxRedirectCount",2);
3074 gEnv->SetValue("XNet.ReconnectTimeout",50);
3075 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
3077 // Make sure we change the temporary directory
3078 gSystem->Setenv("TMPDIR", gSystem->pwd());
3079 // Set temporary compilation directory to current one
3080 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
3081 TObjArray *list = fOutputFiles.Tokenize(",");
3085 Bool_t merged = kTRUE;
3086 while((str=(TObjString*)next())) {
3087 outputFile = str->GetString();
3088 Int_t index = outputFile.Index("@");
3089 if (index > 0) outputFile.Remove(index);
3090 TString outputChunk = outputFile;
3091 outputChunk.ReplaceAll(".root", "_*.root");
3092 // Skip already merged outputs
3093 if (!gSystem->AccessPathName(outputFile)) {
3094 if (fOverwriteMode) {
3095 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
3096 gSystem->Unlink(outputFile);
3097 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
3098 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
3099 outputChunk.Data());
3100 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
3103 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
3107 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
3108 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
3109 outputChunk.Data());
3110 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
3113 if (fMergeExcludes.Contains(outputFile.Data()) ||
3114 fRegisterExcludes.Contains(outputFile.Data())) continue;
3115 // Perform a 'find' command in the output directory, looking for registered outputs
3116 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
3118 Error("MergeOutputs", "Terminate() will NOT be executed");
3122 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
3123 if (fileOpened) fileOpened->Close();
3129 //______________________________________________________________________________
3130 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
3132 // Use the output files connected to output containers from the analysis manager
3133 // rather than the files defined by SetOutputFiles
3134 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
3135 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
3136 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
3139 //______________________________________________________________________________
3140 void AliAnalysisAlien::SetOutputFiles(const char *list)
3142 // Manually set the output files list.
3143 // Removes duplicates. Not allowed if default outputs are not disabled.
3144 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3145 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
3148 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
3150 TString slist = list;
3151 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
3152 TObjArray *arr = slist.Tokenize(" ");
3156 while ((os=(TObjString*)next())) {
3157 sout = os->GetString();
3158 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
3159 if (fOutputFiles.Contains(sout)) continue;
3160 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3161 fOutputFiles += sout;
3166 //______________________________________________________________________________
3167 void AliAnalysisAlien::SetOutputArchive(const char *list)
3169 // Manually set the output archive list. Free text - you are on your own...
3170 // Not allowed if default outputs are not disabled.
3171 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3172 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
3175 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
3176 fOutputArchive = list;
3179 //______________________________________________________________________________
3180 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
3182 // Setting a prefered output SE is not allowed anymore.
3183 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
3186 //______________________________________________________________________________
3187 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
3189 // Set some PROOF special parameter.
3190 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
3192 TObject *old = pair->Key();
3193 TObject *val = pair->Value();
3194 fProofParam.Remove(old);
3198 fProofParam.Add(new TObjString(pname), new TObjString(value));
3201 //______________________________________________________________________________
3202 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
3204 // Returns a special PROOF parameter.
3205 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
3206 if (!pair) return 0;
3207 return pair->Value()->GetName();
3210 //______________________________________________________________________________
3211 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
3213 // Start remote grid analysis.
3214 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3215 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
3216 if (!mgr || !mgr->IsInitialized()) {
3217 Error("StartAnalysis", "You need an initialized analysis manager for this");
3220 // Are we in PROOF mode ?
3221 if (mgr->IsProofMode()) {
3222 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
3223 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3224 if (fProofCluster.IsNull()) {
3225 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3228 if (fProofDataSet.IsNull() && !testMode) {
3229 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3232 // Set the needed environment
3233 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3234 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3235 if (fProofReset && !testMode) {
3236 if (fProofReset==1) {
3237 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3238 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3240 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3241 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3243 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3248 // Check if there is an old active session
3249 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3251 Error("StartAnalysis","You have to reset your old session first\n");
3255 // Do we need to change the ROOT version ? The success of this cannot be checked.
3256 if (!fROOTVersion.IsNull() && !testMode) {
3257 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"VO_ALICE@ROOT::%s\");",
3258 fProofCluster.Data(), fROOTVersion.Data()));
3260 // Connect to PROOF and check the status
3263 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3264 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3266 if (!sworkers.IsNull())
3267 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3269 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3271 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3273 Error("StartAnalysis", "Could not start PROOF in test mode");
3278 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3281 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3282 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3283 // Set proof special parameters if any
3284 TIter nextpp(&fProofParam);
3285 TObject *proofparam;
3286 while ((proofparam=nextpp())) {
3287 TString svalue = GetProofParameter(proofparam->GetName());
3288 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3290 // Is dataset existing ?
3292 TString dataset = fProofDataSet;
3293 Int_t index = dataset.Index("#");
3294 if (index>=0) dataset.Remove(index);
3295 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3296 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3299 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3301 // Is ClearPackages() needed ?
3302 if (TestSpecialBit(kClearPackages)) {
3303 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3304 gROOT->ProcessLine("gProof->ClearPackages();");
3306 // Is a given aliroot mode requested ?
3309 if (!fAliRootMode.IsNull()) {
3310 TString alirootMode = fAliRootMode;
3311 if (alirootMode == "default") alirootMode = "";
3312 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3313 optionsList.SetOwner();
3314 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3315 // Check the additional libs to be loaded
3317 Bool_t parMode = kFALSE;
3318 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3319 // Parse the extra libs for .so
3320 if (fAdditionalLibs.Length()) {
3321 TString additionalLibs = fAdditionalLibs;
3322 additionalLibs.Strip();
3323 if (additionalLibs.Length() && fFriendLibs.Length())
3324 additionalLibs += " ";
3325 additionalLibs += fFriendLibs;
3326 TObjArray *list = additionalLibs.Tokenize(" ");
3329 while((str=(TObjString*)next())) {
3330 if (str->GetString().Contains(".so")) {
3332 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());
3335 TString stmp = str->GetName();
3336 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3337 stmp.ReplaceAll(".so","");
3338 if (!extraLibs.IsNull()) extraLibs += ":";
3342 if (str->GetString().Contains(".par")) {
3343 // The first par file found in the list will not allow any further .so
3345 if (!parLibs.IsNull()) parLibs += ":";
3346 parLibs += str->GetName();
3350 if (list) delete list;
3352 if (!extraLibs.IsNull()) {
3353 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3354 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3356 // Check extra includes
3357 if (!fIncludePath.IsNull()) {
3358 TString includePath = fIncludePath;
3359 includePath.ReplaceAll(" ",":");
3360 includePath.ReplaceAll("$ALICE_ROOT/","");
3361 includePath.ReplaceAll("${ALICE_ROOT}/","");
3362 includePath.ReplaceAll("-I","");
3363 includePath.Remove(TString::kTrailing, ':');
3364 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3365 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3367 // Check if connection to grid is requested
3368 if (TestSpecialBit(kProofConnectGrid))
3369 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3370 // Enable AliRoot par
3372 // Enable proof lite package
3373 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3374 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3375 TNamed *obj = (TNamed*)optionsList.At(i);
3376 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3378 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3379 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3380 Info("StartAnalysis", "AliRootProofLite enabled");
3382 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3386 if ( ! fAliROOTVersion.IsNull() ) {
3387 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3388 fAliROOTVersion.Data(), &optionsList))) {
3389 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3394 // Enable first par files from fAdditionalLibs
3395 if (!parLibs.IsNull()) {
3396 TObjArray *list = parLibs.Tokenize(":");
3398 TObjString *package;
3399 while((package=(TObjString*)next())) {
3400 TString spkg = package->GetName();
3401 spkg.ReplaceAll(".par", "");
3402 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3403 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3404 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3405 if (gROOT->ProcessLine(enablePackage)) {
3406 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3410 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3414 if (list) delete list;
3417 if (fAdditionalLibs.Contains(".so") && !testMode) {
3418 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3419 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3423 // Enable par files if requested
3424 if (fPackages && fPackages->GetEntries()) {
3425 TIter next(fPackages);
3427 while ((package=next())) {
3428 // Skip packages already enabled
3429 if (parLibs.Contains(package->GetName())) continue;
3430 TString spkg = package->GetName();
3431 spkg.ReplaceAll(".par", "");
3432 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3433 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3434 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3435 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3439 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3444 // Do we need to load analysis source files ?
3445 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3446 if (fAnalysisSource.Length()) {
3447 TObjArray *list = fAnalysisSource.Tokenize(" ");
3450 while((str=(TObjString*)next())) {
3451 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3453 if (list) delete list;
3456 // Register dataset to proof lite.
3457 if (fFileForTestMode.IsNull()) {
3458 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3461 if (gSystem->AccessPathName(fFileForTestMode)) {
3462 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3465 TFileCollection *coll = new TFileCollection();
3466 coll->AddFromFile(fFileForTestMode);
3467 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3468 gROOT->ProcessLine("gProof->ShowDataSets()");
3473 // Check if output files have to be taken from the analysis manager
3474 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3475 // Add output files and AOD files
3476 fOutputFiles = GetListOfFiles("outaod");
3477 // Add extra files registered to the analysis manager
3478 TString extra = GetListOfFiles("ext");
3479 if (!extra.IsNull()) {
3480 extra.ReplaceAll(".root", "*.root");
3481 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3482 fOutputFiles += extra;
3484 // Compose the output archive.
3485 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3486 if (mgr->IsCollectThroughput())
3487 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d %s@disk=%d",fOutputFiles.Data(),fNreplicas, mgr->GetFileInfoLog(),fNreplicas);
3489 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3491 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3492 if (TestBit(AliAnalysisGrid::kOffline)) {
3493 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3494 \n there nor any job run. You can revise the JDL and analysis \
3495 \n macro then run the same in \"submit\" mode.");
3496 } else if (TestBit(AliAnalysisGrid::kTest)) {
3497 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3499 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3500 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3501 \n space and job submitted.");
3502 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3503 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3504 if (fMergeViaJDL) CheckInputData();
3507 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3512 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3515 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3516 if (!CheckInputData()) {
3517 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3520 if (!CreateDataset(fDataPattern)) {
3522 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3523 if (fRunNumbers.Length()) serror = "run numbers";
3524 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3525 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3526 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3529 WriteAnalysisFile();
3530 WriteAnalysisMacro();
3532 WriteValidationScript();
3534 WriteMergingMacro();
3535 WriteMergeExecutable();
3536 WriteValidationScript(kTRUE);
3538 if (!CreateJDL()) return kFALSE;
3539 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3541 // Locally testing the analysis
3542 Info("StartAnalysis", "\n_______________________________________________________________________ \
3543 \n Running analysis script in a daughter shell as on a worker node \
3544 \n_______________________________________________________________________");
3545 TObjArray *list = fOutputFiles.Tokenize(",");
3549 while((str=(TObjString*)next())) {
3550 outputFile = str->GetString();
3551 Int_t index = outputFile.Index("@");
3552 if (index > 0) outputFile.Remove(index);
3553 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3556 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3557 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3558 // gSystem->Exec("cat stdout");
3561 // Check if submitting is managed by LPM manager
3562 if (fProductionMode) {
3563 //TString prodfile = fJDLName;
3564 //prodfile.ReplaceAll(".jdl", ".prod");
3565 //WriteProductionFile(prodfile);
3566 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3569 // Submit AliEn job(s)
3570 gGrid->Cd(fGridOutputDir);
3575 if (!fRunNumbers.Length() && !fRunRange[0]) {
3576 // Submit a given xml or a set of runs
3577 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3578 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3580 const char *cjobId = res->GetKey(0,"jobId");
3584 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3587 Info("StartAnalysis", "\n_______________________________________________________________________ \
3588 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3589 \n_______________________________________________________________________",
3590 fJDLName.Data(), cjobId);
3593 if (!fGridJobIDs.IsNull()) fGridJobIDs.Append(" ");
3594 fGridJobIDs.Append(jobID);
3595 if (!fGridStages.IsNull()) fGridStages.Append(" ");
3596 fGridStages.Append("full");
3601 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3605 // Submit for a range of enumeration of runs.
3606 if (!Submit()) return kFALSE;
3607 jobID = fGridJobIDs;
3611 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3612 \n You may exit at any time and terminate the job later using the option <terminate> \
3613 \n ##################################################################################", jobID.Data());
3614 gSystem->Exec("aliensh");
3616 Info("StartAnalysis", "\n#### SUBMITTED JOB %s TO ALIEN QUEUE #### \
3617 \n Remember to terminate the job later using the option <terminate> \
3618 \n ##################################################################################", jobID.Data());
3623 //______________________________________________________________________________
3624 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3626 // Get a comma-separated list of output files of the requested type.
3627 // Type can be (case unsensitive):
3628 // aod - list of aod files (std, extensions and filters)
3629 // out - list of output files connected to containers (but not aod's or extras)
3630 // ext - list of extra files registered to the manager
3631 // ter - list of files produced in terminate
3632 static TString files;
3634 TString stype = type;
3636 TString aodfiles, extra;
3637 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3639 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3640 return files.Data();
3642 if (mgr->GetOutputEventHandler()) {
3643 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3644 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3645 if (!extraaod.IsNull()) {
3647 aodfiles += extraaod;
3650 if (stype.Contains("aod")) {
3652 if (stype == "aod") return files.Data();
3654 // Add output files that are not in the list of AOD files
3655 TString outputfiles = "";
3656 TIter next(mgr->GetOutputs());
3657 AliAnalysisDataContainer *output;
3658 const char *filename = 0;
3659 while ((output=(AliAnalysisDataContainer*)next())) {
3660 filename = output->GetFileName();
3661 if (!(strcmp(filename, "default"))) continue;
3662 if (outputfiles.Contains(filename)) continue;
3663 if (aodfiles.Contains(filename)) continue;
3664 if (!outputfiles.IsNull()) outputfiles += ",";
3665 outputfiles += filename;
3667 if (stype.Contains("out")) {
3668 if (!files.IsNull()) files += ",";
3669 files += outputfiles;
3670 if (stype == "out") return files.Data();
3672 // Add extra files registered to the analysis manager
3674 extra = mgr->GetExtraFiles();
3675 if (!extra.IsNull()) {
3677 extra.ReplaceAll(" ", ",");
3678 TObjArray *fextra = extra.Tokenize(",");
3679 TIter nextx(fextra);
3681 while ((obj=nextx())) {
3682 if (aodfiles.Contains(obj->GetName())) continue;
3683 if (outputfiles.Contains(obj->GetName())) continue;
3684 if (sextra.Contains(obj->GetName())) continue;
3685 if (!sextra.IsNull()) sextra += ",";
3686 sextra += obj->GetName();
3689 if (stype.Contains("ext")) {
3690 if (!files.IsNull()) files += ",";
3694 if (stype == "ext") return files.Data();
3696 if (!fTerminateFiles.IsNull()) {
3697 fTerminateFiles.Strip();
3698 fTerminateFiles.ReplaceAll(" ",",");
3699 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3700 TIter nextx(fextra);
3702 while ((obj=nextx())) {
3703 if (aodfiles.Contains(obj->GetName())) continue;
3704 if (outputfiles.Contains(obj->GetName())) continue;
3705 if (termfiles.Contains(obj->GetName())) continue;
3706 if (sextra.Contains(obj->GetName())) continue;
3707 if (!termfiles.IsNull()) termfiles += ",";
3708 termfiles += obj->GetName();
3712 if (stype.Contains("ter")) {
3713 if (!files.IsNull() && !termfiles.IsNull()) {
3718 return files.Data();
3721 //______________________________________________________________________________
3722 Bool_t AliAnalysisAlien::Submit()
3724 // Submit all master jobs.
3725 Int_t nmasterjobs = fInputFiles->GetEntries();
3726 Long_t tshoot = gSystem->Now();
3727 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3728 while (fNsubmitted < nmasterjobs) {
3729 Long_t now = gSystem->Now();
3730 if ((now-tshoot)>30000) {
3732 if (!SubmitNext()) return kFALSE;
3738 //______________________________________________________________________________
3739 Bool_t AliAnalysisAlien::SubmitMerging()
3741 // Submit all merging jobs.
3742 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3743 gGrid->Cd(fGridOutputDir);
3744 TString mergeJDLName = fExecutable;
3745 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3747 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3750 Int_t ntosubmit = fInputFiles->GetEntries();
3751 for (Int_t i=0; i<ntosubmit; i++) {
3752 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3753 runOutDir.ReplaceAll(".xml", "");
3754 if (fOutputToRunNo) {
3755 // The output directory is the run number
3756 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3757 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3759 if (!fRunNumbers.Length() && !fRunRange[0]) {
3760 // The output directory is the grid outdir
3761 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3762 runOutDir = fGridOutputDir;
3764 // The output directory is the master number in 3 digits format
3765 printf("### Submitting merging job for master <%03d>\n", i);
3766 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3769 // Check now the number of merging stages.
3770 TObjArray *list = fOutputFiles.Tokenize(",");
3774 while((str=(TObjString*)next())) {
3775 outputFile = str->GetString();
3776 Int_t index = outputFile.Index("@");
3777 if (index > 0) outputFile.Remove(index);
3778 if (!fMergeExcludes.Contains(outputFile) &&
3779 !fRegisterExcludes.Contains(outputFile)) break;
3782 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3783 if (!done && (i==ntosubmit-1)) return kFALSE;
3784 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3786 if (!ntosubmit) return kTRUE;
3788 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3789 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3790 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3791 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3792 \n ################################################################################################################");
3793 gSystem->Exec("aliensh");
3795 Info("StartAnalysis", "\n #### STARTED MERGING JOBS FOR YOU #### \
3796 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL') \
3797 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3798 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3799 \n ################################################################################################################");
3804 //______________________________________________________________________________
3805 Bool_t AliAnalysisAlien::SubmitNext()
3807 // Submit next bunch of master jobs if the queue is free. The first master job is
3808 // submitted right away, while the next will not be unless the previous was split.
3809 // The plugin will not submit new master jobs if there are more that 500 jobs in
3811 static Bool_t iscalled = kFALSE;
3812 static Int_t firstmaster = 0;
3813 static Int_t lastmaster = 0;
3814 static Int_t npermaster = 0;
3815 if (iscalled) return kTRUE;
3817 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3818 Int_t ntosubmit = 0;
3821 Int_t nmasterjobs = fInputFiles->GetEntries();
3824 if (!IsUseSubmitPolicy()) {
3826 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3827 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3828 ntosubmit = nmasterjobs;
3831 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3832 printf("=== master %d: %s\n", lastmaster, status.Data());
3833 // If last master not split, just return
3834 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3835 // No more than 100 waiting jobs
3836 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3837 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3838 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3839 if (!ntosubmit) ntosubmit = 1;
3840 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3841 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3843 for (Int_t i=0; i<ntosubmit; i++) {
3844 // Submit for a range of enumeration of runs.
3845 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3847 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3848 runOutDir.ReplaceAll(".xml", "");
3850 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3852 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3853 printf("********* %s\n",query.Data());
3854 res = gGrid->Command(query);
3856 TString cjobId1 = res->GetKey(0,"jobId");
3857 if (!cjobId1.Length()) {
3861 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3864 Info("StartAnalysis", "\n_______________________________________________________________________ \
3865 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3866 \n_______________________________________________________________________",
3867 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3868 if (!fGridJobIDs.IsNull()) fGridJobIDs.Append(" ");
3869 fGridJobIDs.Append(cjobId1);
3870 if (!fGridStages.IsNull()) fGridStages.Append(" ");
3871 fGridStages.Append("full");
3874 lastmaster = cjobId1.Atoi();
3875 if (!firstmaster) firstmaster = lastmaster;
3880 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3888 //______________________________________________________________________________
3889 void AliAnalysisAlien::WriteAnalysisFile()
3891 // Write current analysis manager into the file <analysisFile>
3892 TString analysisFile = fExecutable;
3893 analysisFile.ReplaceAll(".sh", ".root");
3894 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3895 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3896 if (!mgr || !mgr->IsInitialized()) {
3897 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3900 // Check analysis type
3902 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3903 handler = (TObject*)mgr->GetInputEventHandler();
3905 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3906 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3907 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3908 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3910 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3911 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3914 TDirectory *cdir = gDirectory;
3915 TFile *file = TFile::Open(analysisFile, "RECREATE");
3917 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3918 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3919 // Unless merging makes no sense
3920 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3923 // Enable termination for local jobs
3924 mgr->SetSkipTerminate(kFALSE);
3926 if (cdir) cdir->cd();
3927 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3929 Bool_t copy = kTRUE;
3930 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3933 TString workdir = gGrid->GetHomeDirectory();
3934 workdir += fGridWorkingDir;
3935 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3936 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3937 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3938 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3942 //______________________________________________________________________________
3943 void AliAnalysisAlien::WriteAnalysisMacro()
3945 // Write the analysis macro that will steer the analysis in grid mode.
3946 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3948 out.open(fAnalysisMacro.Data(), ios::out);
3950 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3953 Bool_t hasSTEERBase = kFALSE;
3954 Bool_t hasESD = kFALSE;
3955 Bool_t hasAOD = kFALSE;
3956 Bool_t hasANALYSIS = kFALSE;
3957 Bool_t hasOADB = kFALSE;
3958 Bool_t hasANALYSISalice = kFALSE;
3959 Bool_t hasCORRFW = kFALSE;
3960 TString func = fAnalysisMacro;
3961 TString type = "ESD";
3962 TString comment = "// Analysis using ";
3963 if (IsUseMCchain()) {
3967 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3968 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3973 if (type!="AOD" && fFriendChainName!="") {
3974 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3977 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3978 else comment += " data";
3979 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3980 func.ReplaceAll(".C", "");
3981 out << "void " << func.Data() << "()" << endl;
3983 out << comment.Data() << endl;
3984 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3985 out << " TStopwatch timer;" << endl;
3986 out << " timer.Start();" << endl << endl;
3987 // Change temp directory to current one
3988 if (!IsLocalTest()) {
3989 out << "// connect to AliEn and make the chain" << endl;
3990 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3992 out << "// Set temporary merging directory to current one" << endl;
3993 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3994 out << "// Set temporary compilation directory to current one" << endl;
3995 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3996 // Reset existing include path
3997 out << "// Reset existing include path and add current directory first in the search" << endl;
3998 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3999 if (!fExecutableCommand.Contains("aliroot")) {
4000 out << "// load base root libraries" << endl;
4001 out << " gSystem->Load(\"libTree\");" << endl;
4002 out << " gSystem->Load(\"libGeom\");" << endl;
4003 out << " gSystem->Load(\"libVMC\");" << endl;
4004 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4005 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4007 if (fAdditionalRootLibs.Length()) {
4008 // in principle libtree /lib geom libvmc etc. can go into this list, too
4009 out << "// Add aditional libraries" << endl;
4010 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4013 while((str=(TObjString*)next())) {
4014 if (str->GetString().Contains(".so"))
4015 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4017 if (list) delete list;
4019 out << "// Load analysis framework libraries" << endl;
4020 TString setupPar = "AliAnalysisAlien::SetupPar";
4022 if (!fExecutableCommand.Contains("aliroot")) {
4023 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4024 out << " gSystem->Load(\"libESD\");" << endl;
4025 out << " gSystem->Load(\"libAOD\");" << endl;
4027 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4028 out << " gSystem->Load(\"libOADB\");" << endl;
4029 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4030 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4032 TIter next(fPackages);
4035 while ((obj=next())) {
4036 pkgname = obj->GetName();
4037 if (pkgname == "STEERBase" ||
4038 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4039 if (pkgname == "ESD" ||
4040 pkgname == "ESD.par") hasESD = kTRUE;
4041 if (pkgname == "AOD" ||
4042 pkgname == "AOD.par") hasAOD = kTRUE;
4043 if (pkgname == "ANALYSIS" ||
4044 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4045 if (pkgname == "OADB" ||
4046 pkgname == "OADB.par") hasOADB = kTRUE;
4047 if (pkgname == "ANALYSISalice" ||
4048 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4049 if (pkgname == "CORRFW" ||
4050 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4052 if (hasANALYSISalice) setupPar = "SetupPar";
4053 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4054 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4055 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4056 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4057 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4058 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4059 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4060 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4061 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4062 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4063 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4064 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4065 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4066 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4067 out << "// Compile other par packages" << endl;
4069 while ((obj=next())) {
4070 pkgname = obj->GetName();
4071 if (pkgname == "STEERBase" ||
4072 pkgname == "STEERBase.par" ||
4074 pkgname == "ESD.par" ||
4076 pkgname == "AOD.par" ||
4077 pkgname == "ANALYSIS" ||
4078 pkgname == "ANALYSIS.par" ||
4079 pkgname == "OADB" ||
4080 pkgname == "OADB.par" ||
4081 pkgname == "ANALYSISalice" ||
4082 pkgname == "ANALYSISalice.par" ||
4083 pkgname == "CORRFW" ||
4084 pkgname == "CORRFW.par") continue;
4085 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4088 out << "// include path" << endl;
4089 // Get the include path from the interpreter and remove entries pointing to AliRoot
4090 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4091 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4092 out << " TIter nextpath(listpaths);" << endl;
4093 out << " TObjString *pname;" << endl;
4094 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4095 out << " TString current = pname->GetName();" << endl;
4096 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4097 out << " gSystem->AddIncludePath(current);" << endl;
4098 out << " }" << endl;
4099 out << " if (listpaths) delete listpaths;" << endl;
4100 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4101 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4102 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4103 if (fAdditionalLibs.Length()) {
4104 out << "// Add aditional AliRoot libraries" << endl;
4105 TString additionalLibs = fAdditionalLibs;
4106 additionalLibs.Strip();
4107 if (additionalLibs.Length() && fFriendLibs.Length())
4108 additionalLibs += " ";
4109 additionalLibs += fFriendLibs;
4110 TObjArray *list = additionalLibs.Tokenize(" ");
4113 while((str=(TObjString*)next())) {
4114 if (str->GetString().Contains(".so"))
4115 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4116 if (str->GetString().Contains(".par"))
4117 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
4119 if (list) delete list;
4122 out << "// analysis source to be compiled at runtime (if any)" << endl;
4123 if (fAnalysisSource.Length()) {
4124 TObjArray *list = fAnalysisSource.Tokenize(" ");
4127 while((str=(TObjString*)next())) {
4128 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4130 if (list) delete list;
4133 // out << " printf(\"Currently load libraries:\\n\");" << endl;
4134 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
4135 if (fFastReadOption) {
4136 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 !!! \
4137 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
4138 out << "// fast xrootd reading enabled" << endl;
4139 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4140 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4141 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4142 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4143 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4144 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4146 out << "// read the analysis manager from file" << endl;
4147 TString analysisFile = fExecutable;
4148 analysisFile.ReplaceAll(".sh", ".root");
4149 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4150 << analysisFile << "\");" << endl;
4151 out << " if (!mgr) return;" << endl;
4152 if (IsLocalTest()) {
4153 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
4154 out << " plugin->SetRunMode(\"test\");" << endl;
4155 if (fFileForTestMode.IsNull())
4156 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
4158 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
4159 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
4160 if (!fFriendChainName.IsNull())
4161 out << " plugin->SetFriendChainName(\"" << fFriendChainName << "\",\"" << fFriendLibs << "\");" << endl;
4163 out << " plugin->SetUseMCchain();" << endl;
4164 out << " mgr->SetGridHandler(plugin);" << endl;
4165 if (AliAnalysisManager::GetAnalysisManager()) {
4166 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
4167 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
4169 out << " mgr->SetDebugLevel(10);" << endl;
4170 out << " mgr->SetNSysInfo(100);" << endl;
4173 out << " mgr->PrintStatus();" << endl;
4174 if (AliAnalysisManager::GetAnalysisManager()) {
4175 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4176 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4178 if (TestBit(AliAnalysisGrid::kTest))
4179 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4181 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4184 if (!IsLocalTest()) {
4185 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
4186 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
4188 out << " mgr->StartAnalysis(\"localfile\");" << endl;
4190 out << " timer.Stop();" << endl;
4191 out << " timer.Print();" << endl;
4192 out << "}" << endl << endl;
4193 if (!IsLocalTest()) {
4194 out <<"//________________________________________________________________________________" << endl;
4195 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
4197 out << "// Create a chain using url's from xml file" << endl;
4198 out << " TString filename;" << endl;
4199 out << " Int_t run = 0;" << endl;
4200 if (IsUseMCchain()) {
4201 out << " TString treename = \"TE\";" << endl;
4203 if (!fTreeName.IsNull()) {
4204 out << " TString treename = \"" << fTreeName << "\";" << endl;
4206 out << " TString treename = type;" << endl;
4207 out << " treename.ToLower();" << endl;
4208 out << " treename += \"Tree\";" << endl;
4211 out << " printf(\"***************************************\\n\");" << endl;
4212 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
4213 out << " printf(\"***************************************\\n\");" << endl;
4214 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
4215 out << " if (!coll) {" << endl;
4216 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
4217 out << " return NULL;" << endl;
4218 out << " }" << endl;
4219 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
4220 out << " TChain *chain = new TChain(treename);" << endl;
4221 if(!fFriendChainName.IsNull()) {
4222 out << " TList *friends = new TList();" << endl;
4223 out << " TIter nextfriend(friends);" << endl;
4224 out << " TChain *cfriend = 0;" << endl;
4225 TObjArray *list = fFriendChainName.Tokenize(" ");
4228 while((str=(TObjString*)next())) {
4229 out << " cfriend = new TChain(treename, \"" << str->GetName() << "\");" << endl;
4230 out << " friends->Add(cfriend);" << endl;
4231 out << " chain->AddFriend(cfriend);" << endl;
4234 // out << " TChain *chainFriend = new TChain(treename);" << endl;
4236 out << " coll->Reset();" << endl;
4237 out << " while (coll->Next()) {" << endl;
4238 out << " filename = coll->GetTURL("");" << endl;
4239 out << " if (mgr) {" << endl;
4240 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
4241 out << " if (nrun && nrun != run) {" << endl;
4242 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
4243 out << " mgr->SetRunFromPath(nrun);" << endl;
4244 out << " run = nrun;" << endl;
4245 out << " }" << endl;
4246 out << " }" << endl;
4247 out << " chain->Add(filename);" << endl;
4248 if(!fFriendChainName.IsNull()) {
4249 out << " TString bpath=coll->GetTURL(\"\");" << endl;
4250 out << " if (bpath.Index(\"#\") > -1) bpath.Remove(bpath.Index(\"#\"));" << endl;
4251 out << " bpath = gSystem->DirName(bpath);" << endl;
4252 out << " bpath += \"/\";" << endl;
4253 out << " TString fileFriend;" << endl;
4254 out << " nextfriend.Reset();" << endl;
4255 out << " while ((cfriend=(TChain*)nextfriend())) {" << endl;
4256 out << " fileFriend = bpath;" << endl;
4257 out << " fileFriend += cfriend->GetTitle();" << endl;
4258 out << " TFile *file = TFile::Open(fileFriend);" << endl;
4259 out << " if (file) {" << endl;
4260 out << " file->Close();" << endl;
4261 out << " cfriend->Add(fileFriend.Data());" << endl;
4262 out << " } else {" << endl;
4263 out << " ::Fatal(\"CreateChain\", \"Cannot open friend file: %s\", fileFriend.Data());" << endl;
4264 out << " return 0;" << endl;
4265 out << " }" << endl;
4266 out << " }" << endl;
4268 out << " }" << endl;
4269 out << " if (!chain->GetNtrees()) {" << endl;
4270 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
4271 out << " return NULL;" << endl;
4272 out << " }" << endl;
4273 out << " return chain;" << endl;
4274 out << "}" << endl << endl;
4276 if (hasANALYSISalice) {
4277 out <<"//________________________________________________________________________________" << endl;
4278 out << "Bool_t SetupPar(const char *package) {" << endl;
4279 out << "// Compile the package and set it up." << endl;
4280 out << " TString pkgdir = package;" << endl;
4281 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4282 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4283 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4284 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4285 out << " // Check for BUILD.sh and execute" << endl;
4286 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4287 out << " printf(\"*******************************\\n\");" << endl;
4288 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4289 out << " printf(\"*******************************\\n\");" << endl;
4290 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4291 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4292 out << " gSystem->ChangeDirectory(cdir);" << endl;
4293 out << " return kFALSE;" << endl;
4294 out << " }" << endl;
4295 out << " } else {" << endl;
4296 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4297 out << " gSystem->ChangeDirectory(cdir);" << endl;
4298 out << " return kFALSE;" << endl;
4299 out << " }" << endl;
4300 out << " // Check for SETUP.C and execute" << endl;
4301 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4302 out << " printf(\"*******************************\\n\");" << endl;
4303 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4304 out << " printf(\"*******************************\\n\");" << endl;
4305 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4306 out << " } else {" << endl;
4307 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4308 out << " gSystem->ChangeDirectory(cdir);" << endl;
4309 out << " return kFALSE;" << endl;
4310 out << " }" << endl;
4311 out << " // Restore original workdir" << endl;
4312 out << " gSystem->ChangeDirectory(cdir);" << endl;
4313 out << " return kTRUE;" << endl;
4316 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4318 Bool_t copy = kTRUE;
4319 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4322 TString workdir = gGrid->GetHomeDirectory();
4323 workdir += fGridWorkingDir;
4324 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4325 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4326 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4327 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4328 Form("alien://%s/%s", workdir.Data(),
4329 fAnalysisMacro.Data()))) Fatal("","Terminating");
4333 //______________________________________________________________________________
4334 void AliAnalysisAlien::WriteMergingMacro()
4336 // Write a macro to merge the outputs per master job.
4337 if (!fMergeViaJDL) return;
4338 if (!fOutputFiles.Length()) {
4339 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4342 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
4343 TString mergingMacro = fExecutable;
4344 mergingMacro.ReplaceAll(".sh","_merge.C");
4345 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4346 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4348 out.open(mergingMacro.Data(), ios::out);
4350 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4353 Bool_t hasSTEERBase = kFALSE;
4354 Bool_t hasESD = kFALSE;
4355 Bool_t hasAOD = kFALSE;
4356 Bool_t hasANALYSIS = kFALSE;
4357 Bool_t hasOADB = kFALSE;
4358 Bool_t hasANALYSISalice = kFALSE;
4359 Bool_t hasCORRFW = kFALSE;
4360 TString func = mergingMacro;
4362 func.ReplaceAll(".C", "");
4363 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4365 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4366 out << " TStopwatch timer;" << endl;
4367 out << " timer.Start();" << endl << endl;
4368 // Reset existing include path
4369 out << "// Reset existing include path and add current directory first in the search" << endl;
4370 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4371 if (!fExecutableCommand.Contains("aliroot")) {
4372 out << "// load base root libraries" << endl;
4373 out << " gSystem->Load(\"libTree\");" << endl;
4374 out << " gSystem->Load(\"libGeom\");" << endl;
4375 out << " gSystem->Load(\"libVMC\");" << endl;
4376 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4377 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4379 if (fAdditionalRootLibs.Length()) {
4380 // in principle libtree /lib geom libvmc etc. can go into this list, too
4381 out << "// Add aditional libraries" << endl;
4382 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4385 while((str=(TObjString*)next())) {
4386 if (str->GetString().Contains(".so"))
4387 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4389 if (list) delete list;
4391 out << "// Load analysis framework libraries" << endl;
4393 if (!fExecutableCommand.Contains("aliroot")) {
4394 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4395 out << " gSystem->Load(\"libESD\");" << endl;
4396 out << " gSystem->Load(\"libAOD\");" << endl;
4398 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4399 out << " gSystem->Load(\"libOADB\");" << endl;
4400 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4401 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4403 TIter next(fPackages);
4406 TString setupPar = "AliAnalysisAlien::SetupPar";
4407 while ((obj=next())) {
4408 pkgname = obj->GetName();
4409 if (pkgname == "STEERBase" ||
4410 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4411 if (pkgname == "ESD" ||
4412 pkgname == "ESD.par") hasESD = kTRUE;
4413 if (pkgname == "AOD" ||
4414 pkgname == "AOD.par") hasAOD = kTRUE;
4415 if (pkgname == "ANALYSIS" ||
4416 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4417 if (pkgname == "OADB" ||
4418 pkgname == "OADB.par") hasOADB = kTRUE;
4419 if (pkgname == "ANALYSISalice" ||
4420 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4421 if (pkgname == "CORRFW" ||
4422 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4424 if (hasANALYSISalice) setupPar = "SetupPar";
4425 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4426 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4427 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4428 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4429 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4430 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4431 out << " gSystem->Load(\"libOADB\");" << endl;
4432 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4433 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4434 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4435 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4436 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4437 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4438 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4439 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4440 out << "// Compile other par packages" << endl;
4442 while ((obj=next())) {
4443 pkgname = obj->GetName();
4444 if (pkgname == "STEERBase" ||
4445 pkgname == "STEERBase.par" ||
4447 pkgname == "ESD.par" ||
4449 pkgname == "AOD.par" ||
4450 pkgname == "ANALYSIS" ||
4451 pkgname == "ANALYSIS.par" ||
4452 pkgname == "OADB" ||
4453 pkgname == "OADB.par" ||
4454 pkgname == "ANALYSISalice" ||
4455 pkgname == "ANALYSISalice.par" ||
4456 pkgname == "CORRFW" ||
4457 pkgname == "CORRFW.par") continue;
4458 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4461 out << "// include path" << endl;
4462 // Get the include path from the interpreter and remove entries pointing to AliRoot
4463 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4464 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4465 out << " TIter nextpath(listpaths);" << endl;
4466 out << " TObjString *pname;" << endl;
4467 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4468 out << " TString current = pname->GetName();" << endl;
4469 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4470 out << " gSystem->AddIncludePath(current);" << endl;
4471 out << " }" << endl;
4472 out << " if (listpaths) delete listpaths;" << endl;
4473 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4474 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4475 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4476 if (fAdditionalLibs.Length()) {
4477 out << "// Add aditional AliRoot libraries" << endl;
4478 TString additionalLibs = fAdditionalLibs;
4479 additionalLibs.Strip();
4480 if (additionalLibs.Length() && fFriendLibs.Length())
4481 additionalLibs += " ";
4482 additionalLibs += fFriendLibs;
4483 TObjArray *list = additionalLibs.Tokenize(" ");
4486 while((str=(TObjString*)next())) {
4487 if (str->GetString().Contains(".so"))
4488 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4490 if (list) delete list;
4493 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4494 if (fAnalysisSource.Length()) {
4495 TObjArray *list = fAnalysisSource.Tokenize(" ");
4498 while((str=(TObjString*)next())) {
4499 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4501 if (list) delete list;
4505 if (fFastReadOption) {
4506 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 !!!");
4507 out << "// fast xrootd reading enabled" << endl;
4508 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4509 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4510 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4511 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4512 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4513 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4515 // Change temp directory to current one
4516 out << "// Connect to AliEn" << endl;
4517 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4518 out << "// Set temporary merging directory to current one" << endl;
4519 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4520 out << "// Set temporary compilation directory to current one" << endl;
4521 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4522 out << " TString outputDir = dir;" << endl;
4523 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4524 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4525 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4526 out << " TIter *iter = new TIter(list);" << endl;
4527 out << " TObjString *str;" << endl;
4528 out << " TString outputFile;" << endl;
4529 out << " Bool_t merged = kTRUE;" << endl;
4530 TString analysisFile = fExecutable;
4531 analysisFile.ReplaceAll(".sh", ".root");
4532 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4533 << analysisFile << "\");" << endl;
4534 out << " if (!mgr) {" << endl;
4535 out << " printf(\"ERROR: Analysis manager could not be extracted from file \");" << endl;
4536 out << " return;" << endl;
4537 out << " }" << endl;
4538 if (IsLocalTest()) {
4539 out << " printf(\"===================================\n\");" << endl;
4540 out << " printf(\"Testing merging...\\n\");" << endl;
4541 out << " printf(\"===================================\n\");" << endl;
4543 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4544 out << " outputFile = str->GetString();" << endl;
4545 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4546 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4547 out << " if (index > 0) outputFile.Remove(index);" << endl;
4548 out << " // Skip already merged outputs" << endl;
4549 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4550 out << " printf(\"Output file <%s> found. Not merging again.\\n\",outputFile.Data());" << endl;
4551 out << " continue;" << endl;
4552 out << " }" << endl;
4553 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4554 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4555 out << " if (!merged) {" << endl;
4556 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4557 out << " return;" << endl;
4558 out << " }" << endl;
4559 out << " }" << endl;
4560 if (mgr && mgr->IsCollectThroughput() && !IsLocalTest()) {
4561 out << " TString infolog = \"" << mgr->GetFileInfoLog() << "\";" << endl;
4562 out << " AliAnalysisAlien::MergeInfo(infolog, outputDir);" << endl;
4564 out << " // all outputs merged, validate" << endl;
4565 out << " ofstream out;" << endl;
4566 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4567 out << " out.close();" << endl;
4568 out << " // read the analysis manager from file" << endl;
4569 if (IsLocalTest()) {
4570 out << " printf(\"===================================\n\");" << endl;
4571 out << " printf(\"Testing Terminate()...\\n\");" << endl;
4572 out << " printf(\"===================================\n\");" << endl;
4574 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4576 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4577 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4578 out << " mgr->PrintStatus();" << endl;
4580 if (mgr->GetDebugLevel()>3) {
4581 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4583 if (TestBit(AliAnalysisGrid::kTest))
4584 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4586 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4589 out << " TTree *tree = NULL;" << endl;
4590 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4591 out << "}" << endl << endl;
4592 if (hasANALYSISalice) {
4593 out <<"//________________________________________________________________________________" << endl;
4594 out << "Bool_t SetupPar(const char *package) {" << endl;
4595 out << "// Compile the package and set it up." << endl;
4596 out << " TString pkgdir = package;" << endl;
4597 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4598 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4599 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4600 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4601 out << " // Check for BUILD.sh and execute" << endl;
4602 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4603 out << " printf(\"*******************************\\n\");" << endl;
4604 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4605 out << " printf(\"*******************************\\n\");" << endl;
4606 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4607 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4608 out << " gSystem->ChangeDirectory(cdir);" << endl;
4609 out << " return kFALSE;" << endl;
4610 out << " }" << endl;
4611 out << " } else {" << endl;
4612 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4613 out << " gSystem->ChangeDirectory(cdir);" << endl;
4614 out << " return kFALSE;" << endl;
4615 out << " }" << endl;
4616 out << " // Check for SETUP.C and execute" << endl;
4617 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4618 out << " printf(\"*******************************\\n\");" << endl;
4619 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4620 out << " printf(\"*******************************\\n\");" << endl;
4621 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4622 out << " } else {" << endl;
4623 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4624 out << " gSystem->ChangeDirectory(cdir);" << endl;
4625 out << " return kFALSE;" << endl;
4626 out << " }" << endl;
4627 out << " // Restore original workdir" << endl;
4628 out << " gSystem->ChangeDirectory(cdir);" << endl;
4629 out << " return kTRUE;" << endl;
4633 Bool_t copy = kTRUE;
4634 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4637 TString workdir = gGrid->GetHomeDirectory();
4638 workdir += fGridWorkingDir;
4639 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4640 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4641 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4642 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4643 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4647 //______________________________________________________________________________
4648 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4650 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4651 // Note that for loading the compiled library. The current directory should have precedence in
4653 TString pkgdir = package;
4654 pkgdir.ReplaceAll(".par","");
4655 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4656 TString cdir = gSystem->WorkingDirectory();
4657 gSystem->ChangeDirectory(pkgdir);
4658 // Check for BUILD.sh and execute
4659 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4660 printf("**************************************************\n");
4661 printf("*** Building PAR archive %s\n", package);
4662 printf("**************************************************\n");
4663 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4664 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4665 gSystem->ChangeDirectory(cdir);
4669 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4670 gSystem->ChangeDirectory(cdir);
4673 // Check for SETUP.C and execute
4674 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4675 printf("**************************************************\n");
4676 printf("*** Setup PAR archive %s\n", package);
4677 printf("**************************************************\n");
4678 gROOT->Macro("PROOF-INF/SETUP.C");
4679 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4681 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4682 gSystem->ChangeDirectory(cdir);
4685 // Restore original workdir
4686 gSystem->ChangeDirectory(cdir);
4690 //______________________________________________________________________________
4691 void AliAnalysisAlien::WriteExecutable()
4693 // Generate the alien executable script.
4694 // Patch executable with -x to catch error code
4695 if (fExecutableCommand.Contains("root") &&
4696 fExecutableCommand.Contains("-q") &&
4697 !fExecutableCommand.Contains("-x")) fExecutableCommand += " -x";
4698 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4700 out.open(fExecutable.Data(), ios::out);
4702 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4705 out << "#!/bin/bash" << endl;
4706 // Make sure we can properly compile par files
4707 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4708 out << "echo \"=========================================\"" << endl;
4709 out << "echo \"############## PATH : ##############\"" << endl;
4710 out << "echo $PATH" << endl;
4711 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4712 out << "echo $LD_LIBRARY_PATH" << endl;
4713 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4714 out << "echo $ROOTSYS" << endl;
4715 out << "echo \"############## which root : ##############\"" << endl;
4716 out << "which root" << endl;
4717 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4718 out << "echo $ALICE_ROOT" << endl;
4719 out << "echo \"############## which aliroot : ##############\"" << endl;
4720 out << "which aliroot" << endl;
4721 out << "echo \"############## system limits : ##############\"" << endl;
4722 out << "ulimit -a" << endl;
4723 out << "echo \"############## memory : ##############\"" << endl;
4724 out << "free -m" << endl;
4725 out << "echo \"=========================================\"" << endl << endl;
4726 out << fExecutableCommand << " ";
4727 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4728 out << "RET=$?" << endl;
4729 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4730 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4731 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4732 out << " let sig=\"$RET - 128\""<<endl;
4733 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4734 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4735 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4736 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4737 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4738 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4740 out << " exit $RET"<< endl;
4741 out << "fi" << endl << endl ;
4742 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4743 out << "echo \"############## memory after: ##############\"" << endl;
4744 out << "free -m" << endl;
4746 Bool_t copy = kTRUE;
4747 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4750 TString workdir = gGrid->GetHomeDirectory();
4751 TString bindir = Form("%s/bin", workdir.Data());
4752 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4753 workdir += fGridWorkingDir;
4754 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4755 if (FileExists(executable)) gGrid->Rm(executable);
4756 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4757 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4758 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4759 executable.Data())) Fatal("","Terminating");
4763 //______________________________________________________________________________
4764 void AliAnalysisAlien::WriteMergeExecutable()
4766 // Generate the alien executable script for the merging job.
4767 if (!fMergeViaJDL) return;
4768 TString mergeExec = fExecutable;
4769 mergeExec.ReplaceAll(".sh", "_merge.sh");
4770 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4772 out.open(mergeExec.Data(), ios::out);
4774 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4777 out << "#!/bin/bash" << endl;
4778 // Make sure we can properly compile par files
4779 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4780 out << "echo \"=========================================\"" << endl;
4781 out << "echo \"############## PATH : ##############\"" << endl;
4782 out << "echo $PATH" << endl;
4783 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4784 out << "echo $LD_LIBRARY_PATH" << endl;
4785 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4786 out << "echo $ROOTSYS" << endl;
4787 out << "echo \"############## which root : ##############\"" << endl;
4788 out << "which root" << endl;
4789 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4790 out << "echo $ALICE_ROOT" << endl;
4791 out << "echo \"############## which aliroot : ##############\"" << endl;
4792 out << "which aliroot" << endl;
4793 out << "echo \"############## system limits : ##############\"" << endl;
4794 out << "ulimit -a" << endl;
4795 out << "echo \"############## memory : ##############\"" << endl;
4796 out << "free -m" << endl;
4797 out << "echo \"=========================================\"" << endl << endl;
4798 TString mergeMacro = fExecutable;
4799 mergeMacro.ReplaceAll(".sh", "_merge.C");
4800 if (IsOneStageMerging())
4801 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4803 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4804 out << fExecutableCommand << " " << "$ARG" << endl;
4805 out << "RET=$?" << endl;
4806 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4807 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4808 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4809 out << " let sig=\"$RET - 128\""<<endl;
4810 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4811 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4812 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4813 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4814 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4815 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4817 out << " exit $RET"<< endl;
4818 out << "fi" << endl << endl ;
4819 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4820 out << "echo \"############## memory after: ##############\"" << endl;
4821 out << "free -m" << endl;
4823 Bool_t copy = kTRUE;
4824 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4827 TString workdir = gGrid->GetHomeDirectory();
4828 TString bindir = Form("%s/bin", workdir.Data());
4829 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4830 workdir += fGridWorkingDir;
4831 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4832 if (FileExists(executable)) gGrid->Rm(executable);
4833 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4834 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4835 if (!copyLocal2Alien("WriteMergeExecutable",
4836 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4840 //______________________________________________________________________________
4841 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4843 // Write the production file to be submitted by LPM manager. The format is:
4844 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4845 // Next lines: full_path_to_dataset XXX (XXX is a string)
4846 // To submit, one has to: submit jdl XXX for all lines
4848 out.open(filename, ios::out);
4850 Error("WriteProductionFile", "Bad file name: %s", filename);
4854 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4855 workdir = gGrid->GetHomeDirectory();
4856 workdir += fGridWorkingDir;
4857 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4858 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4859 out << locjdl << " " << njobspermaster << endl;
4860 Int_t nmasterjobs = fInputFiles->GetEntries();
4861 for (Int_t i=0; i<nmasterjobs; i++) {
4862 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4863 runOutDir.ReplaceAll(".xml", "");
4865 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4867 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4870 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4871 if (FileExists(filename)) gGrid->Rm(filename);
4872 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4873 if (!copyLocal2Alien("WriteProductionFile", filename,
4874 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4878 //______________________________________________________________________________
4879 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4881 // Generate the alien validation script.
4882 // Generate the validation script
4884 if (fValidationScript.IsNull()) {
4885 fValidationScript = fExecutable;
4886 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4888 TString validationScript = fValidationScript;
4889 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4891 Error("WriteValidationScript", "Alien connection required");
4894 if (!fTerminateFiles.IsNull()) {
4895 fTerminateFiles.Strip();
4896 fTerminateFiles.ReplaceAll(" ",",");
4898 TString outStream = "";
4899 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4900 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4902 out.open(validationScript, ios::out);
4903 out << "#!/bin/bash" << endl;
4904 out << "##################################################" << endl;
4905 out << "validateout=`dirname $0`" << endl;
4906 out << "validatetime=`date`" << endl;
4907 out << "validated=\"0\";" << endl;
4908 out << "error=0" << endl;
4909 out << "if [ -z $validateout ]" << endl;
4910 out << "then" << endl;
4911 out << " validateout=\".\"" << endl;
4912 out << "fi" << endl << endl;
4913 out << "cd $validateout;" << endl;
4914 out << "validateworkdir=`pwd`;" << endl << endl;
4915 out << "echo \"*******************************************************\"" << outStream << endl;
4916 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4918 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4919 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4920 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4921 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4922 out << "ls -la ./" << outStream << endl;
4923 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4924 out << "##################################################" << endl;
4927 out << "if [ ! -f stderr ] ; then" << endl;
4928 out << " error=1" << endl;
4929 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4930 out << " echo \"Error = $error\" " << outStream << endl;
4931 out << "fi" << endl;
4933 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4934 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4935 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4936 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4939 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4940 out << " error=1" << endl;
4941 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4942 out << " echo \"$parArch\" " << outStream << endl;
4943 out << " echo \"Error = $error\" " << outStream << endl;
4944 out << "fi" << endl;
4946 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4947 out << " error=1" << endl;
4948 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4949 out << " echo \"$segViol\" " << outStream << endl;
4950 out << " echo \"Error = $error\" " << outStream << endl;
4951 out << "fi" << endl;
4953 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4954 out << " error=1" << endl;
4955 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4956 out << " echo \"$segFault\" " << outStream << endl;
4957 out << " echo \"Error = $error\" " << outStream << endl;
4958 out << "fi" << endl;
4960 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4961 out << " error=1" << endl;
4962 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4963 out << " echo \"$glibcErr\" " << outStream << endl;
4964 out << " echo \"Error = $error\" " << outStream << endl;
4965 out << "fi" << endl;
4967 // Part dedicated to the specific analyses running into the train
4969 TString outputFiles = fOutputFiles;
4970 if (merge && !fTerminateFiles.IsNull()) {
4972 outputFiles += fTerminateFiles;
4974 TObjArray *arr = outputFiles.Tokenize(",");
4977 while (!merge && (os=(TObjString*)next1())) {
4978 // No need to validate outputs produced by merging since the merging macro does this
4979 outputFile = os->GetString();
4980 Int_t index = outputFile.Index("@");
4981 if (index > 0) outputFile.Remove(index);
4982 if (fTerminateFiles.Contains(outputFile)) continue;
4983 if (outputFile.Contains("*")) continue;
4984 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4985 out << " error=1" << endl;
4986 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4987 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4988 out << "fi" << endl;
4991 out << "if ! [ -f outputs_valid ] ; then" << endl;
4992 out << " error=1" << endl;
4993 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4994 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4995 out << "fi" << endl;
4997 out << "if [ $error = 0 ] ; then" << endl;
4998 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4999 if (!IsKeepLogs()) {
5000 out << " echo \"* === Logs std* will be deleted === \"" << endl;
5002 out << " rm -f std*" << endl;
5004 out << "fi" << endl;
5006 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
5007 out << "echo \"*******************************************************\"" << outStream << endl;
5008 out << "cd -" << endl;
5009 out << "exit $error" << endl;
5011 Bool_t copy = kTRUE;
5012 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
5015 TString workdir = gGrid->GetHomeDirectory();
5016 workdir += fGridWorkingDir;
5017 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
5018 if (FileExists(validationScript)) gGrid->Rm(validationScript);
5019 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
5020 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
5021 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");