1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "AliAnalysisAlien.h"
25 #include "Riostream.h"
33 #include "TFileCollection.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
39 #include "TGridResult.h"
40 #include "TGridCollection.h"
42 #include "TGridJobStatusList.h"
43 #include "TGridJobStatus.h"
44 #include "TFileMerger.h"
45 #include "AliAnalysisManager.h"
46 #include "AliAnalysisTaskCfg.h"
47 #include "AliVEventHandler.h"
48 #include "AliAnalysisDataContainer.h"
49 #include "AliMultiInputEventHandler.h"
55 ClassImp(AliAnalysisAlien)
61 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
63 TString sl(Form("file:%s", loc));
64 TString sr(Form("alien://%s", rem));
65 Bool_t ret = TFile::Cp(sl, sr);
67 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
73 //______________________________________________________________________________
74 AliAnalysisAlien::AliAnalysisAlien()
80 fSplitMaxInputFileNumber(0),
82 fMasterResubmitThreshold(0),
95 fNproofWorkersPerSlave(0),
105 fAdditionalRootLibs(),
134 fRootVersionForProof(),
146 //______________________________________________________________________________
147 AliAnalysisAlien::AliAnalysisAlien(const char *name)
148 :AliAnalysisGrid(name),
153 fSplitMaxInputFileNumber(0),
155 fMasterResubmitThreshold(0),
168 fNproofWorkersPerSlave(0),
172 fExecutableCommand(),
178 fAdditionalRootLibs(),
207 fRootVersionForProof(),
219 //______________________________________________________________________________
220 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
221 :AliAnalysisGrid(other),
224 fPrice(other.fPrice),
226 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
227 fMaxInitFailed(other.fMaxInitFailed),
228 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
229 fNtestFiles(other.fNtestFiles),
230 fNrunsPerMaster(other.fNrunsPerMaster),
231 fMaxMergeFiles(other.fMaxMergeFiles),
232 fMaxMergeStages(other.fMaxMergeStages),
233 fNsubmitted(other.fNsubmitted),
234 fProductionMode(other.fProductionMode),
235 fOutputToRunNo(other.fOutputToRunNo),
236 fMergeViaJDL(other.fMergeViaJDL),
237 fFastReadOption(other.fFastReadOption),
238 fOverwriteMode(other.fOverwriteMode),
239 fNreplicas(other.fNreplicas),
240 fNproofWorkers(other.fNproofWorkers),
241 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
242 fProofReset(other.fProofReset),
243 fRunNumbers(other.fRunNumbers),
244 fExecutable(other.fExecutable),
245 fExecutableCommand(other.fExecutableCommand),
246 fArguments(other.fArguments),
247 fExecutableArgs(other.fExecutableArgs),
248 fAnalysisMacro(other.fAnalysisMacro),
249 fAnalysisSource(other.fAnalysisSource),
250 fValidationScript(other.fValidationScript),
251 fAdditionalRootLibs(other.fAdditionalRootLibs),
252 fAdditionalLibs(other.fAdditionalLibs),
253 fSplitMode(other.fSplitMode),
254 fAPIVersion(other.fAPIVersion),
255 fROOTVersion(other.fROOTVersion),
256 fAliROOTVersion(other.fAliROOTVersion),
257 fExternalPackages(other.fExternalPackages),
259 fGridWorkingDir(other.fGridWorkingDir),
260 fGridDataDir(other.fGridDataDir),
261 fDataPattern(other.fDataPattern),
262 fGridOutputDir(other.fGridOutputDir),
263 fOutputArchive(other.fOutputArchive),
264 fOutputFiles(other.fOutputFiles),
265 fInputFormat(other.fInputFormat),
266 fDatasetName(other.fDatasetName),
267 fJDLName(other.fJDLName),
268 fTerminateFiles(other.fTerminateFiles),
269 fMergeExcludes(other.fMergeExcludes),
270 fRegisterExcludes(other.fRegisterExcludes),
271 fIncludePath(other.fIncludePath),
272 fCloseSE(other.fCloseSE),
273 fFriendChainName(other.fFriendChainName),
274 fJobTag(other.fJobTag),
275 fOutputSingle(other.fOutputSingle),
276 fRunPrefix(other.fRunPrefix),
277 fProofCluster(other.fProofCluster),
278 fProofDataSet(other.fProofDataSet),
279 fFileForTestMode(other.fFileForTestMode),
280 fRootVersionForProof(other.fRootVersionForProof),
281 fAliRootMode(other.fAliRootMode),
282 fMergeDirName(other.fMergeDirName),
289 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
290 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
291 fRunRange[0] = other.fRunRange[0];
292 fRunRange[1] = other.fRunRange[1];
293 if (other.fInputFiles) {
294 fInputFiles = new TObjArray();
295 TIter next(other.fInputFiles);
297 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
298 fInputFiles->SetOwner();
300 if (other.fPackages) {
301 fPackages = new TObjArray();
302 TIter next(other.fPackages);
304 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
305 fPackages->SetOwner();
307 if (other.fModules) {
308 fModules = new TObjArray();
309 fModules->SetOwner();
310 TIter next(other.fModules);
311 AliAnalysisTaskCfg *mod, *crt;
312 while ((crt=(AliAnalysisTaskCfg*)next())) {
313 mod = new AliAnalysisTaskCfg(*crt);
319 //______________________________________________________________________________
320 AliAnalysisAlien::~AliAnalysisAlien()
328 fProofParam.DeleteAll();
331 //______________________________________________________________________________
332 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
335 if (this != &other) {
336 AliAnalysisGrid::operator=(other);
337 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
338 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
339 fPrice = other.fPrice;
341 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
342 fMaxInitFailed = other.fMaxInitFailed;
343 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
344 fNtestFiles = other.fNtestFiles;
345 fNrunsPerMaster = other.fNrunsPerMaster;
346 fMaxMergeFiles = other.fMaxMergeFiles;
347 fMaxMergeStages = other.fMaxMergeStages;
348 fNsubmitted = other.fNsubmitted;
349 fProductionMode = other.fProductionMode;
350 fOutputToRunNo = other.fOutputToRunNo;
351 fMergeViaJDL = other.fMergeViaJDL;
352 fFastReadOption = other.fFastReadOption;
353 fOverwriteMode = other.fOverwriteMode;
354 fNreplicas = other.fNreplicas;
355 fNproofWorkers = other.fNproofWorkers;
356 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
357 fProofReset = other.fProofReset;
358 fRunNumbers = other.fRunNumbers;
359 fExecutable = other.fExecutable;
360 fExecutableCommand = other.fExecutableCommand;
361 fArguments = other.fArguments;
362 fExecutableArgs = other.fExecutableArgs;
363 fAnalysisMacro = other.fAnalysisMacro;
364 fAnalysisSource = other.fAnalysisSource;
365 fValidationScript = other.fValidationScript;
366 fAdditionalRootLibs = other.fAdditionalRootLibs;
367 fAdditionalLibs = other.fAdditionalLibs;
368 fSplitMode = other.fSplitMode;
369 fAPIVersion = other.fAPIVersion;
370 fROOTVersion = other.fROOTVersion;
371 fAliROOTVersion = other.fAliROOTVersion;
372 fExternalPackages = other.fExternalPackages;
374 fGridWorkingDir = other.fGridWorkingDir;
375 fGridDataDir = other.fGridDataDir;
376 fDataPattern = other.fDataPattern;
377 fGridOutputDir = other.fGridOutputDir;
378 fOutputArchive = other.fOutputArchive;
379 fOutputFiles = other.fOutputFiles;
380 fInputFormat = other.fInputFormat;
381 fDatasetName = other.fDatasetName;
382 fJDLName = other.fJDLName;
383 fTerminateFiles = other.fTerminateFiles;
384 fMergeExcludes = other.fMergeExcludes;
385 fRegisterExcludes = other.fRegisterExcludes;
386 fIncludePath = other.fIncludePath;
387 fCloseSE = other.fCloseSE;
388 fFriendChainName = other.fFriendChainName;
389 fJobTag = other.fJobTag;
390 fOutputSingle = other.fOutputSingle;
391 fRunPrefix = other.fRunPrefix;
392 fProofCluster = other.fProofCluster;
393 fProofDataSet = other.fProofDataSet;
394 fFileForTestMode = other.fFileForTestMode;
395 fRootVersionForProof = other.fRootVersionForProof;
396 fAliRootMode = other.fAliRootMode;
397 fMergeDirName = other.fMergeDirName;
398 if (other.fInputFiles) {
399 fInputFiles = new TObjArray();
400 TIter next(other.fInputFiles);
402 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
403 fInputFiles->SetOwner();
405 if (other.fPackages) {
406 fPackages = new TObjArray();
407 TIter next(other.fPackages);
409 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
410 fPackages->SetOwner();
412 if (other.fModules) {
413 fModules = new TObjArray();
414 fModules->SetOwner();
415 TIter next(other.fModules);
416 AliAnalysisTaskCfg *mod, *crt;
417 while ((crt=(AliAnalysisTaskCfg*)next())) {
418 mod = new AliAnalysisTaskCfg(*crt);
426 //______________________________________________________________________________
427 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
429 // Add a single additional library to be loaded. Extension must be present.
431 if (!lib.Contains(".")) {
432 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
435 if (fAdditionalLibs.Contains(name)) {
436 Warning("AddAdditionalLibrary", "Library %s already added.", name);
439 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
440 fAdditionalLibs += lib;
443 //______________________________________________________________________________
444 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
446 // Adding a module. Checks if already existing. Becomes owned by this.
448 if (GetModule(module->GetName())) {
449 Error("AddModule", "A module having the same name %s already added", module->GetName());
453 fModules = new TObjArray();
454 fModules->SetOwner();
456 fModules->Add(module);
459 //______________________________________________________________________________
460 void AliAnalysisAlien::AddModules(TObjArray *list)
462 // Adding a list of modules. Checks if already existing. Becomes owned by this.
464 AliAnalysisTaskCfg *module;
465 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
468 //______________________________________________________________________________
469 Bool_t AliAnalysisAlien::CheckDependencies()
471 // Check if all dependencies are satisfied. Reorder modules if needed.
472 Int_t nmodules = GetNmodules();
474 Warning("CheckDependencies", "No modules added yet to check their dependencies");
477 AliAnalysisTaskCfg *mod = 0;
478 AliAnalysisTaskCfg *dep = 0;
481 for (i=0; i<nmodules; i++) {
482 mod = (AliAnalysisTaskCfg*) fModules->At(i);
483 Int_t ndeps = mod->GetNdeps();
485 for (j=0; j<ndeps; j++) {
486 depname = mod->GetDependency(j);
487 dep = GetModule(depname);
489 Error("CheckDependencies","Dependency %s not added for module %s",
490 depname.Data(), mod->GetName());
493 if (dep->NeedsDependency(mod->GetName())) {
494 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
495 mod->GetName(), dep->GetName());
498 Int_t idep = fModules->IndexOf(dep);
499 // The dependency task must come first
501 // Remove at idep and move all objects below up one slot
502 // down to index i included.
503 fModules->RemoveAt(idep);
504 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
505 fModules->AddAt(dep, i++);
507 //Redo from istart if dependencies were inserted
508 if (i>istart) i=istart-1;
514 //______________________________________________________________________________
515 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
517 // Create the analysis manager and optionally execute the macro in filename.
518 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
520 mgr = new AliAnalysisManager(name);
521 mgr->SetGridHandler((AliAnalysisGrid*)this);
522 if (strlen(filename)) {
523 TString line = gSystem->ExpandPathName(filename);
525 gROOT->ProcessLine(line.Data());
530 //______________________________________________________________________________
531 Int_t AliAnalysisAlien::GetNmodules() const
533 // Get number of modules.
534 if (!fModules) return 0;
535 return fModules->GetEntries();
538 //______________________________________________________________________________
539 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
541 // Get a module by name.
542 if (!fModules) return 0;
543 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
546 //______________________________________________________________________________
547 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
549 // Load a given module.
550 if (mod->IsLoaded()) return kTRUE;
551 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
553 Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
556 Int_t ndeps = mod->GetNdeps();
558 for (Int_t j=0; j<ndeps; j++) {
559 depname = mod->GetDependency(j);
560 AliAnalysisTaskCfg *dep = GetModule(depname);
562 Error("LoadModule","Dependency %s not existing for module %s",
563 depname.Data(), mod->GetName());
566 if (!LoadModule(dep)) {
567 Error("LoadModule","Dependency %s for module %s could not be loaded",
568 depname.Data(), mod->GetName());
572 // Load libraries for the module
573 if (!mod->CheckLoadLibraries()) {
574 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
577 // Check if a custom file name was requested
578 if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
580 // Check if a custom terminate file name was requested
581 if (strlen(mod->GetTerminateFileName())) {
582 if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
583 fTerminateFiles += mod->GetTerminateFileName();
587 if (mod->ExecuteMacro()<0) {
588 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
589 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
592 // Configure dependencies
593 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
594 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
595 mod->GetConfigMacro()->GetTitle(), mod->GetName());
598 // Adjust extra libraries
599 Int_t nlibs = mod->GetNlibs();
601 for (Int_t i=0; i<nlibs; i++) {
602 lib = mod->GetLibrary(i);
603 lib = Form("lib%s.so", lib.Data());
604 if (fAdditionalLibs.Contains(lib)) continue;
605 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
606 fAdditionalLibs += lib;
611 //______________________________________________________________________________
612 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
614 // Generate the full train.
615 fAdditionalLibs = "";
616 if (!LoadModules()) return kFALSE;
617 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
618 if (!mgr->InitAnalysis()) return kFALSE;
621 Int_t productionMode = fProductionMode;
623 TString macro = fAnalysisMacro;
624 TString executable = fExecutable;
625 TString validation = fValidationScript;
626 TString execCommand = fExecutableCommand;
627 SetAnalysisMacro(Form("%s.C", name));
628 SetExecutable(Form("%s.sh", name));
629 // SetExecutableCommand("aliroot -b -q ");
630 SetValidationScript(Form("%s_validation.sh", name));
632 SetProductionMode(productionMode);
633 fAnalysisMacro = macro;
634 fExecutable = executable;
635 fExecutableCommand = execCommand;
636 fValidationScript = validation;
640 //______________________________________________________________________________
641 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
643 // Generate test macros for a single module or for the full train.
644 fAdditionalLibs = "";
645 if (strlen(modname)) {
646 if (!CheckDependencies()) return kFALSE;
647 AliAnalysisTaskCfg *mod = GetModule(modname);
649 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
652 if (!LoadModule(mod)) return kFALSE;
653 } else if (!LoadModules()) return kFALSE;
654 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
655 if (!mgr->InitAnalysis()) return kFALSE;
659 Int_t productionMode = fProductionMode;
661 TString macro = fAnalysisMacro;
662 TString executable = fExecutable;
663 TString validation = fValidationScript;
664 TString execCommand = fExecutableCommand;
665 SetAnalysisMacro(Form("%s.C", name));
666 SetExecutable(Form("%s.sh", name));
667 // SetExecutableCommand("aliroot -b -q ");
668 SetValidationScript(Form("%s_validation.sh", name));
670 WriteAnalysisMacro();
672 WriteValidationScript();
674 WriteMergeExecutable();
675 WriteValidationScript(kTRUE);
676 SetLocalTest(kFALSE);
677 SetProductionMode(productionMode);
678 fAnalysisMacro = macro;
679 fExecutable = executable;
680 fExecutableCommand = execCommand;
681 fValidationScript = validation;
685 //______________________________________________________________________________
686 Bool_t AliAnalysisAlien::LoadModules()
688 // Load all modules by executing the AddTask macros. Checks first the dependencies.
689 fAdditionalLibs = "";
690 Int_t nmodules = GetNmodules();
692 Warning("LoadModules", "No module to be loaded");
695 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
697 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
700 if (!CheckDependencies()) return kFALSE;
701 nmodules = GetNmodules();
702 AliAnalysisTaskCfg *mod;
703 for (Int_t imod=0; imod<nmodules; imod++) {
704 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
705 if (!LoadModule(mod)) return kFALSE;
710 //______________________________________________________________________________
711 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
713 // Set the run number format. Can be a prefix or a format like "%09d"
715 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
718 //______________________________________________________________________________
719 void AliAnalysisAlien::AddIncludePath(const char *path)
721 // Add include path in the remote analysis macro.
723 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
724 else fIncludePath += Form("-I%s ", path);
727 //______________________________________________________________________________
728 void AliAnalysisAlien::AddRunNumber(Int_t run)
730 // Add a run number to the list of runs to be processed.
731 if (fRunNumbers.Length()) fRunNumbers += " ";
732 fRunNumbers += Form(fRunPrefix.Data(), run);
735 //______________________________________________________________________________
736 void AliAnalysisAlien::AddRunList(const char* runList)
738 // Add several runs into the list of runs; they are expected to be separated by a blank character.
739 TString sList = runList;
740 TObjArray *list = sList.Tokenize(" ");
741 Int_t n = list->GetEntries();
742 for (Int_t i = 0; i < n; i++) {
743 TObjString *os = (TObjString*)list->At(i);
744 AddRunNumber(os->GetString().Atoi());
749 //______________________________________________________________________________
750 void AliAnalysisAlien::AddRunNumber(const char* run)
752 // Add a run number to the list of runs to be processed.
755 TObjArray *arr = runs.Tokenize(" ");
758 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
759 while ((os=(TObjString*)next())){
760 if (fRunNumbers.Length()) fRunNumbers += " ";
761 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
766 //______________________________________________________________________________
767 void AliAnalysisAlien::AddDataFile(const char *lfn)
769 // Adds a data file to the input to be analysed. The file should be a valid LFN
770 // or point to an existing file in the alien workdir.
771 if (!fInputFiles) fInputFiles = new TObjArray();
772 fInputFiles->Add(new TObjString(lfn));
775 //______________________________________________________________________________
776 void AliAnalysisAlien::AddExternalPackage(const char *package)
778 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
779 if (fExternalPackages) fExternalPackages += " ";
780 fExternalPackages += package;
783 //______________________________________________________________________________
784 Bool_t AliAnalysisAlien::Connect()
786 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
787 if (gGrid && gGrid->IsConnected()) return kTRUE;
788 if (fProductionMode) return kTRUE;
790 Info("Connect", "Trying to connect to AliEn ...");
791 TGrid::Connect("alien://");
793 if (!gGrid || !gGrid->IsConnected()) {
794 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
797 fUser = gGrid->GetUser();
798 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
802 //______________________________________________________________________________
803 void AliAnalysisAlien::CdWork()
805 // Check validity of alien workspace. Create directory if possible.
807 Error("CdWork", "Alien connection required");
810 TString homedir = gGrid->GetHomeDirectory();
811 TString workdir = homedir + fGridWorkingDir;
812 if (DirectoryExists(workdir)) {
816 // Work directory not existing - create it
818 if (gGrid->Mkdir(workdir, "-p")) {
819 gGrid->Cd(fGridWorkingDir);
820 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
822 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
823 workdir.Data(), homedir.Data());
824 fGridWorkingDir = "";
828 //______________________________________________________________________________
829 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
831 // Check if file copying is possible.
832 if (fProductionMode) return kTRUE;
833 TString salienpath(alienpath);
834 if (salienpath.Contains(" ")) {
835 Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
839 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
842 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
843 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
844 // Check if alien_CLOSE_SE is defined
845 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
846 if (!closeSE.IsNull()) {
847 Info("CheckFileCopy", "Your current close storage is pointing to: \
848 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
850 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
852 // Check if grid directory exists.
853 if (!DirectoryExists(alienpath)) {
854 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
857 TString stest = "plugin_test_copy";
858 TFile f(stest, "RECREATE");
859 // User may not have write permissions to current directory
861 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
862 gSystem->WorkingDirectory());
866 if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
867 if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
868 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
869 \n# 1. Make sure you have write permissions there. If this is the case: \
870 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
871 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
872 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
873 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
874 gSystem->Unlink(stest.Data());
877 gSystem->Unlink(stest.Data());
878 gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
879 Info("CheckFileCopy", "### ...SUCCESS ###");
883 //______________________________________________________________________________
884 Bool_t AliAnalysisAlien::CheckInputData()
886 // Check validity of input data. If necessary, create xml files.
887 if (fProductionMode) return kTRUE;
888 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
889 if (!fGridDataDir.Length()) {
890 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
894 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
897 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
898 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
899 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
902 // Process declared files
903 Bool_t isCollection = kFALSE;
904 Bool_t isXml = kFALSE;
905 Bool_t useTags = kFALSE;
906 Bool_t checked = kFALSE;
907 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
909 TString workdir = gGrid->GetHomeDirectory();
910 workdir += fGridWorkingDir;
913 TIter next(fInputFiles);
914 while ((objstr=(TObjString*)next())) {
917 file += objstr->GetString();
918 // Store full lfn path
919 if (FileExists(file)) objstr->SetString(file);
921 file = objstr->GetName();
922 if (!FileExists(objstr->GetName())) {
923 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
924 objstr->GetName(), workdir.Data());
928 Bool_t iscoll, isxml, usetags;
929 CheckDataType(file, iscoll, isxml, usetags);
932 isCollection = iscoll;
935 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
937 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
938 Error("CheckInputData", "Some conflict was found in the types of inputs");
944 // Process requested run numbers
945 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
946 // Check validity of alien data directory
947 if (!fGridDataDir.Length()) {
948 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
951 if (!DirectoryExists(fGridDataDir)) {
952 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
956 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
960 if (checked && !isXml) {
961 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
964 // Check validity of run number(s)
969 TString schunk, schunk2;
973 useTags = fDataPattern.Contains("tag");
974 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
976 if (useTags != fDataPattern.Contains("tag")) {
977 Error("CheckInputData", "Cannot mix input files using/not using tags");
980 if (fRunNumbers.Length()) {
981 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
982 arr = fRunNumbers.Tokenize(" ");
984 while ((os=(TObjString*)next())) {
985 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
986 if (!DirectoryExists(path)) {
987 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
990 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
991 TString msg = "\n##### file: ";
993 msg += " type: xml_collection;";
994 if (useTags) msg += " using_tags: Yes";
995 else msg += " using_tags: No";
996 Info("CheckDataType", "%s", msg.Data());
997 if (fNrunsPerMaster<2) {
998 AddDataFile(Form("%s.xml", os->GetString().Data()));
1001 if (((nruns-1)%fNrunsPerMaster) == 0) {
1002 schunk = os->GetString();
1004 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
1005 schunk += Form("_%s.xml", os->GetString().Data());
1006 AddDataFile(schunk);
1011 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1012 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1013 format = Form("%%s/%s ", fRunPrefix.Data());
1014 path = Form(format.Data(), fGridDataDir.Data(), irun);
1015 if (!DirectoryExists(path)) {
1018 format = Form("%%s/%s.xml", fRunPrefix.Data());
1019 path = Form(format.Data(), workdir.Data(),irun);
1020 TString msg = "\n##### file: ";
1022 msg += " type: xml_collection;";
1023 if (useTags) msg += " using_tags: Yes";
1024 else msg += " using_tags: No";
1025 Info("CheckDataType", "%s", msg.Data());
1026 if (fNrunsPerMaster<2) {
1027 format = Form("%s.xml", fRunPrefix.Data());
1028 AddDataFile(Form(format.Data(),irun));
1031 if (((nruns-1)%fNrunsPerMaster) == 0) {
1032 schunk = Form(fRunPrefix.Data(),irun);
1034 format = Form("_%s.xml", fRunPrefix.Data());
1035 schunk2 = Form(format.Data(), irun);
1036 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1038 AddDataFile(schunk);
1043 AddDataFile(schunk);
1049 //______________________________________________________________________________
1050 Int_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1052 // Copy data from the given grid directory according a pattern and make a local
1054 // 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
1056 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1059 if (!DirectoryExists(griddir)) {
1060 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1063 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1064 printf("Running command: %s\n", command.Data());
1065 TGridResult *res = gGrid->Command(command);
1066 Int_t nfound = res->GetEntries();
1068 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1071 printf("... found %d files. Copying locally ...\n", nfound);
1074 TObjArray* additionalArchives = 0;
1075 if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1076 additionalArchives = TString(archivefile).Tokenize(";");
1077 archivefile = additionalArchives->At(0)->GetName();
1078 additionalArchives->RemoveAt(0);
1079 additionalArchives->Compress();
1082 // Copy files locally
1084 out.open(output, ios::out);
1086 TString turl, dirname, filename, temp;
1087 TString cdir = gSystem->WorkingDirectory();
1088 gSystem->MakeDirectory(outputdir);
1089 gSystem->ChangeDirectory(outputdir);
1091 for (Int_t i=0; i<nfound; i++) {
1092 map = (TMap*)res->At(i);
1093 turl = map->GetValue("turl")->GetName();
1094 filename = gSystem->BaseName(turl.Data());
1095 dirname = gSystem->DirName(turl.Data());
1096 dirname = gSystem->BaseName(dirname.Data());
1097 gSystem->MakeDirectory(dirname);
1099 TString source(turl);
1100 TString targetFileName(filename);
1102 if (strlen(archivefile) > 0) {
1103 // TODO here the archive in which the file resides should be determined
1104 // however whereis returns only a guid, and guid2lfn does not work
1105 // Therefore we use the one provided as argument for now
1106 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1107 targetFileName = archivefile;
1109 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1110 Bool_t success = kTRUE;
1111 if (additionalArchives) {
1112 for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++) {
1114 target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1115 gSystem->MakeDirectory(gSystem->DirName(target));
1116 success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1121 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1122 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1127 gSystem->ChangeDirectory(cdir);
1129 delete additionalArchives;
1133 //______________________________________________________________________________
1134 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1136 // Create dataset for the grid data directory + run number.
1137 const Int_t gMaxEntries = 15000;
1138 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1140 Error("CreateDataset", "Cannot create dataset with no grid connection");
1145 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1146 TString workdir = gGrid->GetHomeDirectory();
1147 workdir += fGridWorkingDir;
1149 // Compose the 'find' command arguments
1152 TString options = "-x collection ";
1153 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1154 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1155 TString conditions = "";
1162 TString schunk, schunk2;
1163 TGridCollection *cbase=0, *cadd=0;
1164 if (!fRunNumbers.Length() && !fRunRange[0]) {
1165 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1166 // Make a single data collection from data directory.
1167 path = fGridDataDir;
1168 if (!DirectoryExists(path)) {
1169 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1173 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1174 else file = Form("%s.xml", gSystem->BaseName(path));
1178 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1180 command += Form("%s -o %d ",options.Data(), nstart);
1184 command += conditions;
1185 printf("command: %s\n", command.Data());
1186 TGridResult *res = gGrid->Command(command);
1187 if (res) delete res;
1188 // Write standard output to file
1189 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1190 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1191 Bool_t nullFile = kFALSE;
1193 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1195 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1197 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1198 gSystem->Exec("rm -f __tmp*");
1206 gSystem->Exec("rm -f __tmp__");
1207 ncount = line.Atoi();
1210 if (ncount == gMaxEntries) {
1211 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1212 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1213 if (!cbase) cbase = cadd;
1221 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1222 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1225 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1226 delete cbase; cbase = 0;
1228 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1230 gSystem->Exec("rm -f __tmp*");
1231 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1235 Bool_t fileExists = FileExists(file);
1236 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1237 // Copy xml file to alien space
1238 if (fileExists) gGrid->Rm(file);
1239 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1240 if (!FileExists(file)) {
1241 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1244 // Update list of files to be processed.
1246 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1250 Bool_t nullResult = kTRUE;
1251 if (fRunNumbers.Length()) {
1252 TObjArray *arr = fRunNumbers.Tokenize(" ");
1255 while ((os=(TObjString*)next())) {
1258 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
1259 if (!DirectoryExists(path)) continue;
1261 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1262 else file = Form("%s.xml", os->GetString().Data());
1263 // If local collection file does not exist, create it via 'find' command.
1267 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1269 command += Form("%s -o %d ",options.Data(), nstart);
1272 command += conditions;
1273 TGridResult *res = gGrid->Command(command);
1274 if (res) delete res;
1275 // Write standard output to file
1276 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1277 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1278 Bool_t nullFile = kFALSE;
1280 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1282 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1284 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1285 gSystem->Exec("rm -f __tmp*");
1286 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1294 gSystem->Exec("rm -f __tmp__");
1295 ncount = line.Atoi();
1297 nullResult = kFALSE;
1299 if (ncount == gMaxEntries) {
1300 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1301 if (fNrunsPerMaster > 1) {
1302 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1303 file.Data(),gMaxEntries);
1306 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1307 if (!cbase) cbase = cadd;
1314 if (cbase && fNrunsPerMaster<2) {
1315 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1316 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1319 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1320 delete cbase; cbase = 0;
1322 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1324 gSystem->Exec("rm -f __tmp*");
1325 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1329 if (TestBit(AliAnalysisGrid::kTest)) break;
1330 // Check if there is one run per master job.
1331 if (fNrunsPerMaster<2) {
1332 if (FileExists(file)) {
1333 if (fOverwriteMode) gGrid->Rm(file);
1335 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1339 // Copy xml file to alien space
1340 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1341 if (!FileExists(file)) {
1342 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1348 if (((nruns-1)%fNrunsPerMaster) == 0) {
1349 schunk = os->GetString();
1350 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1352 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1353 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1357 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1360 schunk += Form("_%s.xml", os->GetString().Data());
1361 if (FileExists(schunk)) {
1362 if (fOverwriteMode) gGrid->Rm(file);
1364 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1368 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1369 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1370 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1371 if (!FileExists(schunk)) {
1372 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1380 Error("CreateDataset", "No valid dataset corresponding to the query!");
1384 // Process a full run range.
1385 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1386 format = Form("%%s/%s ", fRunPrefix.Data());
1389 path = Form(format.Data(), fGridDataDir.Data(), irun);
1390 if (!DirectoryExists(path)) continue;
1392 format = Form("%s.xml", fRunPrefix.Data());
1393 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1394 else file = Form(format.Data(), irun);
1395 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1396 if (fOverwriteMode) gGrid->Rm(file);
1398 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1402 // If local collection file does not exist, create it via 'find' command.
1406 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1408 command += Form("%s -o %d ",options.Data(), nstart);
1411 command += conditions;
1412 TGridResult *res = gGrid->Command(command);
1413 if (res) delete res;
1414 // Write standard output to file
1415 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1416 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1417 Bool_t nullFile = kFALSE;
1419 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1421 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1423 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1424 gSystem->Exec("rm -f __tmp*");
1432 gSystem->Exec("rm -f __tmp__");
1433 ncount = line.Atoi();
1435 nullResult = kFALSE;
1437 if (ncount == gMaxEntries) {
1438 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1439 if (fNrunsPerMaster > 1) {
1440 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1441 file.Data(),gMaxEntries);
1444 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1445 if (!cbase) cbase = cadd;
1452 if (cbase && fNrunsPerMaster<2) {
1453 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1454 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1457 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1458 delete cbase; cbase = 0;
1460 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1462 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1466 if (TestBit(AliAnalysisGrid::kTest)) break;
1467 // Check if there is one run per master job.
1468 if (fNrunsPerMaster<2) {
1469 if (FileExists(file)) {
1470 if (fOverwriteMode) gGrid->Rm(file);
1472 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1476 // Copy xml file to alien space
1477 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1478 if (!FileExists(file)) {
1479 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1484 // Check if the collection for the chunk exist locally.
1485 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1486 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1487 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1490 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1491 if (((nruns-1)%fNrunsPerMaster) == 0) {
1492 schunk = Form(fRunPrefix.Data(), irun);
1493 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1495 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1499 format = Form("%%s_%s.xml", fRunPrefix.Data());
1500 schunk2 = Form(format.Data(), schunk.Data(), irun);
1501 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1505 if (FileExists(schunk)) {
1506 if (fOverwriteMode) gGrid->Rm(schunk);
1508 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1512 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1513 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1514 if (FileExists(schunk)) {
1515 if (fOverwriteMode) gGrid->Rm(schunk);
1517 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1521 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1522 if (!FileExists(schunk)) {
1523 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1529 Error("CreateDataset", "No valid dataset corresponding to the query!");
1536 //______________________________________________________________________________
1537 Bool_t AliAnalysisAlien::CreateJDL()
1539 // Generate a JDL file according to current settings. The name of the file is
1540 // specified by fJDLName.
1541 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1542 Bool_t error = kFALSE;
1544 Bool_t copy = kTRUE;
1545 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1546 Bool_t generate = kTRUE;
1547 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1549 Error("CreateJDL", "Alien connection required");
1552 // Check validity of alien workspace
1554 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1555 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1556 workdir += fGridWorkingDir;
1560 Error("CreateJDL()", "Define some input files for your analysis.");
1563 // Compose list of input files
1564 // Check if output files were defined
1565 if (!fOutputFiles.Length()) {
1566 Error("CreateJDL", "You must define at least one output file");
1569 // Check if an output directory was defined and valid
1570 if (!fGridOutputDir.Length()) {
1571 Error("CreateJDL", "You must define AliEn output directory");
1574 if (!fProductionMode) {
1575 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1576 if (!DirectoryExists(fGridOutputDir)) {
1577 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1578 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1580 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1584 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1589 // Exit if any error up to now
1590 if (error) return kFALSE;
1592 if (!fUser.IsNull()) {
1593 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1594 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1596 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1597 TString mergeExec = fExecutable;
1598 mergeExec.ReplaceAll(".sh", "_merge.sh");
1599 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1600 mergeExec.ReplaceAll(".sh", ".C");
1601 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1602 if (!fArguments.IsNull())
1603 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1604 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1606 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1607 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1610 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1611 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1612 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1613 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1615 if (fMaxInitFailed > 0) {
1616 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1617 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1619 if (fSplitMaxInputFileNumber > 0) {
1620 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1621 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1623 if (!IsOneStageMerging()) {
1624 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1625 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1627 if (fSplitMode.Length()) {
1628 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1629 fGridJDL->SetDescription("Split", "We split per SE or file");
1631 fMergingJDL->SetValue("Split", "\"se\"");
1632 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1633 if (!fAliROOTVersion.IsNull()) {
1634 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1635 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1637 if (!fROOTVersion.IsNull()) {
1638 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1639 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1641 if (!fAPIVersion.IsNull()) {
1642 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1643 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1645 if (!fExternalPackages.IsNull()) {
1646 arr = fExternalPackages.Tokenize(" ");
1648 while ((os=(TObjString*)next())) {
1649 TString pkgname = os->GetString();
1650 Int_t index = pkgname.Index("::");
1651 TString pkgversion = pkgname(index+2, pkgname.Length());
1652 pkgname.Remove(index);
1653 fGridJDL->AddToPackages(pkgname, pkgversion);
1654 fMergingJDL->AddToPackages(pkgname, pkgversion);
1658 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1659 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1660 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1661 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1662 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1663 TString analysisFile = fExecutable;
1664 analysisFile.ReplaceAll(".sh", ".root");
1665 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1666 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1667 if (fAdditionalLibs.Length()) {
1668 arr = fAdditionalLibs.Tokenize(" ");
1670 while ((os=(TObjString*)next())) {
1671 if (os->GetString().Contains(".so")) continue;
1672 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1673 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1678 TIter next(fPackages);
1680 while ((obj=next())) {
1681 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1682 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1685 if (fOutputArchive.Length()) {
1686 TString outputArchive = fOutputArchive;
1687 if (!fRegisterExcludes.IsNull()) {
1688 arr = fRegisterExcludes.Tokenize(" ");
1690 while ((os=(TObjString*)next1())) {
1691 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1692 outputArchive.ReplaceAll(os->GetString(),"");
1696 arr = outputArchive.Tokenize(" ");
1698 Bool_t first = kTRUE;
1699 const char *comment = "Files to be archived";
1700 const char *comment1 = comment;
1701 while ((os=(TObjString*)next())) {
1702 if (!first) comment = NULL;
1703 if (!os->GetString().Contains("@") && fCloseSE.Length())
1704 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1706 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1710 // Output archive for the merging jdl
1711 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1712 outputArchive = "log_archive.zip:std*@disk=1 ";
1713 // Add normal output files, extra files + terminate files
1714 TString files = GetListOfFiles("outextter");
1715 // Do not register files in fRegisterExcludes
1716 if (!fRegisterExcludes.IsNull()) {
1717 arr = fRegisterExcludes.Tokenize(" ");
1719 while ((os=(TObjString*)next1())) {
1720 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1721 files.ReplaceAll(os->GetString(),"");
1725 files.ReplaceAll(".root", "*.root");
1727 if (mgr->IsCollectThroughput())
1728 outputArchive += Form("root_archive.zip:%s,*.stat,*%s@disk=%d",files.Data(),mgr->GetFileInfoLog(),fNreplicas);
1730 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1732 TString files = fOutputArchive;
1733 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1734 outputArchive = files;
1736 arr = outputArchive.Tokenize(" ");
1740 while ((os=(TObjString*)next2())) {
1741 if (!first) comment = NULL;
1742 TString currentfile = os->GetString();
1743 if (!currentfile.Contains("@") && fCloseSE.Length())
1744 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1746 fMergingJDL->AddToOutputArchive(currentfile, comment);
1751 arr = fOutputFiles.Tokenize(",");
1753 Bool_t first = kTRUE;
1754 const char *comment = "Files to be saved";
1755 while ((os=(TObjString*)next())) {
1756 // Ignore ouputs in jdl that are also in outputarchive
1757 TString sout = os->GetString();
1758 sout.ReplaceAll("*", "");
1759 sout.ReplaceAll(".root", "");
1760 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1761 if (fOutputArchive.Contains(sout)) continue;
1762 // Ignore fRegisterExcludes
1763 if (fRegisterExcludes.Contains(sout)) continue;
1764 if (!first) comment = NULL;
1765 if (!os->GetString().Contains("@") && fCloseSE.Length())
1766 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1768 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1770 if (fMergeExcludes.Contains(sout)) continue;
1771 if (!os->GetString().Contains("@") && fCloseSE.Length())
1772 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1774 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1777 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1778 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1779 TString validationScript = fValidationScript;
1780 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1781 validationScript.ReplaceAll(".sh", "_merge.sh");
1782 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1783 if (fMasterResubmitThreshold) {
1784 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1785 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1787 // Write a jdl with 2 input parameters: collection name and output dir name.
1790 // Copy jdl to grid workspace
1792 // Check if an output directory was defined and valid
1793 if (!fGridOutputDir.Length()) {
1794 Error("CreateJDL", "You must define AliEn output directory");
1797 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1798 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1799 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1800 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1802 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1808 if (TestBit(AliAnalysisGrid::kSubmit)) {
1809 TString mergeJDLName = fExecutable;
1810 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1811 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1812 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1813 if (fProductionMode) {
1814 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1815 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1817 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1818 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1819 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1820 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1821 Fatal("","Terminating");
1822 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1824 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1825 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1826 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1827 Fatal("","Terminating");
1830 if (fAdditionalLibs.Length()) {
1831 arr = fAdditionalLibs.Tokenize(" ");
1834 while ((os=(TObjString*)next())) {
1835 if (os->GetString().Contains(".so")) continue;
1836 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1837 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1838 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1839 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1840 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1841 Fatal("","Terminating");
1846 TIter next(fPackages);
1848 while ((obj=next())) {
1849 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1850 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1851 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1852 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1853 Form("%s/%s", workdir.Data(), obj->GetName())))
1854 Fatal("","Terminating");
1861 //______________________________________________________________________________
1862 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1864 // Writes one or more JDL's corresponding to findex. If findex is negative,
1865 // all run numbers are considered in one go (jdl). For non-negative indices
1866 // they correspond to the indices in the array fInputFiles.
1867 if (!fInputFiles) return kFALSE;
1870 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1871 workdir += fGridWorkingDir;
1872 TString stageName = "$2";
1873 if (fProductionMode) stageName = "$4";
1874 if (!fMergeDirName.IsNull()) {
1875 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1876 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1878 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1879 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1881 if (fProductionMode) {
1882 TIter next(fInputFiles);
1883 while ((os=next())) {
1884 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1886 if (!fOutputToRunNo)
1887 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1889 fGridJDL->SetOutputDirectory(fGridOutputDir);
1891 if (!fRunNumbers.Length() && !fRunRange[0]) {
1892 // One jdl with no parameters in case input data is specified by name.
1893 TIter next(fInputFiles);
1895 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1896 if (!fOutputSingle.IsNull())
1897 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1899 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1900 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1903 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1904 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1905 if (!fOutputSingle.IsNull()) {
1906 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1907 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1909 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1914 // Generate the JDL as a string
1915 TString sjdl = fGridJDL->Generate();
1916 TString sjdl1 = fMergingJDL->Generate();
1918 if (!fMergeDirName.IsNull()) {
1919 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1920 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1922 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1923 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1925 TString sjdl2 = fMergingJDL->Generate();
1926 Int_t index, index1;
1927 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1928 sjdl.ReplaceAll("(member", "\n (member");
1929 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1930 sjdl.ReplaceAll("{", "{\n ");
1931 sjdl.ReplaceAll("};", "\n};");
1932 sjdl.ReplaceAll("{\n \n", "{\n");
1933 sjdl.ReplaceAll("\n\n", "\n");
1934 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1935 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1936 sjdl1.ReplaceAll("(member", "\n (member");
1937 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1938 sjdl1.ReplaceAll("{", "{\n ");
1939 sjdl1.ReplaceAll("};", "\n};");
1940 sjdl1.ReplaceAll("{\n \n", "{\n");
1941 sjdl1.ReplaceAll("\n\n", "\n");
1942 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1943 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1944 sjdl2.ReplaceAll("(member", "\n (member");
1945 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1946 sjdl2.ReplaceAll("{", "{\n ");
1947 sjdl2.ReplaceAll("};", "\n};");
1948 sjdl2.ReplaceAll("{\n \n", "{\n");
1949 sjdl2.ReplaceAll("\n\n", "\n");
1950 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1951 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1952 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1953 index = sjdl.Index("JDLVariables");
1954 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1955 sjdl += "Workdirectorysize = {\"5000MB\"};";
1956 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1957 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1958 index = fJobTag.Index(":");
1959 if (index < 0) index = fJobTag.Length();
1960 TString jobTag = fJobTag;
1961 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1962 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1963 if (fProductionMode) {
1964 sjdl1.Prepend("# Generated merging jdl (production mode) \
1965 \n# $1 = full alien path to output directory to be merged \
1966 \n# $2 = train number \
1967 \n# $3 = production (like LHC10b) \
1968 \n# $4 = merging stage \
1969 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1970 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1971 sjdl2.Prepend("# Generated merging jdl \
1972 \n# $1 = full alien path to output directory to be merged \
1973 \n# $2 = train number \
1974 \n# $3 = production (like LHC10b) \
1975 \n# $4 = merging stage \
1976 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1978 sjdl1.Prepend("# Generated merging jdl \
1979 \n# $1 = full alien path to output directory to be merged \
1980 \n# $2 = merging stage \
1981 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1982 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1983 sjdl2.Prepend("# Generated merging jdl \
1984 \n# $1 = full alien path to output directory to be merged \
1985 \n# $2 = merging stage \
1986 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1988 index = sjdl1.Index("JDLVariables");
1989 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1990 index = sjdl2.Index("JDLVariables");
1991 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1992 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1993 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1994 index = sjdl2.Index("Split =");
1996 index1 = sjdl2.Index("\n", index);
1997 sjdl2.Remove(index, index1-index+1);
1999 index = sjdl2.Index("SplitMaxInputFileNumber");
2001 index1 = sjdl2.Index("\n", index);
2002 sjdl2.Remove(index, index1-index+1);
2004 index = sjdl2.Index("InputDataCollection");
2006 index1 = sjdl2.Index(";", index);
2007 sjdl2.Remove(index, index1-index+1);
2009 index = sjdl2.Index("InputDataListFormat");
2011 index1 = sjdl2.Index("\n", index);
2012 sjdl2.Remove(index, index1-index+1);
2014 index = sjdl2.Index("InputDataList");
2016 index1 = sjdl2.Index("\n", index);
2017 sjdl2.Remove(index, index1-index+1);
2019 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
2020 // Write jdl to file
2022 out.open(fJDLName.Data(), ios::out);
2024 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2027 out << sjdl << endl;
2029 TString mergeJDLName = fExecutable;
2030 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2033 out1.open(mergeJDLName.Data(), ios::out);
2035 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2038 out1 << sjdl1 << endl;
2041 TString finalJDL = mergeJDLName;
2042 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2043 out2.open(finalJDL.Data(), ios::out);
2045 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2048 out2 << sjdl2 << endl;
2052 // Copy jdl to grid workspace
2054 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2056 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2057 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2058 TString finalJDL = mergeJDLName;
2059 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2060 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2061 if (fProductionMode) {
2062 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2063 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2064 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2066 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2067 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2068 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2069 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2070 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2071 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2072 Fatal("","Terminating");
2074 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2075 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2076 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2077 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2078 Fatal("","Terminating");
2079 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2080 Fatal("","Terminating");
2086 //______________________________________________________________________________
2087 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2089 // Returns true if file exists.
2090 if (!gGrid) return kFALSE;
2092 slfn.ReplaceAll("alien://","");
2093 TGridResult *res = gGrid->Ls(slfn);
2094 if (!res) return kFALSE;
2095 TMap *map = dynamic_cast<TMap*>(res->At(0));
2100 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2101 if (!objs || !objs->GetString().Length()) {
2109 //______________________________________________________________________________
2110 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2112 // Returns true if directory exists. Can be also a path.
2113 if (!gGrid) return kFALSE;
2114 // Check if dirname is a path
2115 TString dirstripped = dirname;
2116 dirstripped = dirstripped.Strip();
2117 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2118 TString dir = gSystem->BaseName(dirstripped);
2120 TString path = gSystem->DirName(dirstripped);
2121 TGridResult *res = gGrid->Ls(path, "-F");
2122 if (!res) return kFALSE;
2126 while ((map=dynamic_cast<TMap*>(next()))) {
2127 obj = map->GetValue("name");
2129 if (dir == obj->GetName()) {
2138 //______________________________________________________________________________
2139 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2141 // Check input data type.
2142 isCollection = kFALSE;
2146 Error("CheckDataType", "No connection to grid");
2149 isCollection = IsCollection(lfn);
2150 TString msg = "\n##### file: ";
2153 msg += " type: raw_collection;";
2154 // special treatment for collections
2156 // check for tag files in the collection
2157 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2159 msg += " using_tags: No (unknown)";
2160 Info("CheckDataType", "%s", msg.Data());
2163 const char* typeStr = res->GetKey(0, "origLFN");
2164 if (!typeStr || !strlen(typeStr)) {
2165 msg += " using_tags: No (unknown)";
2166 Info("CheckDataType", "%s", msg.Data());
2169 TString file = typeStr;
2170 useTags = file.Contains(".tag");
2171 if (useTags) msg += " using_tags: Yes";
2172 else msg += " using_tags: No";
2173 Info("CheckDataType", "%s", msg.Data());
2178 isXml = slfn.Contains(".xml");
2180 // Open xml collection and check if there are tag files inside
2181 msg += " type: xml_collection;";
2182 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2184 msg += " using_tags: No (unknown)";
2185 Info("CheckDataType", "%s", msg.Data());
2188 TMap *map = coll->Next();
2190 msg += " using_tags: No (unknown)";
2191 Info("CheckDataType", "%s", msg.Data());
2194 map = (TMap*)map->GetValue("");
2196 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2197 useTags = file.Contains(".tag");
2199 if (useTags) msg += " using_tags: Yes";
2200 else msg += " using_tags: No";
2201 Info("CheckDataType", "%s", msg.Data());
2204 useTags = slfn.Contains(".tag");
2205 if (slfn.Contains(".root")) msg += " type: root file;";
2206 else msg += " type: unknown file;";
2207 if (useTags) msg += " using_tags: Yes";
2208 else msg += " using_tags: No";
2209 Info("CheckDataType", "%s", msg.Data());
2212 //______________________________________________________________________________
2213 void AliAnalysisAlien::EnablePackage(const char *package)
2215 // Enables a par file supposed to exist in the current directory.
2216 TString pkg(package);
2217 pkg.ReplaceAll(".par", "");
2219 if (gSystem->AccessPathName(pkg)) {
2220 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2223 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2224 Info("EnablePackage", "AliEn plugin will use .par packages");
2225 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2227 fPackages = new TObjArray();
2228 fPackages->SetOwner();
2230 fPackages->Add(new TObjString(pkg));
2233 //______________________________________________________________________________
2234 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2236 // Make a tree from files having the location specified in fFileForTestMode.
2237 // Inspired from JF's CreateESDChain.
2238 if (fFileForTestMode.IsNull()) {
2239 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2242 if (gSystem->AccessPathName(fFileForTestMode)) {
2243 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2248 in.open(fFileForTestMode);
2250 // Read the input list of files and add them to the chain
2252 TString streeName(treeName);
2253 if (IsUseMCchain()) streeName = "TE";
2254 TChain *chain = new TChain(streeName);
2255 TChain *chainFriend = 0;
2256 if (!fFriendChainName.IsNull()) chainFriend = new TChain(streeName);
2260 if (line.IsNull() || line.BeginsWith("#")) continue;
2261 if (count++ == fNtestFiles) break;
2262 TString esdFile(line);
2263 TFile *file = TFile::Open(esdFile);
2264 if (file && !file->IsZombie()) {
2265 chain->Add(esdFile);
2267 if (!fFriendChainName.IsNull()) {
2268 if (esdFile.Index("#") > -1)
2269 esdFile.Remove(esdFile.Index("#"));
2270 esdFile = gSystem->DirName(esdFile);
2271 esdFile += "/" + fFriendChainName;
2272 file = TFile::Open(esdFile);
2273 if (file && !file->IsZombie()) {
2275 chainFriend->Add(esdFile);
2277 Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2282 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2286 if (!chain->GetListOfFiles()->GetEntries()) {
2287 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2293 if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2297 //______________________________________________________________________________
2298 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2300 // Get job status for all jobs with jobid>jobidstart.
2301 static char mstatus[20];
2307 TGridJobStatusList *list = gGrid->Ps("");
2308 if (!list) return mstatus;
2309 Int_t nentries = list->GetSize();
2310 TGridJobStatus *status;
2312 for (Int_t ijob=0; ijob<nentries; ijob++) {
2313 status = (TGridJobStatus *)list->At(ijob);
2314 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2315 if (pid<jobidstart) continue;
2316 if (pid == lastid) {
2317 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2319 switch (status->GetStatus()) {
2320 case TGridJobStatus::kWAITING:
2322 case TGridJobStatus::kRUNNING:
2324 case TGridJobStatus::kABORTED:
2325 case TGridJobStatus::kFAIL:
2326 case TGridJobStatus::kUNKNOWN:
2328 case TGridJobStatus::kDONE:
2337 //______________________________________________________________________________
2338 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2340 // Returns true if file is a collection. Functionality duplicated from
2341 // TAlien::Type() because we don't want to directly depend on TAlien.
2343 Error("IsCollection", "No connection to grid");
2346 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2347 if (!res) return kFALSE;
2348 const char* typeStr = res->GetKey(0, "type");
2349 if (!typeStr || !strlen(typeStr)) return kFALSE;
2350 if (!strcmp(typeStr, "collection")) return kTRUE;
2355 //______________________________________________________________________________
2356 Bool_t AliAnalysisAlien::IsSingleOutput() const
2358 // Check if single-ouput option is on.
2359 return (!fOutputSingle.IsNull());
2362 //______________________________________________________________________________
2363 void AliAnalysisAlien::Print(Option_t *) const
2365 // Print current plugin settings.
2366 printf("### AliEn analysis plugin current settings ###\n");
2367 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2368 if (mgr && mgr->IsProofMode()) {
2369 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2370 if (TestBit(AliAnalysisGrid::kTest))
2371 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2372 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2373 if (!fProofDataSet.IsNull())
2374 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2376 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2378 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2379 if (!fRootVersionForProof.IsNull())
2380 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2382 printf("= ROOT version requested________________________ default\n");
2383 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2384 if (!fAliRootMode.IsNull())
2385 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2387 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2388 if (fNproofWorkersPerSlave)
2389 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2390 if (TestSpecialBit(kClearPackages))
2391 printf("= ClearPackages requested...\n");
2392 if (fIncludePath.Data())
2393 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2394 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2395 if (fPackages && fPackages->GetEntries()) {
2396 TIter next(fPackages);
2399 while ((obj=next())) list += obj->GetName();
2400 printf("= Par files to be used: ________________________ %s\n", list.Data());
2402 if (TestSpecialBit(kProofConnectGrid))
2403 printf("= Requested PROOF connection to grid\n");
2406 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2407 if (fOverwriteMode) {
2408 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2409 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2411 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2412 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2413 printf("= Production mode:______________________________ %d\n", fProductionMode);
2414 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2415 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2416 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2418 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2419 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2420 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2421 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2422 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2423 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2424 if (fRunNumbers.Length())
2425 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2427 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2428 if (!fRunRange[0] && !fRunNumbers.Length()) {
2429 TIter next(fInputFiles);
2432 while ((obj=next())) list += obj->GetName();
2433 printf("= Input files to be processed: _________________ %s\n", list.Data());
2435 if (TestBit(AliAnalysisGrid::kTest))
2436 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2437 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2438 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2439 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2440 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2441 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2442 printf("=====================================================================\n");
2443 printf("= Job price: ___________________________________ %d\n", fPrice);
2444 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2445 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2446 if (fMaxInitFailed>0)
2447 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2448 if (fMasterResubmitThreshold>0)
2449 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2450 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2451 if (fNrunsPerMaster>0)
2452 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2453 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2454 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2455 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2456 if (fArguments.Length())
2457 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2458 if (fExecutableArgs.Length())
2459 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2460 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2461 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2462 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2463 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2465 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2466 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2467 if (fIncludePath.Data())
2468 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2469 if (fCloseSE.Length())
2470 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2471 if (fFriendChainName.Length())
2472 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2473 if (fPackages && fPackages->GetEntries()) {
2474 TIter next(fPackages);
2477 while ((obj=next())) list += obj->GetName();
2478 printf("= Par files to be used: ________________________ %s\n", list.Data());
2482 //______________________________________________________________________________
2483 void AliAnalysisAlien::SetDefaults()
2485 // Set default values for everything. What cannot be filled will be left empty.
2486 if (fGridJDL) delete fGridJDL;
2487 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2488 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2491 fSplitMaxInputFileNumber = 100;
2493 fMasterResubmitThreshold = 0;
2499 fNrunsPerMaster = 1;
2500 fMaxMergeFiles = 100;
2502 fExecutable = "analysis.sh";
2503 fExecutableCommand = "root -b -q";
2505 fExecutableArgs = "";
2506 fAnalysisMacro = "myAnalysis.C";
2507 fAnalysisSource = "";
2508 fAdditionalLibs = "";
2512 fAliROOTVersion = "";
2513 fUser = ""; // Your alien user name
2514 fGridWorkingDir = "";
2515 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2516 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2517 fFriendChainName = "";
2518 fGridOutputDir = "output";
2519 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2520 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2521 fInputFormat = "xml-single";
2522 fJDLName = "analysis.jdl";
2523 fJobTag = "Automatically generated analysis JDL";
2524 fMergeExcludes = "";
2527 SetCheckCopy(kTRUE);
2528 SetDefaultOutputs(kTRUE);
2532 //______________________________________________________________________________
2533 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2535 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2536 // First check if the result is already in the output directory.
2537 if (FileExists(Form("%s/%s",aliendir,filename))) {
2538 printf("Final merged results found. Not merging again.\n");
2541 // Now check the last stage done.
2544 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2547 // Next stage of merging
2549 TString pattern = "*root_archive.zip";
2550 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2551 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2552 if (res) delete res;
2553 // Write standard output to file
2554 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2555 // Count the number of files inside
2557 ifile.open(Form("Stage_%d.xml",stage));
2558 if (!ifile.good()) {
2559 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2564 while (!ifile.eof()) {
2566 if (line.Contains("/event")) nfiles++;
2570 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2573 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2575 // Copy the file in the output directory
2576 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2577 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2578 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2579 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2580 // Check if this is the last stage to be done.
2581 Bool_t laststage = (nfiles<nperchunk);
2582 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2584 printf("### Submiting final merging stage %d\n", stage);
2585 TString finalJDL = jdl;
2586 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2587 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2588 Int_t jobId = SubmitSingleJob(query);
2589 if (!jobId) return kFALSE;
2591 printf("### Submiting merging stage %d\n", stage);
2592 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2593 Int_t jobId = SubmitSingleJob(query);
2594 if (!jobId) return kFALSE;
2599 //______________________________________________________________________________
2600 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2602 // Loat the analysis manager from a file.
2603 TFile *file = TFile::Open(fname);
2605 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2608 TIter nextkey(file->GetListOfKeys());
2609 AliAnalysisManager *mgr = 0;
2611 while ((key=(TKey*)nextkey())) {
2612 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2613 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2616 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2620 //______________________________________________________________________________
2621 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2623 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2624 if (!gGrid) return 0;
2625 printf("=> %s ------> ",query);
2626 TGridResult *res = gGrid->Command(query);
2628 TString jobId = res->GetKey(0,"jobId");
2630 if (jobId.IsNull()) {
2631 printf("submission failed. Reason:\n");
2634 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2637 printf(" Job id: %s\n", jobId.Data());
2641 //______________________________________________________________________________
2642 Bool_t AliAnalysisAlien::MergeInfo(const char *output, const char *collection)
2644 // Merges a collection of output files using concatenation.
2645 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", collection));
2647 ::Error("MergeInfo", "Input XML %s collection empty.", collection);
2650 // Iterate grid collection
2652 Bool_t merged = kFALSE;
2654 while (coll->Next()) {
2655 TString fname = gSystem->DirName(coll->GetTURL());
2658 outtmp = Form("%d_%s", ifile, output);
2659 if (!TFile::Cp(fname, outtmp)) {
2660 ::Error("MergeInfo", "Could not copy %s", fname.Data());
2665 gSystem->Exec(Form("cp %s lastmerged", outtmp.Data()));
2668 gSystem->Exec(Form("cat lastmerged %s > tempmerged", outtmp.Data()));
2669 gSystem->Exec("cp tempmerged lastmerged");
2672 gSystem->Exec(Form("cp lastmerged %s", output));
2673 gSystem->Exec(Form("rm tempmerged lastmerged *_%s", output));
2679 //______________________________________________________________________________
2680 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2682 // Merge given output files from basedir. Basedir can be an alien output directory
2683 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2684 // files in a group (ignored for xml input). Merging can be done in stages:
2685 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2686 // stage=1 : works with an xml of all root_archive.zip in the output directory
2687 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2688 TString outputFile = output;
2690 TString outputChunk;
2691 TString previousChunk = "";
2692 TObjArray *listoffiles = new TObjArray();
2693 // listoffiles->SetOwner();
2694 Int_t countChunk = 0;
2695 Int_t countZero = nmaxmerge;
2696 Bool_t merged = kTRUE;
2697 Int_t index = outputFile.Index("@");
2698 if (index > 0) outputFile.Remove(index);
2699 TString inputFile = outputFile;
2700 TString sbasedir = basedir;
2701 if (sbasedir.Contains(".xml")) {
2702 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2703 nmaxmerge = 9999999;
2704 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2706 ::Error("MergeOutput", "Input XML collection empty.");
2709 // Iterate grid collection
2710 while (coll->Next()) {
2711 TString fname = gSystem->DirName(coll->GetTURL());
2714 listoffiles->Add(new TNamed(fname.Data(),""));
2716 } else if (sbasedir.Contains(".txt")) {
2717 // Assume lfn's on each line
2724 if (line.IsNull() || line.BeginsWith("#")) continue;
2726 listoffiles->Add(new TNamed(line.Data(),""));
2729 ::Error("MergeOutput","Input file %s contains no files to be merged\n", sbasedir.Data());
2734 command = Form("find %s/ *%s", basedir, inputFile.Data());
2735 printf("command: %s\n", command.Data());
2736 TGridResult *res = gGrid->Command(command);
2738 ::Error("MergeOutput","No result for the find command\n");
2744 while ((map=(TMap*)nextmap())) {
2745 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2746 if (!objs || !objs->GetString().Length()) {
2747 // Nothing found - skip this output
2752 listoffiles->Add(new TNamed(objs->GetName(),""));
2756 if (!listoffiles->GetEntries()) {
2757 ::Error("MergeOutput","No result for the find command\n");
2762 TFileMerger *fm = 0;
2763 TIter next0(listoffiles);
2764 TObjArray *listoffilestmp = new TObjArray();
2765 listoffilestmp->SetOwner();
2768 // Keep only the files at upper level
2769 Int_t countChar = 0;
2770 while ((nextfile=next0())) {
2771 snextfile = nextfile->GetName();
2772 Int_t crtCount = snextfile.CountChar('/');
2773 if (nextfile == listoffiles->First()) countChar = crtCount;
2774 if (crtCount < countChar) countChar = crtCount;
2777 while ((nextfile=next0())) {
2778 snextfile = nextfile->GetName();
2779 Int_t crtCount = snextfile.CountChar('/');
2780 if (crtCount > countChar) {
2784 listoffilestmp->Add(nextfile);
2787 listoffiles = listoffilestmp; // Now contains 'good' files
2788 listoffiles->Print();
2789 TIter next(listoffiles);
2790 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2791 outputChunk = outputFile;
2792 outputChunk.ReplaceAll(".root", "_*.root");
2793 // Check for existent temporary merge files
2794 // Check overwrite mode and remove previous partial results if needed
2795 // Preserve old merging functionality for stage 0.
2797 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2799 // Skip as many input files as in a chunk
2800 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2803 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2807 snextfile = nextfile->GetName();
2809 outputChunk = outputFile;
2810 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2812 if (gSystem->AccessPathName(outputChunk)) continue;
2813 // Merged file with chunks up to <countChunk> found
2814 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2815 previousChunk = outputChunk;
2819 countZero = nmaxmerge;
2821 while ((nextfile=next())) {
2822 snextfile = nextfile->GetName();
2823 // Loop 'find' results and get next LFN
2824 if (countZero == nmaxmerge) {
2825 // First file in chunk - create file merger and add previous chunk if any.
2826 fm = new TFileMerger(kTRUE);
2827 fm->SetFastMethod(kTRUE);
2828 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2829 outputChunk = outputFile;
2830 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2832 // If last file found, put merged results in the output file
2833 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2834 // Add file to be merged and decrement chunk counter.
2835 fm->AddFile(snextfile);
2837 if (countZero==0 || nextfile == listoffiles->Last()) {
2838 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2839 // Nothing found - skip this output
2840 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2844 fm->OutputFile(outputChunk);
2845 // Merge the outputs, then go to next chunk
2847 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2851 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2852 gSystem->Unlink(previousChunk);
2854 if (nextfile == listoffiles->Last()) break;
2856 countZero = nmaxmerge;
2857 previousChunk = outputChunk;
2864 // Merging stage different than 0.
2865 // Move to the begining of the requested chunk.
2866 fm = new TFileMerger(kTRUE);
2867 fm->SetFastMethod(kTRUE);
2868 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2870 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2871 // Nothing found - skip this output
2872 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2876 fm->OutputFile(outputFile);
2877 // Merge the outputs
2879 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2883 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2889 //______________________________________________________________________________
2890 Bool_t AliAnalysisAlien::MergeOutputs()
2892 // Merge analysis outputs existing in the AliEn space.
2893 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2894 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2896 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2900 if (!TestBit(AliAnalysisGrid::kMerge)) {
2901 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2904 if (fProductionMode) {
2905 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2908 Info("MergeOutputs", "Submitting merging JDL");
2909 if (!SubmitMerging()) return kFALSE;
2910 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2911 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2914 // Get the output path
2915 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2916 if (!DirectoryExists(fGridOutputDir)) {
2917 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2920 if (!fOutputFiles.Length()) {
2921 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2924 // Check if fast read option was requested
2925 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2926 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2927 if (fFastReadOption) {
2928 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2929 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2930 gEnv->SetValue("XNet.ConnectTimeout",50);
2931 gEnv->SetValue("XNet.RequestTimeout",50);
2932 gEnv->SetValue("XNet.MaxRedirectCount",2);
2933 gEnv->SetValue("XNet.ReconnectTimeout",50);
2934 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2936 // Make sure we change the temporary directory
2937 gSystem->Setenv("TMPDIR", gSystem->pwd());
2938 // Set temporary compilation directory to current one
2939 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2940 TObjArray *list = fOutputFiles.Tokenize(",");
2944 Bool_t merged = kTRUE;
2945 while((str=(TObjString*)next())) {
2946 outputFile = str->GetString();
2947 Int_t index = outputFile.Index("@");
2948 if (index > 0) outputFile.Remove(index);
2949 TString outputChunk = outputFile;
2950 outputChunk.ReplaceAll(".root", "_*.root");
2951 // Skip already merged outputs
2952 if (!gSystem->AccessPathName(outputFile)) {
2953 if (fOverwriteMode) {
2954 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2955 gSystem->Unlink(outputFile);
2956 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2957 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2958 outputChunk.Data());
2959 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2962 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2966 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2967 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2968 outputChunk.Data());
2969 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2972 if (fMergeExcludes.Contains(outputFile.Data()) ||
2973 fRegisterExcludes.Contains(outputFile.Data())) continue;
2974 // Perform a 'find' command in the output directory, looking for registered outputs
2975 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2977 Error("MergeOutputs", "Terminate() will NOT be executed");
2980 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2981 if (fileOpened) fileOpened->Close();
2986 //______________________________________________________________________________
2987 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2989 // Use the output files connected to output containers from the analysis manager
2990 // rather than the files defined by SetOutputFiles
2991 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2992 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2993 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2996 //______________________________________________________________________________
2997 void AliAnalysisAlien::SetOutputFiles(const char *list)
2999 // Manually set the output files list.
3000 // Removes duplicates. Not allowed if default outputs are not disabled.
3001 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3002 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
3005 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
3007 TString slist = list;
3008 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
3009 TObjArray *arr = slist.Tokenize(" ");
3013 while ((os=(TObjString*)next())) {
3014 sout = os->GetString();
3015 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
3016 if (fOutputFiles.Contains(sout)) continue;
3017 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3018 fOutputFiles += sout;
3023 //______________________________________________________________________________
3024 void AliAnalysisAlien::SetOutputArchive(const char *list)
3026 // Manually set the output archive list. Free text - you are on your own...
3027 // Not allowed if default outputs are not disabled.
3028 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3029 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
3032 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
3033 fOutputArchive = list;
3036 //______________________________________________________________________________
3037 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
3039 // Setting a prefered output SE is not allowed anymore.
3040 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
3043 //______________________________________________________________________________
3044 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
3046 // Set some PROOF special parameter.
3047 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
3049 TObject *old = pair->Key();
3050 TObject *val = pair->Value();
3051 fProofParam.Remove(old);
3055 fProofParam.Add(new TObjString(pname), new TObjString(value));
3058 //______________________________________________________________________________
3059 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
3061 // Returns a special PROOF parameter.
3062 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
3063 if (!pair) return 0;
3064 return pair->Value()->GetName();
3067 //______________________________________________________________________________
3068 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
3070 // Start remote grid analysis.
3071 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3072 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
3073 if (!mgr || !mgr->IsInitialized()) {
3074 Error("StartAnalysis", "You need an initialized analysis manager for this");
3077 // Are we in PROOF mode ?
3078 if (mgr->IsProofMode()) {
3079 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
3080 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3081 if (fProofCluster.IsNull()) {
3082 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3085 if (fProofDataSet.IsNull() && !testMode) {
3086 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3089 // Set the needed environment
3090 gEnv->SetValue("XSec.GSI.DelegProxy","2");
3091 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3092 if (fProofReset && !testMode) {
3093 if (fProofReset==1) {
3094 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3095 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3097 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3098 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3100 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3105 // Check if there is an old active session
3106 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3108 Error("StartAnalysis","You have to reset your old session first\n");
3112 // Do we need to change the ROOT version ? The success of this cannot be checked.
3113 if (!fRootVersionForProof.IsNull() && !testMode) {
3114 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
3115 fProofCluster.Data(), fRootVersionForProof.Data()));
3117 // Connect to PROOF and check the status
3120 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3121 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3123 if (!sworkers.IsNull())
3124 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3126 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3128 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3130 Error("StartAnalysis", "Could not start PROOF in test mode");
3135 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3138 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3139 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3140 // Set proof special parameters if any
3141 TIter nextpp(&fProofParam);
3142 TObject *proofparam;
3143 while ((proofparam=nextpp())) {
3144 TString svalue = GetProofParameter(proofparam->GetName());
3145 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3147 // Is dataset existing ?
3149 TString dataset = fProofDataSet;
3150 Int_t index = dataset.Index("#");
3151 if (index>=0) dataset.Remove(index);
3152 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3153 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3156 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3158 // Is ClearPackages() needed ?
3159 if (TestSpecialBit(kClearPackages)) {
3160 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3161 gROOT->ProcessLine("gProof->ClearPackages();");
3163 // Is a given aliroot mode requested ?
3166 if (!fAliRootMode.IsNull()) {
3167 TString alirootMode = fAliRootMode;
3168 if (alirootMode == "default") alirootMode = "";
3169 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3170 optionsList.SetOwner();
3171 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3172 // Check the additional libs to be loaded
3174 Bool_t parMode = kFALSE;
3175 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3176 // Parse the extra libs for .so
3177 if (fAdditionalLibs.Length()) {
3178 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3181 while((str=(TObjString*)next())) {
3182 if (str->GetString().Contains(".so")) {
3184 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());
3187 TString stmp = str->GetName();
3188 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3189 stmp.ReplaceAll(".so","");
3190 if (!extraLibs.IsNull()) extraLibs += ":";
3194 if (str->GetString().Contains(".par")) {
3195 // The first par file found in the list will not allow any further .so
3197 if (!parLibs.IsNull()) parLibs += ":";
3198 parLibs += str->GetName();
3202 if (list) delete list;
3204 if (!extraLibs.IsNull()) {
3205 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3206 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3208 // Check extra includes
3209 if (!fIncludePath.IsNull()) {
3210 TString includePath = fIncludePath;
3211 includePath.ReplaceAll(" ",":");
3212 includePath.ReplaceAll("$ALICE_ROOT/","");
3213 includePath.ReplaceAll("${ALICE_ROOT}/","");
3214 includePath.ReplaceAll("-I","");
3215 includePath.Remove(TString::kTrailing, ':');
3216 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3217 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3219 // Check if connection to grid is requested
3220 if (TestSpecialBit(kProofConnectGrid))
3221 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3222 // Enable AliRoot par
3224 // Enable proof lite package
3225 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3226 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3227 TNamed *obj = (TNamed*)optionsList.At(i);
3228 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3230 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3231 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3232 Info("StartAnalysis", "AliRootProofLite enabled");
3234 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3238 if ( ! fAliROOTVersion.IsNull() ) {
3239 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3240 fAliROOTVersion.Data(), &optionsList))) {
3241 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3246 // Enable first par files from fAdditionalLibs
3247 if (!parLibs.IsNull()) {
3248 TObjArray *list = parLibs.Tokenize(":");
3250 TObjString *package;
3251 while((package=(TObjString*)next())) {
3252 TString spkg = package->GetName();
3253 spkg.ReplaceAll(".par", "");
3254 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3255 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3256 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3257 if (gROOT->ProcessLine(enablePackage)) {
3258 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3262 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3266 if (list) delete list;
3269 if (fAdditionalLibs.Contains(".so") && !testMode) {
3270 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3271 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3275 // Enable par files if requested
3276 if (fPackages && fPackages->GetEntries()) {
3277 TIter next(fPackages);
3279 while ((package=next())) {
3280 // Skip packages already enabled
3281 if (parLibs.Contains(package->GetName())) continue;
3282 TString spkg = package->GetName();
3283 spkg.ReplaceAll(".par", "");
3284 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3285 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3286 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3287 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3291 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3296 // Do we need to load analysis source files ?
3297 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3298 if (fAnalysisSource.Length()) {
3299 TObjArray *list = fAnalysisSource.Tokenize(" ");
3302 while((str=(TObjString*)next())) {
3303 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3305 if (list) delete list;
3308 // Register dataset to proof lite.
3309 if (fFileForTestMode.IsNull()) {
3310 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3313 if (gSystem->AccessPathName(fFileForTestMode)) {
3314 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3317 TFileCollection *coll = new TFileCollection();
3318 coll->AddFromFile(fFileForTestMode);
3319 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3320 gROOT->ProcessLine("gProof->ShowDataSets()");
3325 // Check if output files have to be taken from the analysis manager
3326 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3327 // Add output files and AOD files
3328 fOutputFiles = GetListOfFiles("outaod");
3329 // Add extra files registered to the analysis manager
3330 TString extra = GetListOfFiles("ext");
3331 if (!extra.IsNull()) {
3332 extra.ReplaceAll(".root", "*.root");
3333 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3334 fOutputFiles += extra;
3336 // Compose the output archive.
3337 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3338 if (mgr->IsCollectThroughput())
3339 fOutputArchive += Form("root_archive.zip:%s,*.stat,*%s@disk=%d",fOutputFiles.Data(),mgr->GetFileInfoLog(),fNreplicas);
3341 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3343 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3344 if (TestBit(AliAnalysisGrid::kOffline)) {
3345 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3346 \n there nor any job run. You can revise the JDL and analysis \
3347 \n macro then run the same in \"submit\" mode.");
3348 } else if (TestBit(AliAnalysisGrid::kTest)) {
3349 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3351 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3352 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3353 \n space and job submitted.");
3354 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3355 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3356 if (fMergeViaJDL) CheckInputData();
3359 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3364 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3367 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3368 if (!CheckInputData()) {
3369 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3372 if (!CreateDataset(fDataPattern)) {
3374 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3375 if (fRunNumbers.Length()) serror = "run numbers";
3376 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3377 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3378 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3381 WriteAnalysisFile();
3382 WriteAnalysisMacro();
3384 WriteValidationScript();
3386 WriteMergingMacro();
3387 WriteMergeExecutable();
3388 WriteValidationScript(kTRUE);
3390 if (!CreateJDL()) return kFALSE;
3391 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3393 // Locally testing the analysis
3394 Info("StartAnalysis", "\n_______________________________________________________________________ \
3395 \n Running analysis script in a daughter shell as on a worker node \
3396 \n_______________________________________________________________________");
3397 TObjArray *list = fOutputFiles.Tokenize(",");
3401 while((str=(TObjString*)next())) {
3402 outputFile = str->GetString();
3403 Int_t index = outputFile.Index("@");
3404 if (index > 0) outputFile.Remove(index);
3405 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3408 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3409 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3410 // gSystem->Exec("cat stdout");
3413 // Check if submitting is managed by LPM manager
3414 if (fProductionMode) {
3415 //TString prodfile = fJDLName;
3416 //prodfile.ReplaceAll(".jdl", ".prod");
3417 //WriteProductionFile(prodfile);
3418 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3421 // Submit AliEn job(s)
3422 gGrid->Cd(fGridOutputDir);
3425 if (!fRunNumbers.Length() && !fRunRange[0]) {
3426 // Submit a given xml or a set of runs
3427 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3428 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3430 const char *cjobId = res->GetKey(0,"jobId");
3434 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3437 Info("StartAnalysis", "\n_______________________________________________________________________ \
3438 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3439 \n_______________________________________________________________________",
3440 fJDLName.Data(), cjobId);
3445 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3449 // Submit for a range of enumeration of runs.
3450 if (!Submit()) return kFALSE;
3453 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3454 \n You may exit at any time and terminate the job later using the option <terminate> \
3455 \n ##################################################################################", jobID.Data());
3456 gSystem->Exec("aliensh");
3460 //______________________________________________________________________________
3461 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3463 // Get a comma-separated list of output files of the requested type.
3464 // Type can be (case unsensitive):
3465 // aod - list of aod files (std, extensions and filters)
3466 // out - list of output files connected to containers (but not aod's or extras)
3467 // ext - list of extra files registered to the manager
3468 // ter - list of files produced in terminate
3469 static TString files;
3471 TString stype = type;
3473 TString aodfiles, extra;
3474 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3476 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3477 return files.Data();
3479 if (mgr->GetOutputEventHandler()) {
3480 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3481 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3482 if (!extraaod.IsNull()) {
3484 aodfiles += extraaod;
3487 if (stype.Contains("aod")) {
3489 if (stype == "aod") return files.Data();
3491 // Add output files that are not in the list of AOD files
3492 TString outputfiles = "";
3493 TIter next(mgr->GetOutputs());
3494 AliAnalysisDataContainer *output;
3495 const char *filename = 0;
3496 while ((output=(AliAnalysisDataContainer*)next())) {
3497 filename = output->GetFileName();
3498 if (!(strcmp(filename, "default"))) continue;
3499 if (outputfiles.Contains(filename)) continue;
3500 if (aodfiles.Contains(filename)) continue;
3501 if (!outputfiles.IsNull()) outputfiles += ",";
3502 outputfiles += filename;
3504 if (stype.Contains("out")) {
3505 if (!files.IsNull()) files += ",";
3506 files += outputfiles;
3507 if (stype == "out") return files.Data();
3509 // Add extra files registered to the analysis manager
3511 extra = mgr->GetExtraFiles();
3512 if (!extra.IsNull()) {
3514 extra.ReplaceAll(" ", ",");
3515 TObjArray *fextra = extra.Tokenize(",");
3516 TIter nextx(fextra);
3518 while ((obj=nextx())) {
3519 if (aodfiles.Contains(obj->GetName())) continue;
3520 if (outputfiles.Contains(obj->GetName())) continue;
3521 if (sextra.Contains(obj->GetName())) continue;
3522 if (!sextra.IsNull()) sextra += ",";
3523 sextra += obj->GetName();
3526 if (stype.Contains("ext")) {
3527 if (!files.IsNull()) files += ",";
3531 if (stype == "ext") return files.Data();
3533 if (!fTerminateFiles.IsNull()) {
3534 fTerminateFiles.Strip();
3535 fTerminateFiles.ReplaceAll(" ",",");
3536 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3537 TIter nextx(fextra);
3539 while ((obj=nextx())) {
3540 if (aodfiles.Contains(obj->GetName())) continue;
3541 if (outputfiles.Contains(obj->GetName())) continue;
3542 if (termfiles.Contains(obj->GetName())) continue;
3543 if (sextra.Contains(obj->GetName())) continue;
3544 if (!termfiles.IsNull()) termfiles += ",";
3545 termfiles += obj->GetName();
3549 if (stype.Contains("ter")) {
3550 if (!files.IsNull() && !termfiles.IsNull()) {
3555 return files.Data();
3558 //______________________________________________________________________________
3559 Bool_t AliAnalysisAlien::Submit()
3561 // Submit all master jobs.
3562 Int_t nmasterjobs = fInputFiles->GetEntries();
3563 Long_t tshoot = gSystem->Now();
3564 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3565 while (fNsubmitted < nmasterjobs) {
3566 Long_t now = gSystem->Now();
3567 if ((now-tshoot)>30000) {
3569 if (!SubmitNext()) return kFALSE;
3575 //______________________________________________________________________________
3576 Bool_t AliAnalysisAlien::SubmitMerging()
3578 // Submit all merging jobs.
3579 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3580 gGrid->Cd(fGridOutputDir);
3581 TString mergeJDLName = fExecutable;
3582 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3584 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3587 Int_t ntosubmit = fInputFiles->GetEntries();
3588 for (Int_t i=0; i<ntosubmit; i++) {
3589 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3590 runOutDir.ReplaceAll(".xml", "");
3591 if (fOutputToRunNo) {
3592 // The output directory is the run number
3593 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3594 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3596 if (!fRunNumbers.Length() && !fRunRange[0]) {
3597 // The output directory is the grid outdir
3598 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3599 runOutDir = fGridOutputDir;
3601 // The output directory is the master number in 3 digits format
3602 printf("### Submitting merging job for master <%03d>\n", i);
3603 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3606 // Check now the number of merging stages.
3607 TObjArray *list = fOutputFiles.Tokenize(",");
3611 while((str=(TObjString*)next())) {
3612 outputFile = str->GetString();
3613 Int_t index = outputFile.Index("@");
3614 if (index > 0) outputFile.Remove(index);
3615 if (!fMergeExcludes.Contains(outputFile) &&
3616 !fRegisterExcludes.Contains(outputFile)) break;
3619 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3620 if (!done && (i==ntosubmit-1)) return kFALSE;
3621 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3623 if (!ntosubmit) return kTRUE;
3624 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3625 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3626 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3627 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3628 \n ################################################################################################################");
3629 gSystem->Exec("aliensh");
3633 //______________________________________________________________________________
3634 Bool_t AliAnalysisAlien::SubmitNext()
3636 // Submit next bunch of master jobs if the queue is free. The first master job is
3637 // submitted right away, while the next will not be unless the previous was split.
3638 // The plugin will not submit new master jobs if there are more that 500 jobs in
3640 static Bool_t iscalled = kFALSE;
3641 static Int_t firstmaster = 0;
3642 static Int_t lastmaster = 0;
3643 static Int_t npermaster = 0;
3644 if (iscalled) return kTRUE;
3646 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3647 Int_t ntosubmit = 0;
3650 Int_t nmasterjobs = fInputFiles->GetEntries();
3653 if (!IsUseSubmitPolicy()) {
3655 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3656 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3657 ntosubmit = nmasterjobs;
3660 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3661 printf("=== master %d: %s\n", lastmaster, status.Data());
3662 // If last master not split, just return
3663 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3664 // No more than 100 waiting jobs
3665 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3666 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3667 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3668 if (!ntosubmit) ntosubmit = 1;
3669 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3670 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3672 for (Int_t i=0; i<ntosubmit; i++) {
3673 // Submit for a range of enumeration of runs.
3674 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3676 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3677 runOutDir.ReplaceAll(".xml", "");
3679 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3681 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3682 printf("********* %s\n",query.Data());
3683 res = gGrid->Command(query);
3685 TString cjobId1 = res->GetKey(0,"jobId");
3686 if (!cjobId1.Length()) {
3690 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3693 Info("StartAnalysis", "\n_______________________________________________________________________ \
3694 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3695 \n_______________________________________________________________________",
3696 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3699 lastmaster = cjobId1.Atoi();
3700 if (!firstmaster) firstmaster = lastmaster;
3705 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3713 //______________________________________________________________________________
3714 void AliAnalysisAlien::WriteAnalysisFile()
3716 // Write current analysis manager into the file <analysisFile>
3717 TString analysisFile = fExecutable;
3718 analysisFile.ReplaceAll(".sh", ".root");
3719 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3720 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3721 if (!mgr || !mgr->IsInitialized()) {
3722 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3725 // Check analysis type
3727 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3728 handler = (TObject*)mgr->GetInputEventHandler();
3730 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3731 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3732 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3733 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3735 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3736 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3739 TDirectory *cdir = gDirectory;
3740 TFile *file = TFile::Open(analysisFile, "RECREATE");
3742 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3743 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3744 // Unless merging makes no sense
3745 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3748 // Enable termination for local jobs
3749 mgr->SetSkipTerminate(kFALSE);
3751 if (cdir) cdir->cd();
3752 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3754 Bool_t copy = kTRUE;
3755 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3758 TString workdir = gGrid->GetHomeDirectory();
3759 workdir += fGridWorkingDir;
3760 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3761 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3762 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3763 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3767 //______________________________________________________________________________
3768 void AliAnalysisAlien::WriteAnalysisMacro()
3770 // Write the analysis macro that will steer the analysis in grid mode.
3771 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3773 out.open(fAnalysisMacro.Data(), ios::out);
3775 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3778 Bool_t hasSTEERBase = kFALSE;
3779 Bool_t hasESD = kFALSE;
3780 Bool_t hasAOD = kFALSE;
3781 Bool_t hasANALYSIS = kFALSE;
3782 Bool_t hasOADB = kFALSE;
3783 Bool_t hasANALYSISalice = kFALSE;
3784 Bool_t hasCORRFW = kFALSE;
3785 TString func = fAnalysisMacro;
3786 TString type = "ESD";
3787 TString comment = "// Analysis using ";
3788 if (IsUseMCchain()) {
3792 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3793 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3798 if (type!="AOD" && fFriendChainName!="") {
3799 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3802 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3803 else comment += " data";
3804 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3805 func.ReplaceAll(".C", "");
3806 out << "void " << func.Data() << "()" << endl;
3808 out << comment.Data() << endl;
3809 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3810 out << " TStopwatch timer;" << endl;
3811 out << " timer.Start();" << endl << endl;
3812 // Change temp directory to current one
3813 if (!IsLocalTest()) {
3814 out << "// connect to AliEn and make the chain" << endl;
3815 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3817 out << "// Set temporary merging directory to current one" << endl;
3818 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3819 out << "// Set temporary compilation directory to current one" << endl;
3820 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3821 // Reset existing include path
3822 out << "// Reset existing include path and add current directory first in the search" << endl;
3823 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3824 if (!fExecutableCommand.Contains("aliroot")) {
3825 out << "// load base root libraries" << endl;
3826 out << " gSystem->Load(\"libTree\");" << endl;
3827 out << " gSystem->Load(\"libGeom\");" << endl;
3828 out << " gSystem->Load(\"libVMC\");" << endl;
3829 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3830 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3832 if (fAdditionalRootLibs.Length()) {
3833 // in principle libtree /lib geom libvmc etc. can go into this list, too
3834 out << "// Add aditional libraries" << endl;
3835 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3838 while((str=(TObjString*)next())) {
3839 if (str->GetString().Contains(".so"))
3840 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3842 if (list) delete list;
3844 out << "// Load analysis framework libraries" << endl;
3845 TString setupPar = "AliAnalysisAlien::SetupPar";
3847 if (!fExecutableCommand.Contains("aliroot")) {
3848 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3849 out << " gSystem->Load(\"libESD\");" << endl;
3850 out << " gSystem->Load(\"libAOD\");" << endl;
3852 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3853 out << " gSystem->Load(\"libOADB\");" << endl;
3854 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3855 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3857 TIter next(fPackages);
3860 while ((obj=next())) {
3861 pkgname = obj->GetName();
3862 if (pkgname == "STEERBase" ||
3863 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3864 if (pkgname == "ESD" ||
3865 pkgname == "ESD.par") hasESD = kTRUE;
3866 if (pkgname == "AOD" ||
3867 pkgname == "AOD.par") hasAOD = kTRUE;
3868 if (pkgname == "ANALYSIS" ||
3869 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3870 if (pkgname == "OADB" ||
3871 pkgname == "OADB.par") hasOADB = kTRUE;
3872 if (pkgname == "ANALYSISalice" ||
3873 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3874 if (pkgname == "CORRFW" ||
3875 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3877 if (hasANALYSISalice) setupPar = "SetupPar";
3878 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3879 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3880 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3881 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3882 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3883 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3884 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3885 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3886 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3887 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3888 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3889 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3890 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3891 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3892 out << "// Compile other par packages" << endl;
3894 while ((obj=next())) {
3895 pkgname = obj->GetName();
3896 if (pkgname == "STEERBase" ||
3897 pkgname == "STEERBase.par" ||
3899 pkgname == "ESD.par" ||
3901 pkgname == "AOD.par" ||
3902 pkgname == "ANALYSIS" ||
3903 pkgname == "ANALYSIS.par" ||
3904 pkgname == "OADB" ||
3905 pkgname == "OADB.par" ||
3906 pkgname == "ANALYSISalice" ||
3907 pkgname == "ANALYSISalice.par" ||
3908 pkgname == "CORRFW" ||
3909 pkgname == "CORRFW.par") continue;
3910 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3913 out << "// include path" << endl;
3914 // Get the include path from the interpreter and remove entries pointing to AliRoot
3915 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3916 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3917 out << " TIter nextpath(listpaths);" << endl;
3918 out << " TObjString *pname;" << endl;
3919 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3920 out << " TString current = pname->GetName();" << endl;
3921 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3922 out << " gSystem->AddIncludePath(current);" << endl;
3923 out << " }" << endl;
3924 out << " if (listpaths) delete listpaths;" << endl;
3925 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3926 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3927 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3928 if (fAdditionalLibs.Length()) {
3929 out << "// Add aditional AliRoot libraries" << endl;
3930 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3933 while((str=(TObjString*)next())) {
3934 if (str->GetString().Contains(".so"))
3935 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3936 if (str->GetString().Contains(".par"))
3937 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3939 if (list) delete list;
3942 out << "// analysis source to be compiled at runtime (if any)" << endl;
3943 if (fAnalysisSource.Length()) {
3944 TObjArray *list = fAnalysisSource.Tokenize(" ");
3947 while((str=(TObjString*)next())) {
3948 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3950 if (list) delete list;
3953 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3954 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3955 if (fFastReadOption) {
3956 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 !!! \
3957 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3958 out << "// fast xrootd reading enabled" << endl;
3959 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3960 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3961 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3962 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3963 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3964 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3966 out << "// read the analysis manager from file" << endl;
3967 TString analysisFile = fExecutable;
3968 analysisFile.ReplaceAll(".sh", ".root");
3969 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3970 << analysisFile << "\");" << endl;
3971 out << " if (!mgr) return;" << endl;
3972 if (IsLocalTest()) {
3973 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3974 out << " plugin->SetRunMode(\"test\");" << endl;
3975 if (fFileForTestMode.IsNull())
3976 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3978 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3979 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3980 if (!fFriendChainName.IsNull())
3981 out << " plugin->SetFriendChainName(\"" << fFriendChainName << "\");" << endl;
3983 out << " plugin->SetUseMCchain();" << endl;
3984 out << " mgr->SetGridHandler(plugin);" << endl;
3985 if (AliAnalysisManager::GetAnalysisManager()) {
3986 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3987 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3989 out << " mgr->SetDebugLevel(10);" << endl;
3990 out << " mgr->SetNSysInfo(100);" << endl;
3993 out << " mgr->PrintStatus();" << endl;
3994 if (AliAnalysisManager::GetAnalysisManager()) {
3995 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3996 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3998 if (TestBit(AliAnalysisGrid::kTest))
3999 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4001 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4004 if (!IsLocalTest()) {
4005 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
4006 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
4008 out << " mgr->StartAnalysis(\"localfile\");" << endl;
4010 out << " timer.Stop();" << endl;
4011 out << " timer.Print();" << endl;
4012 out << "}" << endl << endl;
4013 if (!IsLocalTest()) {
4014 out <<"//________________________________________________________________________________" << endl;
4015 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
4017 out << "// Create a chain using url's from xml file" << endl;
4018 out << " TString filename;" << endl;
4019 out << " Int_t run = 0;" << endl;
4020 if (IsUseMCchain()) {
4021 out << " TString treename = \"TE\";" << endl;
4023 out << " TString treename = type;" << endl;
4024 out << " treename.ToLower();" << endl;
4025 out << " treename += \"Tree\";" << endl;
4027 out << " printf(\"***************************************\\n\");" << endl;
4028 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
4029 out << " printf(\"***************************************\\n\");" << endl;
4030 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
4031 out << " if (!coll) {" << endl;
4032 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
4033 out << " return NULL;" << endl;
4034 out << " }" << endl;
4035 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
4036 out << " TChain *chain = new TChain(treename);" << endl;
4037 if(fFriendChainName!="") {
4038 out << " TChain *chainFriend = new TChain(treename);" << endl;
4040 out << " coll->Reset();" << endl;
4041 out << " while (coll->Next()) {" << endl;
4042 out << " filename = coll->GetTURL("");" << endl;
4043 out << " if (mgr) {" << endl;
4044 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
4045 out << " if (nrun && nrun != run) {" << endl;
4046 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
4047 out << " mgr->SetRunFromPath(nrun);" << endl;
4048 out << " run = nrun;" << endl;
4049 out << " }" << endl;
4050 out << " }" << endl;
4051 out << " chain->Add(filename);" << endl;
4052 if(fFriendChainName!="") {
4053 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
4054 out << " if (fileFriend.Index(\"#\") > -1) fileFriend.Remove(fileFriend.Index(\"#\"));" << endl;
4055 out << " fileFriend = gSystem->DirName(fileFriend);" << endl;
4056 out << " fileFriend += \"/\";" << endl;
4057 out << " fileFriend += \"" << fFriendChainName << "\";";
4058 out << " TFile *file = TFile::Open(fileFriend);" << endl;
4059 out << " if (file) {" << endl;
4060 out << " file->Close();" << endl;
4061 out << " chainFriend->Add(fileFriend.Data());" << endl;
4062 out << " } else {" << endl;
4063 out << " ::Fatal(\"CreateChain\", \"Cannot open friend file: %s\", fileFriend.Data());" << endl;
4064 out << " return 0;" << endl;
4065 out << " }" << endl;
4067 out << " }" << endl;
4068 out << " if (!chain->GetNtrees()) {" << endl;
4069 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
4070 out << " return NULL;" << endl;
4071 out << " }" << endl;
4072 if(fFriendChainName!="") {
4073 out << " chain->AddFriend(chainFriend);" << endl;
4075 out << " return chain;" << endl;
4076 out << "}" << endl << endl;
4078 if (hasANALYSISalice) {
4079 out <<"//________________________________________________________________________________" << endl;
4080 out << "Bool_t SetupPar(const char *package) {" << endl;
4081 out << "// Compile the package and set it up." << endl;
4082 out << " TString pkgdir = package;" << endl;
4083 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4084 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4085 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4086 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4087 out << " // Check for BUILD.sh and execute" << endl;
4088 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4089 out << " printf(\"*******************************\\n\");" << endl;
4090 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4091 out << " printf(\"*******************************\\n\");" << endl;
4092 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4093 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4094 out << " gSystem->ChangeDirectory(cdir);" << endl;
4095 out << " return kFALSE;" << endl;
4096 out << " }" << endl;
4097 out << " } else {" << endl;
4098 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4099 out << " gSystem->ChangeDirectory(cdir);" << endl;
4100 out << " return kFALSE;" << endl;
4101 out << " }" << endl;
4102 out << " // Check for SETUP.C and execute" << endl;
4103 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4104 out << " printf(\"*******************************\\n\");" << endl;
4105 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4106 out << " printf(\"*******************************\\n\");" << endl;
4107 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4108 out << " } else {" << endl;
4109 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4110 out << " gSystem->ChangeDirectory(cdir);" << endl;
4111 out << " return kFALSE;" << endl;
4112 out << " }" << endl;
4113 out << " // Restore original workdir" << endl;
4114 out << " gSystem->ChangeDirectory(cdir);" << endl;
4115 out << " return kTRUE;" << endl;
4118 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4120 Bool_t copy = kTRUE;
4121 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4124 TString workdir = gGrid->GetHomeDirectory();
4125 workdir += fGridWorkingDir;
4126 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4127 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4128 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4129 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
4130 Form("alien://%s/%s", workdir.Data(),
4131 fAnalysisMacro.Data()))) Fatal("","Terminating");
4135 //______________________________________________________________________________
4136 void AliAnalysisAlien::WriteMergingMacro()
4138 // Write a macro to merge the outputs per master job.
4139 if (!fMergeViaJDL) return;
4140 if (!fOutputFiles.Length()) {
4141 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4144 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
4145 TString mergingMacro = fExecutable;
4146 mergingMacro.ReplaceAll(".sh","_merge.C");
4147 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4148 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4150 out.open(mergingMacro.Data(), ios::out);
4152 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4155 Bool_t hasSTEERBase = kFALSE;
4156 Bool_t hasESD = kFALSE;
4157 Bool_t hasAOD = kFALSE;
4158 Bool_t hasANALYSIS = kFALSE;
4159 Bool_t hasOADB = kFALSE;
4160 Bool_t hasANALYSISalice = kFALSE;
4161 Bool_t hasCORRFW = kFALSE;
4162 TString func = mergingMacro;
4164 func.ReplaceAll(".C", "");
4165 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4167 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4168 out << " TStopwatch timer;" << endl;
4169 out << " timer.Start();" << endl << endl;
4170 // Reset existing include path
4171 out << "// Reset existing include path and add current directory first in the search" << endl;
4172 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4173 if (!fExecutableCommand.Contains("aliroot")) {
4174 out << "// load base root libraries" << endl;
4175 out << " gSystem->Load(\"libTree\");" << endl;
4176 out << " gSystem->Load(\"libGeom\");" << endl;
4177 out << " gSystem->Load(\"libVMC\");" << endl;
4178 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4179 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4181 if (fAdditionalRootLibs.Length()) {
4182 // in principle libtree /lib geom libvmc etc. can go into this list, too
4183 out << "// Add aditional libraries" << endl;
4184 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4187 while((str=(TObjString*)next())) {
4188 if (str->GetString().Contains(".so"))
4189 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4191 if (list) delete list;
4193 out << "// Load analysis framework libraries" << endl;
4195 if (!fExecutableCommand.Contains("aliroot")) {
4196 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4197 out << " gSystem->Load(\"libESD\");" << endl;
4198 out << " gSystem->Load(\"libAOD\");" << endl;
4200 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4201 out << " gSystem->Load(\"libOADB\");" << endl;
4202 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4203 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4205 TIter next(fPackages);
4208 TString setupPar = "AliAnalysisAlien::SetupPar";
4209 while ((obj=next())) {
4210 pkgname = obj->GetName();
4211 if (pkgname == "STEERBase" ||
4212 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4213 if (pkgname == "ESD" ||
4214 pkgname == "ESD.par") hasESD = kTRUE;
4215 if (pkgname == "AOD" ||
4216 pkgname == "AOD.par") hasAOD = kTRUE;
4217 if (pkgname == "ANALYSIS" ||
4218 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4219 if (pkgname == "OADB" ||
4220 pkgname == "OADB.par") hasOADB = kTRUE;
4221 if (pkgname == "ANALYSISalice" ||
4222 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4223 if (pkgname == "CORRFW" ||
4224 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4226 if (hasANALYSISalice) setupPar = "SetupPar";
4227 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4228 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4229 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4230 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4231 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4232 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4233 out << " gSystem->Load(\"libOADB\");" << endl;
4234 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4235 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4236 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4237 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4238 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4239 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4240 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4241 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4242 out << "// Compile other par packages" << endl;
4244 while ((obj=next())) {
4245 pkgname = obj->GetName();
4246 if (pkgname == "STEERBase" ||
4247 pkgname == "STEERBase.par" ||
4249 pkgname == "ESD.par" ||
4251 pkgname == "AOD.par" ||
4252 pkgname == "ANALYSIS" ||
4253 pkgname == "ANALYSIS.par" ||
4254 pkgname == "OADB" ||
4255 pkgname == "OADB.par" ||
4256 pkgname == "ANALYSISalice" ||
4257 pkgname == "ANALYSISalice.par" ||
4258 pkgname == "CORRFW" ||
4259 pkgname == "CORRFW.par") continue;
4260 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4263 out << "// include path" << endl;
4264 // Get the include path from the interpreter and remove entries pointing to AliRoot
4265 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4266 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4267 out << " TIter nextpath(listpaths);" << endl;
4268 out << " TObjString *pname;" << endl;
4269 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4270 out << " TString current = pname->GetName();" << endl;
4271 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4272 out << " gSystem->AddIncludePath(current);" << endl;
4273 out << " }" << endl;
4274 out << " if (listpaths) delete listpaths;" << endl;
4275 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4276 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4277 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4278 if (fAdditionalLibs.Length()) {
4279 out << "// Add aditional AliRoot libraries" << endl;
4280 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4283 while((str=(TObjString*)next())) {
4284 if (str->GetString().Contains(".so"))
4285 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4287 if (list) delete list;
4290 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4291 if (fAnalysisSource.Length()) {
4292 TObjArray *list = fAnalysisSource.Tokenize(" ");
4295 while((str=(TObjString*)next())) {
4296 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4298 if (list) delete list;
4302 if (fFastReadOption) {
4303 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 !!!");
4304 out << "// fast xrootd reading enabled" << endl;
4305 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4306 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4307 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4308 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4309 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4310 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4312 // Change temp directory to current one
4313 out << "// Connect to AliEn" << endl;
4314 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4315 out << "// Set temporary merging directory to current one" << endl;
4316 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4317 out << "// Set temporary compilation directory to current one" << endl;
4318 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4319 out << " TString outputDir = dir;" << endl;
4320 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4321 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4322 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4323 out << " TIter *iter = new TIter(list);" << endl;
4324 out << " TObjString *str;" << endl;
4325 out << " TString outputFile;" << endl;
4326 out << " Bool_t merged = kTRUE;" << endl;
4327 TString analysisFile = fExecutable;
4328 analysisFile.ReplaceAll(".sh", ".root");
4329 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4330 << analysisFile << "\");" << endl;
4331 out << " if (!mgr) {" << endl;
4332 out << " printf(\"ERROR: Analysis manager could not be extracted from file \");" << endl;
4333 out << " return;" << endl;
4334 out << " }" << endl;
4335 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4336 out << " outputFile = str->GetString();" << endl;
4337 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4338 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4339 out << " if (index > 0) outputFile.Remove(index);" << endl;
4340 out << " // Skip already merged outputs" << endl;
4341 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4342 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4343 out << " continue;" << endl;
4344 out << " }" << endl;
4345 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4346 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4347 out << " if (!merged) {" << endl;
4348 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4349 out << " return;" << endl;
4350 out << " }" << endl;
4351 out << " }" << endl;
4352 if (mgr && mgr->IsCollectThroughput()) {
4353 out << " TString infolog = \"" << mgr->GetFileInfoLog() << "\";" << endl;
4354 out << " AliAnalysisAlien::MergeInfo(infolog, outputDir);" << endl;
4356 out << " // all outputs merged, validate" << endl;
4357 out << " ofstream out;" << endl;
4358 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4359 out << " out.close();" << endl;
4360 out << " // read the analysis manager from file" << endl;
4361 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4362 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4363 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4364 out << " mgr->PrintStatus();" << endl;
4366 if (mgr->GetDebugLevel()>3) {
4367 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4369 if (TestBit(AliAnalysisGrid::kTest))
4370 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4372 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4375 out << " TTree *tree = NULL;" << endl;
4376 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4377 out << "}" << endl << endl;
4378 if (hasANALYSISalice) {
4379 out <<"//________________________________________________________________________________" << endl;
4380 out << "Bool_t SetupPar(const char *package) {" << endl;
4381 out << "// Compile the package and set it up." << endl;
4382 out << " TString pkgdir = package;" << endl;
4383 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4384 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4385 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4386 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4387 out << " // Check for BUILD.sh and execute" << endl;
4388 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4389 out << " printf(\"*******************************\\n\");" << endl;
4390 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4391 out << " printf(\"*******************************\\n\");" << endl;
4392 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4393 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4394 out << " gSystem->ChangeDirectory(cdir);" << endl;
4395 out << " return kFALSE;" << endl;
4396 out << " }" << endl;
4397 out << " } else {" << endl;
4398 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4399 out << " gSystem->ChangeDirectory(cdir);" << endl;
4400 out << " return kFALSE;" << endl;
4401 out << " }" << endl;
4402 out << " // Check for SETUP.C and execute" << endl;
4403 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4404 out << " printf(\"*******************************\\n\");" << endl;
4405 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4406 out << " printf(\"*******************************\\n\");" << endl;
4407 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4408 out << " } else {" << endl;
4409 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4410 out << " gSystem->ChangeDirectory(cdir);" << endl;
4411 out << " return kFALSE;" << endl;
4412 out << " }" << endl;
4413 out << " // Restore original workdir" << endl;
4414 out << " gSystem->ChangeDirectory(cdir);" << endl;
4415 out << " return kTRUE;" << endl;
4419 Bool_t copy = kTRUE;
4420 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4423 TString workdir = gGrid->GetHomeDirectory();
4424 workdir += fGridWorkingDir;
4425 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4426 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4427 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4428 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4429 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4433 //______________________________________________________________________________
4434 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4436 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4437 // Note that for loading the compiled library. The current directory should have precedence in
4439 TString pkgdir = package;
4440 pkgdir.ReplaceAll(".par","");
4441 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4442 TString cdir = gSystem->WorkingDirectory();
4443 gSystem->ChangeDirectory(pkgdir);
4444 // Check for BUILD.sh and execute
4445 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4446 printf("**************************************************\n");
4447 printf("*** Building PAR archive %s\n", package);
4448 printf("**************************************************\n");
4449 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4450 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4451 gSystem->ChangeDirectory(cdir);
4455 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4456 gSystem->ChangeDirectory(cdir);
4459 // Check for SETUP.C and execute
4460 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4461 printf("**************************************************\n");
4462 printf("*** Setup PAR archive %s\n", package);
4463 printf("**************************************************\n");
4464 gROOT->Macro("PROOF-INF/SETUP.C");
4465 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4467 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4468 gSystem->ChangeDirectory(cdir);
4471 // Restore original workdir
4472 gSystem->ChangeDirectory(cdir);
4476 //______________________________________________________________________________
4477 void AliAnalysisAlien::WriteExecutable()
4479 // Generate the alien executable script.
4480 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4482 out.open(fExecutable.Data(), ios::out);
4484 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4487 out << "#!/bin/bash" << endl;
4488 // Make sure we can properly compile par files
4489 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4490 out << "echo \"=========================================\"" << endl;
4491 out << "echo \"############## PATH : ##############\"" << endl;
4492 out << "echo $PATH" << endl;
4493 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4494 out << "echo $LD_LIBRARY_PATH" << endl;
4495 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4496 out << "echo $ROOTSYS" << endl;
4497 out << "echo \"############## which root : ##############\"" << endl;
4498 out << "which root" << endl;
4499 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4500 out << "echo $ALICE_ROOT" << endl;
4501 out << "echo \"############## which aliroot : ##############\"" << endl;
4502 out << "which aliroot" << endl;
4503 out << "echo \"############## system limits : ##############\"" << endl;
4504 out << "ulimit -a" << endl;
4505 out << "echo \"############## memory : ##############\"" << endl;
4506 out << "free -m" << endl;
4507 out << "echo \"=========================================\"" << endl << endl;
4508 out << fExecutableCommand << " ";
4509 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4510 out << "RET=$?" << endl;
4511 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4512 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4513 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4514 out << " let sig=\"$RET - 128\""<<endl;
4515 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4516 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4517 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4518 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4519 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4520 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4522 out << " exit $RET"<< endl;
4523 out << "fi" << endl << endl ;
4524 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4525 out << "echo \"############## memory after: ##############\"" << endl;
4526 out << "free -m" << endl;
4528 Bool_t copy = kTRUE;
4529 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4532 TString workdir = gGrid->GetHomeDirectory();
4533 TString bindir = Form("%s/bin", workdir.Data());
4534 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4535 workdir += fGridWorkingDir;
4536 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4537 if (FileExists(executable)) gGrid->Rm(executable);
4538 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4539 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4540 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4541 executable.Data())) Fatal("","Terminating");
4545 //______________________________________________________________________________
4546 void AliAnalysisAlien::WriteMergeExecutable()
4548 // Generate the alien executable script for the merging job.
4549 if (!fMergeViaJDL) return;
4550 TString mergeExec = fExecutable;
4551 mergeExec.ReplaceAll(".sh", "_merge.sh");
4552 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4554 out.open(mergeExec.Data(), ios::out);
4556 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4559 out << "#!/bin/bash" << endl;
4560 // Make sure we can properly compile par files
4561 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4562 out << "echo \"=========================================\"" << endl;
4563 out << "echo \"############## PATH : ##############\"" << endl;
4564 out << "echo $PATH" << endl;
4565 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4566 out << "echo $LD_LIBRARY_PATH" << endl;
4567 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4568 out << "echo $ROOTSYS" << endl;
4569 out << "echo \"############## which root : ##############\"" << endl;
4570 out << "which root" << endl;
4571 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4572 out << "echo $ALICE_ROOT" << endl;
4573 out << "echo \"############## which aliroot : ##############\"" << endl;
4574 out << "which aliroot" << endl;
4575 out << "echo \"############## system limits : ##############\"" << endl;
4576 out << "ulimit -a" << endl;
4577 out << "echo \"############## memory : ##############\"" << endl;
4578 out << "free -m" << endl;
4579 out << "echo \"=========================================\"" << endl << endl;
4580 TString mergeMacro = fExecutable;
4581 mergeMacro.ReplaceAll(".sh", "_merge.C");
4582 if (IsOneStageMerging())
4583 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4585 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4586 out << fExecutableCommand << " " << "$ARG" << endl;
4587 out << "RET=$?" << endl;
4588 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4589 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4590 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4591 out << " let sig=\"$RET - 128\""<<endl;
4592 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4593 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4594 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4595 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4596 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4597 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4599 out << " exit $RET"<< endl;
4600 out << "fi" << endl << endl ;
4601 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4602 out << "echo \"############## memory after: ##############\"" << endl;
4603 out << "free -m" << endl;
4605 Bool_t copy = kTRUE;
4606 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4609 TString workdir = gGrid->GetHomeDirectory();
4610 TString bindir = Form("%s/bin", workdir.Data());
4611 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4612 workdir += fGridWorkingDir;
4613 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4614 if (FileExists(executable)) gGrid->Rm(executable);
4615 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4616 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4617 if (!copyLocal2Alien("WriteMergeExecutable",
4618 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4622 //______________________________________________________________________________
4623 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4625 // Write the production file to be submitted by LPM manager. The format is:
4626 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4627 // Next lines: full_path_to_dataset XXX (XXX is a string)
4628 // To submit, one has to: submit jdl XXX for all lines
4630 out.open(filename, ios::out);
4632 Error("WriteProductionFile", "Bad file name: %s", filename);
4636 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4637 workdir = gGrid->GetHomeDirectory();
4638 workdir += fGridWorkingDir;
4639 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4640 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4641 out << locjdl << " " << njobspermaster << endl;
4642 Int_t nmasterjobs = fInputFiles->GetEntries();
4643 for (Int_t i=0; i<nmasterjobs; i++) {
4644 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4645 runOutDir.ReplaceAll(".xml", "");
4647 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4649 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4652 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4653 if (FileExists(filename)) gGrid->Rm(filename);
4654 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4655 if (!copyLocal2Alien("WriteProductionFile", filename,
4656 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4660 //______________________________________________________________________________
4661 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4663 // Generate the alien validation script.
4664 // Generate the validation script
4666 if (fValidationScript.IsNull()) {
4667 fValidationScript = fExecutable;
4668 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4670 TString validationScript = fValidationScript;
4671 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4673 Error("WriteValidationScript", "Alien connection required");
4676 if (!fTerminateFiles.IsNull()) {
4677 fTerminateFiles.Strip();
4678 fTerminateFiles.ReplaceAll(" ",",");
4680 TString outStream = "";
4681 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4682 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4684 out.open(validationScript, ios::out);
4685 out << "#!/bin/bash" << endl;
4686 out << "##################################################" << endl;
4687 out << "validateout=`dirname $0`" << endl;
4688 out << "validatetime=`date`" << endl;
4689 out << "validated=\"0\";" << endl;
4690 out << "error=0" << endl;
4691 out << "if [ -z $validateout ]" << endl;
4692 out << "then" << endl;
4693 out << " validateout=\".\"" << endl;
4694 out << "fi" << endl << endl;
4695 out << "cd $validateout;" << endl;
4696 out << "validateworkdir=`pwd`;" << endl << endl;
4697 out << "echo \"*******************************************************\"" << outStream << endl;
4698 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4700 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4701 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4702 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4703 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4704 out << "ls -la ./" << outStream << endl;
4705 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4706 out << "##################################################" << endl;
4709 out << "if [ ! -f stderr ] ; then" << endl;
4710 out << " error=1" << endl;
4711 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4712 out << " echo \"Error = $error\" " << outStream << endl;
4713 out << "fi" << endl;
4715 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4716 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4717 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4718 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4721 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4722 out << " error=1" << endl;
4723 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4724 out << " echo \"$parArch\" " << outStream << endl;
4725 out << " echo \"Error = $error\" " << outStream << endl;
4726 out << "fi" << endl;
4728 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4729 out << " error=1" << endl;
4730 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4731 out << " echo \"$segViol\" " << outStream << endl;
4732 out << " echo \"Error = $error\" " << outStream << endl;
4733 out << "fi" << endl;
4735 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4736 out << " error=1" << endl;
4737 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4738 out << " echo \"$segFault\" " << outStream << endl;
4739 out << " echo \"Error = $error\" " << outStream << endl;
4740 out << "fi" << endl;
4742 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4743 out << " error=1" << endl;
4744 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4745 out << " echo \"$glibcErr\" " << outStream << endl;
4746 out << " echo \"Error = $error\" " << outStream << endl;
4747 out << "fi" << endl;
4749 // Part dedicated to the specific analyses running into the train
4751 TString outputFiles = fOutputFiles;
4752 if (merge && !fTerminateFiles.IsNull()) {
4754 outputFiles += fTerminateFiles;
4756 TObjArray *arr = outputFiles.Tokenize(",");
4759 while (!merge && (os=(TObjString*)next1())) {
4760 // No need to validate outputs produced by merging since the merging macro does this
4761 outputFile = os->GetString();
4762 Int_t index = outputFile.Index("@");
4763 if (index > 0) outputFile.Remove(index);
4764 if (fTerminateFiles.Contains(outputFile)) continue;
4765 if (outputFile.Contains("*")) continue;
4766 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4767 out << " error=1" << endl;
4768 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4769 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4770 out << "fi" << endl;
4773 out << "if ! [ -f outputs_valid ] ; then" << endl;
4774 out << " error=1" << endl;
4775 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4776 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4777 out << "fi" << endl;
4779 out << "if [ $error = 0 ] ; then" << endl;
4780 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4781 if (!IsKeepLogs()) {
4782 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4784 out << " rm -f std*" << endl;
4786 out << "fi" << endl;
4788 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4789 out << "echo \"*******************************************************\"" << outStream << endl;
4790 out << "cd -" << endl;
4791 out << "exit $error" << endl;
4793 Bool_t copy = kTRUE;
4794 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4797 TString workdir = gGrid->GetHomeDirectory();
4798 workdir += fGridWorkingDir;
4799 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4800 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4801 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4802 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4803 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");