1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "AliAnalysisAlien.h"
25 #include "Riostream.h"
33 #include "TFileCollection.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
39 #include "TGridResult.h"
40 #include "TGridCollection.h"
42 #include "TGridJobStatusList.h"
43 #include "TGridJobStatus.h"
44 #include "TFileMerger.h"
45 #include "AliAnalysisManager.h"
46 #include "AliAnalysisTaskCfg.h"
47 #include "AliVEventHandler.h"
48 #include "AliAnalysisDataContainer.h"
49 #include "AliMultiInputEventHandler.h"
51 ClassImp(AliAnalysisAlien)
57 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
59 TString sl(Form("file:%s", loc));
60 TString sr(Form("alien://%s", rem));
61 Bool_t ret = TFile::Cp(sl, sr);
63 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
69 //______________________________________________________________________________
70 AliAnalysisAlien::AliAnalysisAlien()
76 fSplitMaxInputFileNumber(0),
78 fMasterResubmitThreshold(0),
91 fNproofWorkersPerSlave(0),
101 fAdditionalRootLibs(),
130 fRootVersionForProof(),
142 //______________________________________________________________________________
143 AliAnalysisAlien::AliAnalysisAlien(const char *name)
144 :AliAnalysisGrid(name),
149 fSplitMaxInputFileNumber(0),
151 fMasterResubmitThreshold(0),
164 fNproofWorkersPerSlave(0),
168 fExecutableCommand(),
174 fAdditionalRootLibs(),
203 fRootVersionForProof(),
215 //______________________________________________________________________________
216 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
217 :AliAnalysisGrid(other),
220 fPrice(other.fPrice),
222 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
223 fMaxInitFailed(other.fMaxInitFailed),
224 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
225 fNtestFiles(other.fNtestFiles),
226 fNrunsPerMaster(other.fNrunsPerMaster),
227 fMaxMergeFiles(other.fMaxMergeFiles),
228 fMaxMergeStages(other.fMaxMergeStages),
229 fNsubmitted(other.fNsubmitted),
230 fProductionMode(other.fProductionMode),
231 fOutputToRunNo(other.fOutputToRunNo),
232 fMergeViaJDL(other.fMergeViaJDL),
233 fFastReadOption(other.fFastReadOption),
234 fOverwriteMode(other.fOverwriteMode),
235 fNreplicas(other.fNreplicas),
236 fNproofWorkers(other.fNproofWorkers),
237 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
238 fProofReset(other.fProofReset),
239 fRunNumbers(other.fRunNumbers),
240 fExecutable(other.fExecutable),
241 fExecutableCommand(other.fExecutableCommand),
242 fArguments(other.fArguments),
243 fExecutableArgs(other.fExecutableArgs),
244 fAnalysisMacro(other.fAnalysisMacro),
245 fAnalysisSource(other.fAnalysisSource),
246 fValidationScript(other.fValidationScript),
247 fAdditionalRootLibs(other.fAdditionalRootLibs),
248 fAdditionalLibs(other.fAdditionalLibs),
249 fSplitMode(other.fSplitMode),
250 fAPIVersion(other.fAPIVersion),
251 fROOTVersion(other.fROOTVersion),
252 fAliROOTVersion(other.fAliROOTVersion),
253 fExternalPackages(other.fExternalPackages),
255 fGridWorkingDir(other.fGridWorkingDir),
256 fGridDataDir(other.fGridDataDir),
257 fDataPattern(other.fDataPattern),
258 fGridOutputDir(other.fGridOutputDir),
259 fOutputArchive(other.fOutputArchive),
260 fOutputFiles(other.fOutputFiles),
261 fInputFormat(other.fInputFormat),
262 fDatasetName(other.fDatasetName),
263 fJDLName(other.fJDLName),
264 fTerminateFiles(other.fTerminateFiles),
265 fMergeExcludes(other.fMergeExcludes),
266 fRegisterExcludes(other.fRegisterExcludes),
267 fIncludePath(other.fIncludePath),
268 fCloseSE(other.fCloseSE),
269 fFriendChainName(other.fFriendChainName),
270 fJobTag(other.fJobTag),
271 fOutputSingle(other.fOutputSingle),
272 fRunPrefix(other.fRunPrefix),
273 fProofCluster(other.fProofCluster),
274 fProofDataSet(other.fProofDataSet),
275 fFileForTestMode(other.fFileForTestMode),
276 fRootVersionForProof(other.fRootVersionForProof),
277 fAliRootMode(other.fAliRootMode),
278 fMergeDirName(other.fMergeDirName),
285 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
286 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
287 fRunRange[0] = other.fRunRange[0];
288 fRunRange[1] = other.fRunRange[1];
289 if (other.fInputFiles) {
290 fInputFiles = new TObjArray();
291 TIter next(other.fInputFiles);
293 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
294 fInputFiles->SetOwner();
296 if (other.fPackages) {
297 fPackages = new TObjArray();
298 TIter next(other.fPackages);
300 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
301 fPackages->SetOwner();
303 if (other.fModules) {
304 fModules = new TObjArray();
305 fModules->SetOwner();
306 TIter next(other.fModules);
307 AliAnalysisTaskCfg *mod, *crt;
308 while ((crt=(AliAnalysisTaskCfg*)next())) {
309 mod = new AliAnalysisTaskCfg(*crt);
315 //______________________________________________________________________________
316 AliAnalysisAlien::~AliAnalysisAlien()
324 fProofParam.DeleteAll();
327 //______________________________________________________________________________
328 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
331 if (this != &other) {
332 AliAnalysisGrid::operator=(other);
333 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
334 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
335 fPrice = other.fPrice;
337 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
338 fMaxInitFailed = other.fMaxInitFailed;
339 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
340 fNtestFiles = other.fNtestFiles;
341 fNrunsPerMaster = other.fNrunsPerMaster;
342 fMaxMergeFiles = other.fMaxMergeFiles;
343 fMaxMergeStages = other.fMaxMergeStages;
344 fNsubmitted = other.fNsubmitted;
345 fProductionMode = other.fProductionMode;
346 fOutputToRunNo = other.fOutputToRunNo;
347 fMergeViaJDL = other.fMergeViaJDL;
348 fFastReadOption = other.fFastReadOption;
349 fOverwriteMode = other.fOverwriteMode;
350 fNreplicas = other.fNreplicas;
351 fNproofWorkers = other.fNproofWorkers;
352 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
353 fProofReset = other.fProofReset;
354 fRunNumbers = other.fRunNumbers;
355 fExecutable = other.fExecutable;
356 fExecutableCommand = other.fExecutableCommand;
357 fArguments = other.fArguments;
358 fExecutableArgs = other.fExecutableArgs;
359 fAnalysisMacro = other.fAnalysisMacro;
360 fAnalysisSource = other.fAnalysisSource;
361 fValidationScript = other.fValidationScript;
362 fAdditionalRootLibs = other.fAdditionalRootLibs;
363 fAdditionalLibs = other.fAdditionalLibs;
364 fSplitMode = other.fSplitMode;
365 fAPIVersion = other.fAPIVersion;
366 fROOTVersion = other.fROOTVersion;
367 fAliROOTVersion = other.fAliROOTVersion;
368 fExternalPackages = other.fExternalPackages;
370 fGridWorkingDir = other.fGridWorkingDir;
371 fGridDataDir = other.fGridDataDir;
372 fDataPattern = other.fDataPattern;
373 fGridOutputDir = other.fGridOutputDir;
374 fOutputArchive = other.fOutputArchive;
375 fOutputFiles = other.fOutputFiles;
376 fInputFormat = other.fInputFormat;
377 fDatasetName = other.fDatasetName;
378 fJDLName = other.fJDLName;
379 fTerminateFiles = other.fTerminateFiles;
380 fMergeExcludes = other.fMergeExcludes;
381 fRegisterExcludes = other.fRegisterExcludes;
382 fIncludePath = other.fIncludePath;
383 fCloseSE = other.fCloseSE;
384 fFriendChainName = other.fFriendChainName;
385 fJobTag = other.fJobTag;
386 fOutputSingle = other.fOutputSingle;
387 fRunPrefix = other.fRunPrefix;
388 fProofCluster = other.fProofCluster;
389 fProofDataSet = other.fProofDataSet;
390 fFileForTestMode = other.fFileForTestMode;
391 fRootVersionForProof = other.fRootVersionForProof;
392 fAliRootMode = other.fAliRootMode;
393 fMergeDirName = other.fMergeDirName;
394 if (other.fInputFiles) {
395 fInputFiles = new TObjArray();
396 TIter next(other.fInputFiles);
398 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
399 fInputFiles->SetOwner();
401 if (other.fPackages) {
402 fPackages = new TObjArray();
403 TIter next(other.fPackages);
405 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
406 fPackages->SetOwner();
408 if (other.fModules) {
409 fModules = new TObjArray();
410 fModules->SetOwner();
411 TIter next(other.fModules);
412 AliAnalysisTaskCfg *mod, *crt;
413 while ((crt=(AliAnalysisTaskCfg*)next())) {
414 mod = new AliAnalysisTaskCfg(*crt);
422 //______________________________________________________________________________
423 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
425 // Add a single additional library to be loaded. Extension must be present.
427 if (!lib.Contains(".")) {
428 Error("AddAdditionalLibrary", "Extension not defined for %s", name);
431 if (fAdditionalLibs.Contains(name)) {
432 Warning("AddAdditionalLibrary", "Library %s already added.", name);
435 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
436 fAdditionalLibs += lib;
439 //______________________________________________________________________________
440 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
442 // Adding a module. Checks if already existing. Becomes owned by this.
444 if (GetModule(module->GetName())) {
445 Error("AddModule", "A module having the same name %s already added", module->GetName());
449 fModules = new TObjArray();
450 fModules->SetOwner();
452 fModules->Add(module);
455 //______________________________________________________________________________
456 void AliAnalysisAlien::AddModules(TObjArray *list)
458 // Adding a list of modules. Checks if already existing. Becomes owned by this.
460 AliAnalysisTaskCfg *module;
461 while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
464 //______________________________________________________________________________
465 Bool_t AliAnalysisAlien::CheckDependencies()
467 // Check if all dependencies are satisfied. Reorder modules if needed.
468 Int_t nmodules = GetNmodules();
470 Warning("CheckDependencies", "No modules added yet to check their dependencies");
473 AliAnalysisTaskCfg *mod = 0;
474 AliAnalysisTaskCfg *dep = 0;
477 for (i=0; i<nmodules; i++) {
478 mod = (AliAnalysisTaskCfg*) fModules->At(i);
479 Int_t ndeps = mod->GetNdeps();
481 for (j=0; j<ndeps; j++) {
482 depname = mod->GetDependency(j);
483 dep = GetModule(depname);
485 Error("CheckDependencies","Dependency %s not added for module %s",
486 depname.Data(), mod->GetName());
489 if (dep->NeedsDependency(mod->GetName())) {
490 Error("CheckDependencies","Modules %s and %s circularly depend on each other",
491 mod->GetName(), dep->GetName());
494 Int_t idep = fModules->IndexOf(dep);
495 // The dependency task must come first
497 // Remove at idep and move all objects below up one slot
498 // down to index i included.
499 fModules->RemoveAt(idep);
500 for (k=idep-1; k>=i; k--) fModules->AddAt(fModules->RemoveAt(k),k+1);
501 fModules->AddAt(dep, i++);
503 //Redo from istart if dependencies were inserted
504 if (i>istart) i=istart-1;
510 //______________________________________________________________________________
511 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
513 // Create the analysis manager and optionally execute the macro in filename.
514 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
516 mgr = new AliAnalysisManager(name);
517 mgr->SetGridHandler((AliAnalysisGrid*)this);
518 if (strlen(filename)) {
519 TString line = gSystem->ExpandPathName(filename);
521 gROOT->ProcessLine(line.Data());
526 //______________________________________________________________________________
527 Int_t AliAnalysisAlien::GetNmodules() const
529 // Get number of modules.
530 if (!fModules) return 0;
531 return fModules->GetEntries();
534 //______________________________________________________________________________
535 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
537 // Get a module by name.
538 if (!fModules) return 0;
539 return (AliAnalysisTaskCfg*)fModules->FindObject(name);
542 //______________________________________________________________________________
543 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
545 // Load a given module.
546 if (mod->IsLoaded()) return kTRUE;
547 Int_t ndeps = mod->GetNdeps();
549 for (Int_t j=0; j<ndeps; j++) {
550 depname = mod->GetDependency(j);
551 AliAnalysisTaskCfg *dep = GetModule(depname);
553 Error("LoadModule","Dependency %s not existing for module %s",
554 depname.Data(), mod->GetName());
557 if (!LoadModule(dep)) {
558 Error("LoadModule","Dependency %s for module %s could not be loaded",
559 depname.Data(), mod->GetName());
563 // Load libraries for the module
564 if (!mod->CheckLoadLibraries()) {
565 Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
569 if (mod->ExecuteMacro()<0) {
570 Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
571 mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
574 // Configure dependencies
575 if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
576 Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
577 mod->GetConfigMacro()->GetTitle(), mod->GetName());
580 // Adjust extra libraries
581 Int_t nlibs = mod->GetNlibs();
583 for (Int_t i=0; i<nlibs; i++) {
584 lib = mod->GetLibrary(i);
585 if (fAdditionalLibs.Contains(lib)) continue;
586 lib = Form("lib%s.so", lib.Data());
587 if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
588 fAdditionalLibs += lib;
593 //______________________________________________________________________________
594 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
596 // Generate the full train.
597 fAdditionalLibs = "";
598 if (!LoadModules()) return kFALSE;
599 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
600 if (!mgr->InitAnalysis()) return kFALSE;
603 Int_t productionMode = fProductionMode;
605 TString macro = fAnalysisMacro;
606 TString executable = fExecutable;
607 TString validation = fValidationScript;
608 TString execCommand = fExecutableCommand;
609 SetAnalysisMacro(Form("%s.C", name));
610 SetExecutable(Form("%s.sh", name));
611 SetExecutableCommand("aliroot -b -q ");
612 SetValidationScript(Form("%s_validation.sh", name));
614 SetProductionMode(productionMode);
615 fAnalysisMacro = macro;
616 fExecutable = executable;
617 fExecutableCommand = execCommand;
618 fValidationScript = validation;
622 //______________________________________________________________________________
623 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
625 // Generate test macros for a single module or for the full train.
626 fAdditionalLibs = "";
627 if (strlen(modname)) {
628 if (!CheckDependencies()) return kFALSE;
629 AliAnalysisTaskCfg *mod = GetModule(modname);
631 Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
634 if (!LoadModule(mod)) return kFALSE;
635 } else if (!LoadModules()) return kFALSE;
636 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
637 if (!mgr->InitAnalysis()) return kFALSE;
641 Int_t productionMode = fProductionMode;
643 TString macro = fAnalysisMacro;
644 TString executable = fExecutable;
645 TString validation = fValidationScript;
646 TString execCommand = fExecutableCommand;
647 SetAnalysisMacro(Form("%s.C", name));
648 SetExecutable(Form("%s.sh", name));
649 SetExecutableCommand("aliroot -b -q ");
650 SetValidationScript(Form("%s_validation.sh", name));
652 WriteAnalysisMacro();
654 WriteValidationScript();
655 SetLocalTest(kFALSE);
656 SetProductionMode(productionMode);
657 fAnalysisMacro = macro;
658 fExecutable = executable;
659 fExecutableCommand = execCommand;
660 fValidationScript = validation;
664 //______________________________________________________________________________
665 Bool_t AliAnalysisAlien::LoadModules()
667 // Load all modules by executing the AddTask macros. Checks first the dependencies.
668 fAdditionalLibs = "";
669 Int_t nmodules = GetNmodules();
671 Warning("LoadModules", "No module to be loaded");
674 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
676 Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
679 if (!CheckDependencies()) return kFALSE;
680 nmodules = GetNmodules();
681 AliAnalysisTaskCfg *mod;
682 for (Int_t imod=0; imod<nmodules; imod++) {
683 mod = (AliAnalysisTaskCfg*)fModules->At(imod);
684 if (!LoadModule(mod)) return kFALSE;
689 //______________________________________________________________________________
690 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
692 // Set the run number format. Can be a prefix or a format like "%09d"
694 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
697 //______________________________________________________________________________
698 void AliAnalysisAlien::AddIncludePath(const char *path)
700 // Add include path in the remote analysis macro.
702 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
703 else fIncludePath += Form("-I%s ", path);
706 //______________________________________________________________________________
707 void AliAnalysisAlien::AddRunNumber(Int_t run)
709 // Add a run number to the list of runs to be processed.
710 if (fRunNumbers.Length()) fRunNumbers += " ";
711 fRunNumbers += Form(fRunPrefix.Data(), run);
714 //______________________________________________________________________________
715 void AliAnalysisAlien::AddRunList(const char* runList)
717 // Add several runs into the list of runs; they are expected to be separated by a blank character.
718 TString sList = runList;
719 TObjArray *list = sList.Tokenize(" ");
720 Int_t n = list->GetEntries();
721 for (Int_t i = 0; i < n; i++) {
722 TObjString *os = (TObjString*)list->At(i);
723 AddRunNumber(os->GetString().Atoi());
728 //______________________________________________________________________________
729 void AliAnalysisAlien::AddRunNumber(const char* run)
731 // Add a run number to the list of runs to be processed.
734 TObjArray *arr = runs.Tokenize(" ");
737 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
738 while ((os=(TObjString*)next())){
739 if (fRunNumbers.Length()) fRunNumbers += " ";
740 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
745 //______________________________________________________________________________
746 void AliAnalysisAlien::AddDataFile(const char *lfn)
748 // Adds a data file to the input to be analysed. The file should be a valid LFN
749 // or point to an existing file in the alien workdir.
750 if (!fInputFiles) fInputFiles = new TObjArray();
751 fInputFiles->Add(new TObjString(lfn));
754 //______________________________________________________________________________
755 void AliAnalysisAlien::AddExternalPackage(const char *package)
757 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
758 if (fExternalPackages) fExternalPackages += " ";
759 fExternalPackages += package;
762 //______________________________________________________________________________
763 Bool_t AliAnalysisAlien::Connect()
765 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
766 if (gGrid && gGrid->IsConnected()) return kTRUE;
767 if (fProductionMode) return kTRUE;
769 Info("Connect", "Trying to connect to AliEn ...");
770 TGrid::Connect("alien://");
772 if (!gGrid || !gGrid->IsConnected()) {
773 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
776 fUser = gGrid->GetUser();
777 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
781 //______________________________________________________________________________
782 void AliAnalysisAlien::CdWork()
784 // Check validity of alien workspace. Create directory if possible.
786 Error("CdWork", "Alien connection required");
789 TString homedir = gGrid->GetHomeDirectory();
790 TString workdir = homedir + fGridWorkingDir;
791 if (DirectoryExists(workdir)) {
795 // Work directory not existing - create it
797 if (gGrid->Mkdir(workdir, "-p")) {
798 gGrid->Cd(fGridWorkingDir);
799 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
801 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
802 workdir.Data(), homedir.Data());
803 fGridWorkingDir = "";
807 //______________________________________________________________________________
808 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
810 // Check if file copying is possible.
811 if (fProductionMode) return kTRUE;
813 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
816 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
817 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
818 // Check if alien_CLOSE_SE is defined
819 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
820 if (!closeSE.IsNull()) {
821 Info("CheckFileCopy", "Your current close storage is pointing to: \
822 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
824 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
826 // Check if grid directory exists.
827 if (!DirectoryExists(alienpath)) {
828 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
831 TFile f("plugin_test_copy", "RECREATE");
832 // User may not have write permissions to current directory
834 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
835 gSystem->WorkingDirectory());
839 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
840 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
841 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
842 \n# 1. Make sure you have write permissions there. If this is the case: \
843 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
844 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
845 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
846 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
847 gSystem->Unlink(f.GetName());
850 gSystem->Unlink(f.GetName());
851 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
852 Info("CheckFileCopy", "### ...SUCCESS ###");
856 //______________________________________________________________________________
857 Bool_t AliAnalysisAlien::CheckInputData()
859 // Check validity of input data. If necessary, create xml files.
860 if (fProductionMode) return kTRUE;
861 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
862 if (!fGridDataDir.Length()) {
863 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
867 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
870 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
871 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
872 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
875 // Process declared files
876 Bool_t isCollection = kFALSE;
877 Bool_t isXml = kFALSE;
878 Bool_t useTags = kFALSE;
879 Bool_t checked = kFALSE;
880 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
882 TString workdir = gGrid->GetHomeDirectory();
883 workdir += fGridWorkingDir;
886 TIter next(fInputFiles);
887 while ((objstr=(TObjString*)next())) {
890 file += objstr->GetString();
891 // Store full lfn path
892 if (FileExists(file)) objstr->SetString(file);
894 file = objstr->GetName();
895 if (!FileExists(objstr->GetName())) {
896 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
897 objstr->GetName(), workdir.Data());
901 Bool_t iscoll, isxml, usetags;
902 CheckDataType(file, iscoll, isxml, usetags);
905 isCollection = iscoll;
908 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
910 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
911 Error("CheckInputData", "Some conflict was found in the types of inputs");
917 // Process requested run numbers
918 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
919 // Check validity of alien data directory
920 if (!fGridDataDir.Length()) {
921 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
924 if (!DirectoryExists(fGridDataDir)) {
925 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
929 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
933 if (checked && !isXml) {
934 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
937 // Check validity of run number(s)
942 TString schunk, schunk2;
946 useTags = fDataPattern.Contains("tag");
947 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
949 if (useTags != fDataPattern.Contains("tag")) {
950 Error("CheckInputData", "Cannot mix input files using/not using tags");
953 if (fRunNumbers.Length()) {
954 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
955 arr = fRunNumbers.Tokenize(" ");
957 while ((os=(TObjString*)next())) {
958 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
959 if (!DirectoryExists(path)) {
960 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
963 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
964 TString msg = "\n##### file: ";
966 msg += " type: xml_collection;";
967 if (useTags) msg += " using_tags: Yes";
968 else msg += " using_tags: No";
969 Info("CheckDataType", "%s", msg.Data());
970 if (fNrunsPerMaster<2) {
971 AddDataFile(Form("%s.xml", os->GetString().Data()));
974 if (((nruns-1)%fNrunsPerMaster) == 0) {
975 schunk = os->GetString();
977 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
978 schunk += Form("_%s.xml", os->GetString().Data());
984 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
985 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
986 format = Form("%%s/%s ", fRunPrefix.Data());
987 path = Form(format.Data(), fGridDataDir.Data(), irun);
988 if (!DirectoryExists(path)) {
991 format = Form("%%s/%s.xml", fRunPrefix.Data());
992 path = Form(format.Data(), workdir.Data(),irun);
993 TString msg = "\n##### file: ";
995 msg += " type: xml_collection;";
996 if (useTags) msg += " using_tags: Yes";
997 else msg += " using_tags: No";
998 Info("CheckDataType", "%s", msg.Data());
999 if (fNrunsPerMaster<2) {
1000 format = Form("%s.xml", fRunPrefix.Data());
1001 AddDataFile(Form(format.Data(),irun));
1004 if (((nruns-1)%fNrunsPerMaster) == 0) {
1005 schunk = Form(fRunPrefix.Data(),irun);
1007 format = Form("_%s.xml", fRunPrefix.Data());
1008 schunk2 = Form(format.Data(), irun);
1009 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1011 AddDataFile(schunk);
1016 AddDataFile(schunk);
1022 //______________________________________________________________________________
1023 Bool_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1025 // Copy data from the given grid directory according a pattern and make a local
1028 Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1031 if (!DirectoryExists(griddir)) {
1032 Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1035 TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1036 printf("Running command: %s\n", command.Data());
1037 TGridResult *res = gGrid->Command(command);
1038 Int_t nfound = res->GetEntries();
1040 Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1043 printf("... found %d files. Copying locally ...\n", nfound);
1044 // Copy files locally
1046 out.open(output, ios::out);
1048 TString turl, dirname, filename, temp;
1049 TString cdir = gSystem->WorkingDirectory();
1050 gSystem->MakeDirectory(outputdir);
1051 gSystem->ChangeDirectory(outputdir);
1052 for (Int_t i=0; i<nfound; i++) {
1053 map = (TMap*)res->At(i);
1054 turl = map->GetValue("turl")->GetName();
1055 filename = gSystem->BaseName(turl.Data());
1056 dirname = gSystem->DirName(turl.Data());
1057 dirname = gSystem->BaseName(dirname.Data());
1058 gSystem->MakeDirectory(dirname);
1060 TString source(turl);
1061 TString targetFileName(filename);
1063 if (strlen(archivefile) > 0) {
1064 // TODO here the archive in which the file resides should be determined
1065 // however whereis returns only a guid, and guid2lfn does not work
1066 // Therefore we use the one provided as argument for now
1067 source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1068 targetFileName = archivefile;
1070 if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1071 if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1072 out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1075 gSystem->ChangeDirectory(cdir);
1080 //______________________________________________________________________________
1081 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1083 // Create dataset for the grid data directory + run number.
1084 const Int_t gMaxEntries = 15000;
1085 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1087 Error("CreateDataset", "Cannot create dataset with no grid connection");
1092 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1093 TString workdir = gGrid->GetHomeDirectory();
1094 workdir += fGridWorkingDir;
1096 // Compose the 'find' command arguments
1099 TString options = "-x collection ";
1100 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1101 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
1102 TString conditions = "";
1109 TString schunk, schunk2;
1110 TGridCollection *cbase=0, *cadd=0;
1111 if (!fRunNumbers.Length() && !fRunRange[0]) {
1112 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1113 // Make a single data collection from data directory.
1114 path = fGridDataDir;
1115 if (!DirectoryExists(path)) {
1116 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1120 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1121 else file = Form("%s.xml", gSystem->BaseName(path));
1125 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1127 command += Form("%s -o %d ",options.Data(), nstart);
1131 command += conditions;
1132 printf("command: %s\n", command.Data());
1133 TGridResult *res = gGrid->Command(command);
1134 if (res) delete res;
1135 // Write standard output to file
1136 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1137 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1138 Bool_t nullFile = kFALSE;
1140 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1142 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1144 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1145 gSystem->Exec("rm -f __tmp*");
1153 gSystem->Exec("rm -f __tmp__");
1154 ncount = line.Atoi();
1157 if (ncount == gMaxEntries) {
1158 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1159 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1160 if (!cbase) cbase = cadd;
1168 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1169 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1172 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1173 delete cbase; cbase = 0;
1175 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1177 gSystem->Exec("rm -f __tmp*");
1178 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1182 Bool_t fileExists = FileExists(file);
1183 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1184 // Copy xml file to alien space
1185 if (fileExists) gGrid->Rm(file);
1186 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1187 if (!FileExists(file)) {
1188 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1191 // Update list of files to be processed.
1193 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1197 Bool_t nullResult = kTRUE;
1198 if (fRunNumbers.Length()) {
1199 TObjArray *arr = fRunNumbers.Tokenize(" ");
1202 while ((os=(TObjString*)next())) {
1205 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
1206 if (!DirectoryExists(path)) continue;
1208 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1209 else file = Form("%s.xml", os->GetString().Data());
1210 // If local collection file does not exist, create it via 'find' command.
1214 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1216 command += Form("%s -o %d ",options.Data(), nstart);
1219 command += conditions;
1220 TGridResult *res = gGrid->Command(command);
1221 if (res) delete res;
1222 // Write standard output to file
1223 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1224 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1225 Bool_t nullFile = kFALSE;
1227 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1229 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1231 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1232 gSystem->Exec("rm -f __tmp*");
1233 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1241 gSystem->Exec("rm -f __tmp__");
1242 ncount = line.Atoi();
1244 nullResult = kFALSE;
1246 if (ncount == gMaxEntries) {
1247 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1248 if (fNrunsPerMaster > 1) {
1249 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1250 file.Data(),gMaxEntries);
1253 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1254 if (!cbase) cbase = cadd;
1261 if (cbase && fNrunsPerMaster<2) {
1262 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1263 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1266 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1267 delete cbase; cbase = 0;
1269 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1271 gSystem->Exec("rm -f __tmp*");
1272 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1276 if (TestBit(AliAnalysisGrid::kTest)) break;
1277 // Check if there is one run per master job.
1278 if (fNrunsPerMaster<2) {
1279 if (FileExists(file)) {
1280 if (fOverwriteMode) gGrid->Rm(file);
1282 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1286 // Copy xml file to alien space
1287 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1288 if (!FileExists(file)) {
1289 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1295 if (((nruns-1)%fNrunsPerMaster) == 0) {
1296 schunk = os->GetString();
1297 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1299 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1300 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
1304 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1307 schunk += Form("_%s.xml", os->GetString().Data());
1308 if (FileExists(schunk)) {
1309 if (fOverwriteMode) gGrid->Rm(file);
1311 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1315 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1316 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1317 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1318 if (!FileExists(schunk)) {
1319 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1327 Error("CreateDataset", "No valid dataset corresponding to the query!");
1331 // Process a full run range.
1332 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1333 format = Form("%%s/%s ", fRunPrefix.Data());
1336 path = Form(format.Data(), fGridDataDir.Data(), irun);
1337 if (!DirectoryExists(path)) continue;
1339 format = Form("%s.xml", fRunPrefix.Data());
1340 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1341 else file = Form(format.Data(), irun);
1342 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
1343 if (fOverwriteMode) gGrid->Rm(file);
1345 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1349 // If local collection file does not exist, create it via 'find' command.
1353 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1355 command += Form("%s -o %d ",options.Data(), nstart);
1358 command += conditions;
1359 TGridResult *res = gGrid->Command(command);
1360 if (res) delete res;
1361 // Write standard output to file
1362 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1363 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1364 Bool_t nullFile = kFALSE;
1366 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1368 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1370 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1371 gSystem->Exec("rm -f __tmp*");
1379 gSystem->Exec("rm -f __tmp__");
1380 ncount = line.Atoi();
1382 nullResult = kFALSE;
1384 if (ncount == gMaxEntries) {
1385 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1386 if (fNrunsPerMaster > 1) {
1387 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1388 file.Data(),gMaxEntries);
1391 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1392 if (!cbase) cbase = cadd;
1399 if (cbase && fNrunsPerMaster<2) {
1400 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1401 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1404 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1405 delete cbase; cbase = 0;
1407 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1409 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1413 if (TestBit(AliAnalysisGrid::kTest)) break;
1414 // Check if there is one run per master job.
1415 if (fNrunsPerMaster<2) {
1416 if (FileExists(file)) {
1417 if (fOverwriteMode) gGrid->Rm(file);
1419 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1423 // Copy xml file to alien space
1424 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1425 if (!FileExists(file)) {
1426 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1431 // Check if the collection for the chunk exist locally.
1432 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1433 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1434 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1437 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1438 if (((nruns-1)%fNrunsPerMaster) == 0) {
1439 schunk = Form(fRunPrefix.Data(), irun);
1440 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1442 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1446 format = Form("%%s_%s.xml", fRunPrefix.Data());
1447 schunk2 = Form(format.Data(), schunk.Data(), irun);
1448 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1452 if (FileExists(schunk)) {
1453 if (fOverwriteMode) gGrid->Rm(schunk);
1455 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1459 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1460 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1461 if (FileExists(schunk)) {
1462 if (fOverwriteMode) gGrid->Rm(schunk);
1464 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1468 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1469 if (!FileExists(schunk)) {
1470 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1476 Error("CreateDataset", "No valid dataset corresponding to the query!");
1483 //______________________________________________________________________________
1484 Bool_t AliAnalysisAlien::CreateJDL()
1486 // Generate a JDL file according to current settings. The name of the file is
1487 // specified by fJDLName.
1488 Bool_t error = kFALSE;
1490 Bool_t copy = kTRUE;
1491 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1492 Bool_t generate = kTRUE;
1493 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1495 Error("CreateJDL", "Alien connection required");
1498 // Check validity of alien workspace
1500 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1501 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1502 workdir += fGridWorkingDir;
1506 Error("CreateJDL()", "Define some input files for your analysis.");
1509 // Compose list of input files
1510 // Check if output files were defined
1511 if (!fOutputFiles.Length()) {
1512 Error("CreateJDL", "You must define at least one output file");
1515 // Check if an output directory was defined and valid
1516 if (!fGridOutputDir.Length()) {
1517 Error("CreateJDL", "You must define AliEn output directory");
1520 if (!fProductionMode) {
1521 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1522 if (!DirectoryExists(fGridOutputDir)) {
1523 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1524 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1526 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1530 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1535 // Exit if any error up to now
1536 if (error) return kFALSE;
1538 if (!fUser.IsNull()) {
1539 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1540 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1542 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1543 TString mergeExec = fExecutable;
1544 mergeExec.ReplaceAll(".sh", "_merge.sh");
1545 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1546 mergeExec.ReplaceAll(".sh", ".C");
1547 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1548 if (!fArguments.IsNull())
1549 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1550 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1552 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1553 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1556 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1557 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1558 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1559 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1561 if (fMaxInitFailed > 0) {
1562 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1563 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1565 if (fSplitMaxInputFileNumber > 0) {
1566 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1567 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1569 if (!IsOneStageMerging()) {
1570 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1571 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1573 if (fSplitMode.Length()) {
1574 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1575 fGridJDL->SetDescription("Split", "We split per SE or file");
1577 fMergingJDL->SetValue("Split", "\"se\"");
1578 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1579 if (!fAliROOTVersion.IsNull()) {
1580 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1581 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1583 if (!fROOTVersion.IsNull()) {
1584 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1585 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1587 if (!fAPIVersion.IsNull()) {
1588 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1589 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1591 if (!fExternalPackages.IsNull()) {
1592 arr = fExternalPackages.Tokenize(" ");
1594 while ((os=(TObjString*)next())) {
1595 TString pkgname = os->GetString();
1596 Int_t index = pkgname.Index("::");
1597 TString pkgversion = pkgname(index+2, pkgname.Length());
1598 pkgname.Remove(index);
1599 fGridJDL->AddToPackages(pkgname, pkgversion);
1600 fMergingJDL->AddToPackages(pkgname, pkgversion);
1604 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1605 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1606 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1607 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1608 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1609 TString analysisFile = fExecutable;
1610 analysisFile.ReplaceAll(".sh", ".root");
1611 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1612 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1613 if (fAdditionalLibs.Length()) {
1614 arr = fAdditionalLibs.Tokenize(" ");
1616 while ((os=(TObjString*)next())) {
1617 if (os->GetString().Contains(".so")) continue;
1618 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1619 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1624 TIter next(fPackages);
1626 while ((obj=next())) {
1627 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1628 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1631 if (fOutputArchive.Length()) {
1632 arr = fOutputArchive.Tokenize(" ");
1634 Bool_t first = kTRUE;
1635 const char *comment = "Files to be archived";
1636 const char *comment1 = comment;
1637 while ((os=(TObjString*)next())) {
1638 if (!first) comment = NULL;
1639 if (!os->GetString().Contains("@") && fCloseSE.Length())
1640 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1642 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1646 // Output archive for the merging jdl
1647 TString outputArchive;
1648 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1649 outputArchive = "log_archive.zip:std*@disk=1 ";
1650 // Add normal output files, extra files + terminate files
1651 TString files = GetListOfFiles("outextter");
1652 // Do not register files in fRegisterExcludes
1653 if (!fRegisterExcludes.IsNull()) {
1654 arr = fRegisterExcludes.Tokenize(" ");
1656 while ((os=(TObjString*)next1())) {
1657 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1658 files.ReplaceAll(os->GetString(),"");
1662 files.ReplaceAll(".root", "*.root");
1663 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1665 TString files = fOutputArchive;
1666 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1667 outputArchive = files;
1669 arr = outputArchive.Tokenize(" ");
1673 while ((os=(TObjString*)next2())) {
1674 if (!first) comment = NULL;
1675 TString currentfile = os->GetString();
1676 if (!currentfile.Contains("@") && fCloseSE.Length())
1677 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1679 fMergingJDL->AddToOutputArchive(currentfile, comment);
1684 arr = fOutputFiles.Tokenize(",");
1686 Bool_t first = kTRUE;
1687 const char *comment = "Files to be saved";
1688 while ((os=(TObjString*)next())) {
1689 // Ignore ouputs in jdl that are also in outputarchive
1690 TString sout = os->GetString();
1691 sout.ReplaceAll("*", "");
1692 sout.ReplaceAll(".root", "");
1693 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1694 if (fOutputArchive.Contains(sout)) continue;
1695 // Ignore fRegisterExcludes
1696 if (fRegisterExcludes.Contains(sout)) continue;
1697 if (!first) comment = NULL;
1698 if (!os->GetString().Contains("@") && fCloseSE.Length())
1699 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1701 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1703 if (fMergeExcludes.Contains(sout)) continue;
1704 if (!os->GetString().Contains("@") && fCloseSE.Length())
1705 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1707 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1710 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1711 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1712 TString validationScript = fValidationScript;
1713 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1714 validationScript.ReplaceAll(".sh", "_merge.sh");
1715 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1716 if (fMasterResubmitThreshold) {
1717 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1718 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1720 // Write a jdl with 2 input parameters: collection name and output dir name.
1723 // Copy jdl to grid workspace
1725 // Check if an output directory was defined and valid
1726 if (!fGridOutputDir.Length()) {
1727 Error("CreateJDL", "You must define AliEn output directory");
1730 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1731 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1732 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1733 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1735 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1741 if (TestBit(AliAnalysisGrid::kSubmit)) {
1742 TString mergeJDLName = fExecutable;
1743 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1744 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1745 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1746 if (fProductionMode) {
1747 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1748 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1750 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1751 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1752 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1753 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1754 Fatal("","Terminating");
1755 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1757 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1758 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1759 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1760 Fatal("","Terminating");
1763 if (fAdditionalLibs.Length()) {
1764 arr = fAdditionalLibs.Tokenize(" ");
1767 while ((os=(TObjString*)next())) {
1768 if (os->GetString().Contains(".so")) continue;
1769 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1770 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1771 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1772 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1773 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1774 Fatal("","Terminating");
1779 TIter next(fPackages);
1781 while ((obj=next())) {
1782 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1783 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1784 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1785 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1786 Form("%s/%s", workdir.Data(), obj->GetName())))
1787 Fatal("","Terminating");
1794 //______________________________________________________________________________
1795 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1797 // Writes one or more JDL's corresponding to findex. If findex is negative,
1798 // all run numbers are considered in one go (jdl). For non-negative indices
1799 // they correspond to the indices in the array fInputFiles.
1800 if (!fInputFiles) return kFALSE;
1803 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1804 workdir += fGridWorkingDir;
1805 TString stageName = "$2";
1806 if (fProductionMode) stageName = "$4";
1807 if (!fMergeDirName.IsNull()) {
1808 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1809 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1811 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1812 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1814 if (fProductionMode) {
1815 TIter next(fInputFiles);
1816 while ((os=next())) {
1817 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1819 if (!fOutputToRunNo)
1820 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1822 fGridJDL->SetOutputDirectory(fGridOutputDir);
1824 if (!fRunNumbers.Length() && !fRunRange[0]) {
1825 // One jdl with no parameters in case input data is specified by name.
1826 TIter next(fInputFiles);
1828 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1829 if (!fOutputSingle.IsNull())
1830 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1832 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1833 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1836 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1837 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1838 if (!fOutputSingle.IsNull()) {
1839 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1840 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1842 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1847 // Generate the JDL as a string
1848 TString sjdl = fGridJDL->Generate();
1849 TString sjdl1 = fMergingJDL->Generate();
1851 if (!fMergeDirName.IsNull()) {
1852 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1853 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1855 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1856 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1858 TString sjdl2 = fMergingJDL->Generate();
1859 Int_t index, index1;
1860 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1861 sjdl.ReplaceAll("(member", "\n (member");
1862 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1863 sjdl.ReplaceAll("{", "{\n ");
1864 sjdl.ReplaceAll("};", "\n};");
1865 sjdl.ReplaceAll("{\n \n", "{\n");
1866 sjdl.ReplaceAll("\n\n", "\n");
1867 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1868 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1869 sjdl1.ReplaceAll("(member", "\n (member");
1870 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1871 sjdl1.ReplaceAll("{", "{\n ");
1872 sjdl1.ReplaceAll("};", "\n};");
1873 sjdl1.ReplaceAll("{\n \n", "{\n");
1874 sjdl1.ReplaceAll("\n\n", "\n");
1875 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1876 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1877 sjdl2.ReplaceAll("(member", "\n (member");
1878 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1879 sjdl2.ReplaceAll("{", "{\n ");
1880 sjdl2.ReplaceAll("};", "\n};");
1881 sjdl2.ReplaceAll("{\n \n", "{\n");
1882 sjdl2.ReplaceAll("\n\n", "\n");
1883 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1884 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1885 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1886 index = sjdl.Index("JDLVariables");
1887 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1888 sjdl += "Workdirectorysize = {\"5000MB\"};";
1889 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1890 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1891 index = fJobTag.Index(":");
1892 if (index < 0) index = fJobTag.Length();
1893 TString jobTag = fJobTag;
1894 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1895 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1896 if (fProductionMode) {
1897 sjdl1.Prepend("# Generated merging jdl (production mode) \
1898 \n# $1 = full alien path to output directory to be merged \
1899 \n# $2 = train number \
1900 \n# $3 = production (like LHC10b) \
1901 \n# $4 = merging stage \
1902 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1903 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1904 sjdl2.Prepend("# Generated merging jdl \
1905 \n# $1 = full alien path to output directory to be merged \
1906 \n# $2 = train number \
1907 \n# $3 = production (like LHC10b) \
1908 \n# $4 = merging stage \
1909 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1911 sjdl1.Prepend("# Generated merging jdl \
1912 \n# $1 = full alien path to output directory to be merged \
1913 \n# $2 = merging stage \
1914 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1915 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1916 sjdl2.Prepend("# Generated merging jdl \
1917 \n# $1 = full alien path to output directory to be merged \
1918 \n# $2 = merging stage \
1919 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1921 index = sjdl1.Index("JDLVariables");
1922 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1923 index = sjdl2.Index("JDLVariables");
1924 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1925 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1926 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1927 index = sjdl2.Index("Split =");
1929 index1 = sjdl2.Index("\n", index);
1930 sjdl2.Remove(index, index1-index+1);
1932 index = sjdl2.Index("SplitMaxInputFileNumber");
1934 index1 = sjdl2.Index("\n", index);
1935 sjdl2.Remove(index, index1-index+1);
1937 index = sjdl2.Index("InputDataCollection");
1939 index1 = sjdl2.Index(";", index);
1940 sjdl2.Remove(index, index1-index+1);
1942 index = sjdl2.Index("InputDataListFormat");
1944 index1 = sjdl2.Index("\n", index);
1945 sjdl2.Remove(index, index1-index+1);
1947 index = sjdl2.Index("InputDataList");
1949 index1 = sjdl2.Index("\n", index);
1950 sjdl2.Remove(index, index1-index+1);
1952 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1953 // Write jdl to file
1955 out.open(fJDLName.Data(), ios::out);
1957 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1960 out << sjdl << endl;
1962 TString mergeJDLName = fExecutable;
1963 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1966 out1.open(mergeJDLName.Data(), ios::out);
1968 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1971 out1 << sjdl1 << endl;
1974 TString finalJDL = mergeJDLName;
1975 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1976 out2.open(finalJDL.Data(), ios::out);
1978 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1981 out2 << sjdl2 << endl;
1985 // Copy jdl to grid workspace
1987 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1989 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1990 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1991 TString finalJDL = mergeJDLName;
1992 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1993 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1994 if (fProductionMode) {
1995 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1996 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1997 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1999 if (FileExists(locjdl)) gGrid->Rm(locjdl);
2000 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2001 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2002 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2003 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2004 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
2005 Fatal("","Terminating");
2007 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2008 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2009 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2010 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2011 Fatal("","Terminating");
2012 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2013 Fatal("","Terminating");
2019 //______________________________________________________________________________
2020 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2022 // Returns true if file exists.
2023 if (!gGrid) return kFALSE;
2025 slfn.ReplaceAll("alien://","");
2026 TGridResult *res = gGrid->Ls(slfn);
2027 if (!res) return kFALSE;
2028 TMap *map = dynamic_cast<TMap*>(res->At(0));
2033 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2034 if (!objs || !objs->GetString().Length()) {
2042 //______________________________________________________________________________
2043 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2045 // Returns true if directory exists. Can be also a path.
2046 if (!gGrid) return kFALSE;
2047 // Check if dirname is a path
2048 TString dirstripped = dirname;
2049 dirstripped = dirstripped.Strip();
2050 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2051 TString dir = gSystem->BaseName(dirstripped);
2053 TString path = gSystem->DirName(dirstripped);
2054 TGridResult *res = gGrid->Ls(path, "-F");
2055 if (!res) return kFALSE;
2059 while ((map=dynamic_cast<TMap*>(next()))) {
2060 obj = map->GetValue("name");
2062 if (dir == obj->GetName()) {
2071 //______________________________________________________________________________
2072 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2074 // Check input data type.
2075 isCollection = kFALSE;
2079 Error("CheckDataType", "No connection to grid");
2082 isCollection = IsCollection(lfn);
2083 TString msg = "\n##### file: ";
2086 msg += " type: raw_collection;";
2087 // special treatment for collections
2089 // check for tag files in the collection
2090 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2092 msg += " using_tags: No (unknown)";
2093 Info("CheckDataType", "%s", msg.Data());
2096 const char* typeStr = res->GetKey(0, "origLFN");
2097 if (!typeStr || !strlen(typeStr)) {
2098 msg += " using_tags: No (unknown)";
2099 Info("CheckDataType", "%s", msg.Data());
2102 TString file = typeStr;
2103 useTags = file.Contains(".tag");
2104 if (useTags) msg += " using_tags: Yes";
2105 else msg += " using_tags: No";
2106 Info("CheckDataType", "%s", msg.Data());
2111 isXml = slfn.Contains(".xml");
2113 // Open xml collection and check if there are tag files inside
2114 msg += " type: xml_collection;";
2115 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2117 msg += " using_tags: No (unknown)";
2118 Info("CheckDataType", "%s", msg.Data());
2121 TMap *map = coll->Next();
2123 msg += " using_tags: No (unknown)";
2124 Info("CheckDataType", "%s", msg.Data());
2127 map = (TMap*)map->GetValue("");
2129 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2130 useTags = file.Contains(".tag");
2132 if (useTags) msg += " using_tags: Yes";
2133 else msg += " using_tags: No";
2134 Info("CheckDataType", "%s", msg.Data());
2137 useTags = slfn.Contains(".tag");
2138 if (slfn.Contains(".root")) msg += " type: root file;";
2139 else msg += " type: unknown file;";
2140 if (useTags) msg += " using_tags: Yes";
2141 else msg += " using_tags: No";
2142 Info("CheckDataType", "%s", msg.Data());
2145 //______________________________________________________________________________
2146 void AliAnalysisAlien::EnablePackage(const char *package)
2148 // Enables a par file supposed to exist in the current directory.
2149 TString pkg(package);
2150 pkg.ReplaceAll(".par", "");
2152 if (gSystem->AccessPathName(pkg)) {
2153 Fatal("EnablePackage", "Package %s not found", pkg.Data());
2156 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2157 Info("EnablePackage", "AliEn plugin will use .par packages");
2158 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2160 fPackages = new TObjArray();
2161 fPackages->SetOwner();
2163 fPackages->Add(new TObjString(pkg));
2166 //______________________________________________________________________________
2167 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2169 // Make a tree from files having the location specified in fFileForTestMode.
2170 // Inspired from JF's CreateESDChain.
2171 if (fFileForTestMode.IsNull()) {
2172 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2175 if (gSystem->AccessPathName(fFileForTestMode)) {
2176 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2181 in.open(fFileForTestMode);
2183 // Read the input list of files and add them to the chain
2185 TChain *chain = new TChain(treeName);
2186 TChain *chainFriend = 0;
2187 if (!fFriendChainName.IsNull()) chainFriend = new TChain(treeName);
2191 if (line.IsNull()) continue;
2192 if (count++ == fNtestFiles) break;
2193 TString esdFile(line);
2194 TFile *file = TFile::Open(esdFile);
2195 if (file && !file->IsZombie()) {
2196 chain->Add(esdFile);
2198 if (!fFriendChainName.IsNull()) {
2199 esdFile.ReplaceAll("AliAOD.root", fFriendChainName.Data());
2200 esdFile.ReplaceAll("AliAODs.root", fFriendChainName.Data());
2201 file = TFile::Open(esdFile);
2202 if (file && !file->IsZombie()) {
2204 chainFriend->Add(esdFile);
2206 Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2211 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2215 if (!chain->GetListOfFiles()->GetEntries()) {
2216 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2222 if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2226 //______________________________________________________________________________
2227 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2229 // Get job status for all jobs with jobid>jobidstart.
2230 static char mstatus[20];
2236 TGridJobStatusList *list = gGrid->Ps("");
2237 if (!list) return mstatus;
2238 Int_t nentries = list->GetSize();
2239 TGridJobStatus *status;
2241 for (Int_t ijob=0; ijob<nentries; ijob++) {
2242 status = (TGridJobStatus *)list->At(ijob);
2243 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2244 if (pid<jobidstart) continue;
2245 if (pid == lastid) {
2246 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2248 switch (status->GetStatus()) {
2249 case TGridJobStatus::kWAITING:
2251 case TGridJobStatus::kRUNNING:
2253 case TGridJobStatus::kABORTED:
2254 case TGridJobStatus::kFAIL:
2255 case TGridJobStatus::kUNKNOWN:
2257 case TGridJobStatus::kDONE:
2266 //______________________________________________________________________________
2267 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2269 // Returns true if file is a collection. Functionality duplicated from
2270 // TAlien::Type() because we don't want to directly depend on TAlien.
2272 Error("IsCollection", "No connection to grid");
2275 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2276 if (!res) return kFALSE;
2277 const char* typeStr = res->GetKey(0, "type");
2278 if (!typeStr || !strlen(typeStr)) return kFALSE;
2279 if (!strcmp(typeStr, "collection")) return kTRUE;
2284 //______________________________________________________________________________
2285 Bool_t AliAnalysisAlien::IsSingleOutput() const
2287 // Check if single-ouput option is on.
2288 return (!fOutputSingle.IsNull());
2291 //______________________________________________________________________________
2292 void AliAnalysisAlien::Print(Option_t *) const
2294 // Print current plugin settings.
2295 printf("### AliEn analysis plugin current settings ###\n");
2296 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2297 if (mgr && mgr->IsProofMode()) {
2298 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2299 if (TestBit(AliAnalysisGrid::kTest))
2300 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2301 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2302 if (!fProofDataSet.IsNull())
2303 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2305 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2307 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2308 if (!fRootVersionForProof.IsNull())
2309 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2311 printf("= ROOT version requested________________________ default\n");
2312 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2313 if (!fAliRootMode.IsNull())
2314 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2316 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2317 if (fNproofWorkersPerSlave)
2318 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2319 if (TestSpecialBit(kClearPackages))
2320 printf("= ClearPackages requested...\n");
2321 if (fIncludePath.Data())
2322 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2323 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2324 if (fPackages && fPackages->GetEntries()) {
2325 TIter next(fPackages);
2328 while ((obj=next())) list += obj->GetName();
2329 printf("= Par files to be used: ________________________ %s\n", list.Data());
2331 if (TestSpecialBit(kProofConnectGrid))
2332 printf("= Requested PROOF connection to grid\n");
2335 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2336 if (fOverwriteMode) {
2337 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2338 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2340 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2341 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2342 printf("= Production mode:______________________________ %d\n", fProductionMode);
2343 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2344 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2345 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2347 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2348 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2349 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2350 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2351 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2352 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2353 if (fRunNumbers.Length())
2354 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2356 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2357 if (!fRunRange[0] && !fRunNumbers.Length()) {
2358 TIter next(fInputFiles);
2361 while ((obj=next())) list += obj->GetName();
2362 printf("= Input files to be processed: _________________ %s\n", list.Data());
2364 if (TestBit(AliAnalysisGrid::kTest))
2365 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2366 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2367 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2368 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2369 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2370 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2371 printf("=====================================================================\n");
2372 printf("= Job price: ___________________________________ %d\n", fPrice);
2373 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2374 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2375 if (fMaxInitFailed>0)
2376 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2377 if (fMasterResubmitThreshold>0)
2378 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2379 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2380 if (fNrunsPerMaster>0)
2381 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2382 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2383 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2384 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2385 if (fArguments.Length())
2386 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2387 if (fExecutableArgs.Length())
2388 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2389 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2390 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2391 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2392 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2394 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2395 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2396 if (fIncludePath.Data())
2397 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2398 if (fCloseSE.Length())
2399 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2400 if (fFriendChainName.Length())
2401 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2402 if (fPackages && fPackages->GetEntries()) {
2403 TIter next(fPackages);
2406 while ((obj=next())) list += obj->GetName();
2407 printf("= Par files to be used: ________________________ %s\n", list.Data());
2411 //______________________________________________________________________________
2412 void AliAnalysisAlien::SetDefaults()
2414 // Set default values for everything. What cannot be filled will be left empty.
2415 if (fGridJDL) delete fGridJDL;
2416 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2417 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2420 fSplitMaxInputFileNumber = 100;
2422 fMasterResubmitThreshold = 0;
2428 fNrunsPerMaster = 1;
2429 fMaxMergeFiles = 100;
2431 fExecutable = "analysis.sh";
2432 fExecutableCommand = "root -b -q";
2434 fExecutableArgs = "";
2435 fAnalysisMacro = "myAnalysis.C";
2436 fAnalysisSource = "";
2437 fAdditionalLibs = "";
2441 fAliROOTVersion = "";
2442 fUser = ""; // Your alien user name
2443 fGridWorkingDir = "";
2444 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2445 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2446 fFriendChainName = "";
2447 fGridOutputDir = "output";
2448 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2449 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2450 fInputFormat = "xml-single";
2451 fJDLName = "analysis.jdl";
2452 fJobTag = "Automatically generated analysis JDL";
2453 fMergeExcludes = "";
2456 SetCheckCopy(kTRUE);
2457 SetDefaultOutputs(kTRUE);
2461 //______________________________________________________________________________
2462 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2464 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2465 // First check if the result is already in the output directory.
2466 if (FileExists(Form("%s/%s",aliendir,filename))) {
2467 printf("Final merged results found. Not merging again.\n");
2470 // Now check the last stage done.
2473 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2476 // Next stage of merging
2478 TString pattern = "*root_archive.zip";
2479 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2480 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2481 if (res) delete res;
2482 // Write standard output to file
2483 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2484 // Count the number of files inside
2486 ifile.open(Form("Stage_%d.xml",stage));
2487 if (!ifile.good()) {
2488 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2493 while (!ifile.eof()) {
2495 if (line.Contains("/event")) nfiles++;
2499 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2502 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2504 // Copy the file in the output directory
2505 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2506 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2507 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2508 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2509 // Check if this is the last stage to be done.
2510 Bool_t laststage = (nfiles<nperchunk);
2511 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2513 printf("### Submiting final merging stage %d\n", stage);
2514 TString finalJDL = jdl;
2515 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2516 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2517 Int_t jobId = SubmitSingleJob(query);
2518 if (!jobId) return kFALSE;
2520 printf("### Submiting merging stage %d\n", stage);
2521 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2522 Int_t jobId = SubmitSingleJob(query);
2523 if (!jobId) return kFALSE;
2528 //______________________________________________________________________________
2529 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2531 // Loat the analysis manager from a file.
2532 TFile *file = TFile::Open(fname);
2534 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2537 TIter nextkey(file->GetListOfKeys());
2538 AliAnalysisManager *mgr = 0;
2540 while ((key=(TKey*)nextkey())) {
2541 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2542 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2545 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2549 //______________________________________________________________________________
2550 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2552 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2553 if (!gGrid) return 0;
2554 printf("=> %s ------> ",query);
2555 TGridResult *res = gGrid->Command(query);
2557 TString jobId = res->GetKey(0,"jobId");
2559 if (jobId.IsNull()) {
2560 printf("submission failed. Reason:\n");
2563 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2566 printf(" Job id: %s\n", jobId.Data());
2570 //______________________________________________________________________________
2571 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2573 // Merge given output files from basedir. Basedir can be an alien output directory
2574 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2575 // files in a group (ignored for xml input). Merging can be done in stages:
2576 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2577 // stage=1 : works with an xml of all root_archive.zip in the output directory
2578 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2579 TString outputFile = output;
2581 TString outputChunk;
2582 TString previousChunk = "";
2583 TObjArray *listoffiles = new TObjArray();
2584 // listoffiles->SetOwner();
2585 Int_t countChunk = 0;
2586 Int_t countZero = nmaxmerge;
2587 Bool_t merged = kTRUE;
2588 Int_t index = outputFile.Index("@");
2589 if (index > 0) outputFile.Remove(index);
2590 TString inputFile = outputFile;
2591 TString sbasedir = basedir;
2592 if (sbasedir.Contains(".xml")) {
2593 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2594 nmaxmerge = 9999999;
2595 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2597 ::Error("MergeOutput", "Input XML collection empty.");
2600 // Iterate grid collection
2601 while (coll->Next()) {
2602 TString fname = gSystem->DirName(coll->GetTURL());
2605 listoffiles->Add(new TNamed(fname.Data(),""));
2608 command = Form("find %s/ *%s", basedir, inputFile.Data());
2609 printf("command: %s\n", command.Data());
2610 TGridResult *res = gGrid->Command(command);
2612 ::Error("MergeOutput","No result for the find command\n");
2618 while ((map=(TMap*)nextmap())) {
2619 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2620 if (!objs || !objs->GetString().Length()) {
2621 // Nothing found - skip this output
2626 listoffiles->Add(new TNamed(objs->GetName(),""));
2630 if (!listoffiles->GetEntries()) {
2631 ::Error("MergeOutput","No result for the find command\n");
2636 TFileMerger *fm = 0;
2637 TIter next0(listoffiles);
2638 TObjArray *listoffilestmp = new TObjArray();
2639 listoffilestmp->SetOwner();
2642 // Keep only the files at upper level
2643 Int_t countChar = 0;
2644 while ((nextfile=next0())) {
2645 snextfile = nextfile->GetName();
2646 Int_t crtCount = snextfile.CountChar('/');
2647 if (nextfile == listoffiles->First()) countChar = crtCount;
2648 if (crtCount < countChar) countChar = crtCount;
2651 while ((nextfile=next0())) {
2652 snextfile = nextfile->GetName();
2653 Int_t crtCount = snextfile.CountChar('/');
2654 if (crtCount > countChar) {
2658 listoffilestmp->Add(nextfile);
2661 listoffiles = listoffilestmp; // Now contains 'good' files
2662 listoffiles->Print();
2663 TIter next(listoffiles);
2664 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2665 outputChunk = outputFile;
2666 outputChunk.ReplaceAll(".root", "_*.root");
2667 // Check for existent temporary merge files
2668 // Check overwrite mode and remove previous partial results if needed
2669 // Preserve old merging functionality for stage 0.
2671 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2673 // Skip as many input files as in a chunk
2674 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2677 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2681 snextfile = nextfile->GetName();
2683 outputChunk = outputFile;
2684 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2686 if (gSystem->AccessPathName(outputChunk)) continue;
2687 // Merged file with chunks up to <countChunk> found
2688 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2689 previousChunk = outputChunk;
2693 countZero = nmaxmerge;
2695 while ((nextfile=next())) {
2696 snextfile = nextfile->GetName();
2697 // Loop 'find' results and get next LFN
2698 if (countZero == nmaxmerge) {
2699 // First file in chunk - create file merger and add previous chunk if any.
2700 fm = new TFileMerger(kTRUE);
2701 fm->SetFastMethod(kTRUE);
2702 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2703 outputChunk = outputFile;
2704 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2706 // If last file found, put merged results in the output file
2707 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2708 // Add file to be merged and decrement chunk counter.
2709 fm->AddFile(snextfile);
2711 if (countZero==0 || nextfile == listoffiles->Last()) {
2712 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2713 // Nothing found - skip this output
2714 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2718 fm->OutputFile(outputChunk);
2719 // Merge the outputs, then go to next chunk
2721 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2725 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2726 gSystem->Unlink(previousChunk);
2728 if (nextfile == listoffiles->Last()) break;
2730 countZero = nmaxmerge;
2731 previousChunk = outputChunk;
2738 // Merging stage different than 0.
2739 // Move to the begining of the requested chunk.
2740 fm = new TFileMerger(kTRUE);
2741 fm->SetFastMethod(kTRUE);
2742 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2744 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2745 // Nothing found - skip this output
2746 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2750 fm->OutputFile(outputFile);
2751 // Merge the outputs
2753 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2757 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2763 //______________________________________________________________________________
2764 Bool_t AliAnalysisAlien::MergeOutputs()
2766 // Merge analysis outputs existing in the AliEn space.
2767 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2768 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2770 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2774 if (!TestBit(AliAnalysisGrid::kMerge)) {
2775 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2778 if (fProductionMode) {
2779 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2782 Info("MergeOutputs", "Submitting merging JDL");
2783 if (!SubmitMerging()) return kFALSE;
2784 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2785 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2788 // Get the output path
2789 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2790 if (!DirectoryExists(fGridOutputDir)) {
2791 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2794 if (!fOutputFiles.Length()) {
2795 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2798 // Check if fast read option was requested
2799 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2800 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2801 if (fFastReadOption) {
2802 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2803 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2804 gEnv->SetValue("XNet.ConnectTimeout",50);
2805 gEnv->SetValue("XNet.RequestTimeout",50);
2806 gEnv->SetValue("XNet.MaxRedirectCount",2);
2807 gEnv->SetValue("XNet.ReconnectTimeout",50);
2808 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2810 // Make sure we change the temporary directory
2811 gSystem->Setenv("TMPDIR", gSystem->pwd());
2812 // Set temporary compilation directory to current one
2813 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2814 TObjArray *list = fOutputFiles.Tokenize(",");
2818 Bool_t merged = kTRUE;
2819 while((str=(TObjString*)next())) {
2820 outputFile = str->GetString();
2821 Int_t index = outputFile.Index("@");
2822 if (index > 0) outputFile.Remove(index);
2823 TString outputChunk = outputFile;
2824 outputChunk.ReplaceAll(".root", "_*.root");
2825 // Skip already merged outputs
2826 if (!gSystem->AccessPathName(outputFile)) {
2827 if (fOverwriteMode) {
2828 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2829 gSystem->Unlink(outputFile);
2830 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2831 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2832 outputChunk.Data());
2833 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2836 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2840 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2841 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2842 outputChunk.Data());
2843 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2846 if (fMergeExcludes.Contains(outputFile.Data()) ||
2847 fRegisterExcludes.Contains(outputFile.Data())) continue;
2848 // Perform a 'find' command in the output directory, looking for registered outputs
2849 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2851 Error("MergeOutputs", "Terminate() will NOT be executed");
2854 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2855 if (fileOpened) fileOpened->Close();
2860 //______________________________________________________________________________
2861 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2863 // Use the output files connected to output containers from the analysis manager
2864 // rather than the files defined by SetOutputFiles
2865 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2866 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2867 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2870 //______________________________________________________________________________
2871 void AliAnalysisAlien::SetOutputFiles(const char *list)
2873 // Manually set the output files list.
2874 // Removes duplicates. Not allowed if default outputs are not disabled.
2875 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2876 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2879 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2881 TString slist = list;
2882 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2883 TObjArray *arr = slist.Tokenize(" ");
2887 while ((os=(TObjString*)next())) {
2888 sout = os->GetString();
2889 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2890 if (fOutputFiles.Contains(sout)) continue;
2891 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2892 fOutputFiles += sout;
2897 //______________________________________________________________________________
2898 void AliAnalysisAlien::SetOutputArchive(const char *list)
2900 // Manually set the output archive list. Free text - you are on your own...
2901 // Not allowed if default outputs are not disabled.
2902 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2903 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2906 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2907 fOutputArchive = list;
2910 //______________________________________________________________________________
2911 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2913 // Setting a prefered output SE is not allowed anymore.
2914 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2917 //______________________________________________________________________________
2918 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2920 // Set some PROOF special parameter.
2921 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2923 TObject *old = pair->Key();
2924 TObject *val = pair->Value();
2925 fProofParam.Remove(old);
2929 fProofParam.Add(new TObjString(pname), new TObjString(value));
2932 //______________________________________________________________________________
2933 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2935 // Returns a special PROOF parameter.
2936 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2937 if (!pair) return 0;
2938 return pair->Value()->GetName();
2941 //______________________________________________________________________________
2942 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2944 // Start remote grid analysis.
2945 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2946 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2947 if (!mgr || !mgr->IsInitialized()) {
2948 Error("StartAnalysis", "You need an initialized analysis manager for this");
2951 // Are we in PROOF mode ?
2952 if (mgr->IsProofMode()) {
2953 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2954 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2955 if (fProofCluster.IsNull()) {
2956 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2959 if (fProofDataSet.IsNull() && !testMode) {
2960 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2963 // Set the needed environment
2964 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2965 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2966 if (fProofReset && !testMode) {
2967 if (fProofReset==1) {
2968 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2969 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2971 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2972 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2974 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2979 // Check if there is an old active session
2980 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2982 Error("StartAnalysis","You have to reset your old session first\n");
2986 // Do we need to change the ROOT version ? The success of this cannot be checked.
2987 if (!fRootVersionForProof.IsNull() && !testMode) {
2988 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2989 fProofCluster.Data(), fRootVersionForProof.Data()));
2991 // Connect to PROOF and check the status
2994 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2995 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2997 if (!sworkers.IsNull())
2998 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3000 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3002 proof = gROOT->ProcessLine("TProof::Open(\"\");");
3004 Error("StartAnalysis", "Could not start PROOF in test mode");
3009 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3012 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3013 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3014 // Set proof special parameters if any
3015 TIter nextpp(&fProofParam);
3016 TObject *proofparam;
3017 while ((proofparam=nextpp())) {
3018 TString svalue = GetProofParameter(proofparam->GetName());
3019 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3021 // Is dataset existing ?
3023 TString dataset = fProofDataSet;
3024 Int_t index = dataset.Index("#");
3025 if (index>=0) dataset.Remove(index);
3026 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3027 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3030 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3032 // Is ClearPackages() needed ?
3033 if (TestSpecialBit(kClearPackages)) {
3034 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3035 gROOT->ProcessLine("gProof->ClearPackages();");
3037 // Is a given aliroot mode requested ?
3040 if (!fAliRootMode.IsNull()) {
3041 TString alirootMode = fAliRootMode;
3042 if (alirootMode == "default") alirootMode = "";
3043 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3044 optionsList.SetOwner();
3045 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3046 // Check the additional libs to be loaded
3048 Bool_t parMode = kFALSE;
3049 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3050 // Parse the extra libs for .so
3051 if (fAdditionalLibs.Length()) {
3052 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3055 while((str=(TObjString*)next())) {
3056 if (str->GetString().Contains(".so")) {
3058 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());
3061 TString stmp = str->GetName();
3062 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3063 stmp.ReplaceAll(".so","");
3064 if (!extraLibs.IsNull()) extraLibs += ":";
3068 if (str->GetString().Contains(".par")) {
3069 // The first par file found in the list will not allow any further .so
3071 if (!parLibs.IsNull()) parLibs += ":";
3072 parLibs += str->GetName();
3076 if (list) delete list;
3078 if (!extraLibs.IsNull()) {
3079 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3080 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3082 // Check extra includes
3083 if (!fIncludePath.IsNull()) {
3084 TString includePath = fIncludePath;
3085 includePath.ReplaceAll(" ",":");
3086 includePath.ReplaceAll("$ALICE_ROOT/","");
3087 includePath.ReplaceAll("${ALICE_ROOT}/","");
3088 includePath.ReplaceAll("-I","");
3089 includePath.Remove(TString::kTrailing, ':');
3090 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3091 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3093 // Check if connection to grid is requested
3094 if (TestSpecialBit(kProofConnectGrid))
3095 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3096 // Enable AliRoot par
3098 // Enable proof lite package
3099 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3100 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3101 TNamed *obj = (TNamed*)optionsList.At(i);
3102 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3104 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3105 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3106 Info("StartAnalysis", "AliRootProofLite enabled");
3108 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3112 if ( ! fAliROOTVersion.IsNull() ) {
3113 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3114 fAliROOTVersion.Data(), &optionsList))) {
3115 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3120 // Enable first par files from fAdditionalLibs
3121 if (!parLibs.IsNull()) {
3122 TObjArray *list = parLibs.Tokenize(":");
3124 TObjString *package;
3125 while((package=(TObjString*)next())) {
3126 TString spkg = package->GetName();
3127 spkg.ReplaceAll(".par", "");
3128 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3129 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3130 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3131 if (gROOT->ProcessLine(enablePackage)) {
3132 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3136 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3140 if (list) delete list;
3143 if (fAdditionalLibs.Contains(".so") && !testMode) {
3144 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3145 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3149 // Enable par files if requested
3150 if (fPackages && fPackages->GetEntries()) {
3151 TIter next(fPackages);
3153 while ((package=next())) {
3154 // Skip packages already enabled
3155 if (parLibs.Contains(package->GetName())) continue;
3156 TString spkg = package->GetName();
3157 spkg.ReplaceAll(".par", "");
3158 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3159 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3160 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3161 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3165 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3170 // Do we need to load analysis source files ?
3171 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3172 if (fAnalysisSource.Length()) {
3173 TObjArray *list = fAnalysisSource.Tokenize(" ");
3176 while((str=(TObjString*)next())) {
3177 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3179 if (list) delete list;
3182 // Register dataset to proof lite.
3183 if (fFileForTestMode.IsNull()) {
3184 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3187 if (gSystem->AccessPathName(fFileForTestMode)) {
3188 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3191 TFileCollection *coll = new TFileCollection();
3192 coll->AddFromFile(fFileForTestMode);
3193 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3194 gROOT->ProcessLine("gProof->ShowDataSets()");
3199 // Check if output files have to be taken from the analysis manager
3200 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3201 // Add output files and AOD files
3202 fOutputFiles = GetListOfFiles("outaod");
3203 // Add extra files registered to the analysis manager
3204 TString extra = GetListOfFiles("ext");
3205 if (!extra.IsNull()) {
3206 extra.ReplaceAll(".root", "*.root");
3207 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3208 fOutputFiles += extra;
3210 // Compose the output archive.
3211 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3212 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3214 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3215 if (TestBit(AliAnalysisGrid::kOffline)) {
3216 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3217 \n there nor any job run. You can revise the JDL and analysis \
3218 \n macro then run the same in \"submit\" mode.");
3219 } else if (TestBit(AliAnalysisGrid::kTest)) {
3220 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3222 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3223 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3224 \n space and job submitted.");
3225 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3226 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3227 if (fMergeViaJDL) CheckInputData();
3230 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3235 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3238 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3239 if (!CheckInputData()) {
3240 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3243 if (!CreateDataset(fDataPattern)) {
3245 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3246 if (fRunNumbers.Length()) serror = "run numbers";
3247 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3248 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3249 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3252 WriteAnalysisFile();
3253 WriteAnalysisMacro();
3255 WriteValidationScript();
3257 WriteMergingMacro();
3258 WriteMergeExecutable();
3259 WriteValidationScript(kTRUE);
3261 if (!CreateJDL()) return kFALSE;
3262 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3264 // Locally testing the analysis
3265 Info("StartAnalysis", "\n_______________________________________________________________________ \
3266 \n Running analysis script in a daughter shell as on a worker node \
3267 \n_______________________________________________________________________");
3268 TObjArray *list = fOutputFiles.Tokenize(",");
3272 while((str=(TObjString*)next())) {
3273 outputFile = str->GetString();
3274 Int_t index = outputFile.Index("@");
3275 if (index > 0) outputFile.Remove(index);
3276 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3279 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3280 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3281 // gSystem->Exec("cat stdout");
3284 // Check if submitting is managed by LPM manager
3285 if (fProductionMode) {
3286 TString prodfile = fJDLName;
3287 prodfile.ReplaceAll(".jdl", ".prod");
3288 WriteProductionFile(prodfile);
3289 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3292 // Submit AliEn job(s)
3293 gGrid->Cd(fGridOutputDir);
3296 if (!fRunNumbers.Length() && !fRunRange[0]) {
3297 // Submit a given xml or a set of runs
3298 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3299 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3301 const char *cjobId = res->GetKey(0,"jobId");
3305 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3308 Info("StartAnalysis", "\n_______________________________________________________________________ \
3309 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3310 \n_______________________________________________________________________",
3311 fJDLName.Data(), cjobId);
3316 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3320 // Submit for a range of enumeration of runs.
3321 if (!Submit()) return kFALSE;
3324 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3325 \n You may exit at any time and terminate the job later using the option <terminate> \
3326 \n ##################################################################################", jobID.Data());
3327 gSystem->Exec("aliensh");
3331 //______________________________________________________________________________
3332 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3334 // Get a comma-separated list of output files of the requested type.
3335 // Type can be (case unsensitive):
3336 // aod - list of aod files (std, extensions and filters)
3337 // out - list of output files connected to containers (but not aod's or extras)
3338 // ext - list of extra files registered to the manager
3339 // ter - list of files produced in terminate
3340 static TString files;
3342 TString stype = type;
3344 TString aodfiles, extra;
3345 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3347 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3348 return files.Data();
3350 if (mgr->GetOutputEventHandler()) {
3351 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3352 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3353 if (!extraaod.IsNull()) {
3355 aodfiles += extraaod;
3358 if (stype.Contains("aod")) {
3360 if (stype == "aod") return files.Data();
3362 // Add output files that are not in the list of AOD files
3363 TString outputfiles = "";
3364 TIter next(mgr->GetOutputs());
3365 AliAnalysisDataContainer *output;
3366 const char *filename = 0;
3367 while ((output=(AliAnalysisDataContainer*)next())) {
3368 filename = output->GetFileName();
3369 if (!(strcmp(filename, "default"))) continue;
3370 if (outputfiles.Contains(filename)) continue;
3371 if (aodfiles.Contains(filename)) continue;
3372 if (!outputfiles.IsNull()) outputfiles += ",";
3373 outputfiles += filename;
3375 if (stype.Contains("out")) {
3376 if (!files.IsNull()) files += ",";
3377 files += outputfiles;
3378 if (stype == "out") return files.Data();
3380 // Add extra files registered to the analysis manager
3382 extra = mgr->GetExtraFiles();
3383 if (!extra.IsNull()) {
3385 extra.ReplaceAll(" ", ",");
3386 TObjArray *fextra = extra.Tokenize(",");
3387 TIter nextx(fextra);
3389 while ((obj=nextx())) {
3390 if (aodfiles.Contains(obj->GetName())) continue;
3391 if (outputfiles.Contains(obj->GetName())) continue;
3392 if (sextra.Contains(obj->GetName())) continue;
3393 if (!sextra.IsNull()) sextra += ",";
3394 sextra += obj->GetName();
3397 if (stype.Contains("ext")) {
3398 if (!files.IsNull()) files += ",";
3402 if (stype == "ext") return files.Data();
3404 if (!fTerminateFiles.IsNull()) {
3405 fTerminateFiles.Strip();
3406 fTerminateFiles.ReplaceAll(" ",",");
3407 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3408 TIter nextx(fextra);
3410 while ((obj=nextx())) {
3411 if (aodfiles.Contains(obj->GetName())) continue;
3412 if (outputfiles.Contains(obj->GetName())) continue;
3413 if (termfiles.Contains(obj->GetName())) continue;
3414 if (sextra.Contains(obj->GetName())) continue;
3415 if (!termfiles.IsNull()) termfiles += ",";
3416 termfiles += obj->GetName();
3420 if (stype.Contains("ter")) {
3421 if (!files.IsNull() && !termfiles.IsNull()) {
3426 return files.Data();
3429 //______________________________________________________________________________
3430 Bool_t AliAnalysisAlien::Submit()
3432 // Submit all master jobs.
3433 Int_t nmasterjobs = fInputFiles->GetEntries();
3434 Long_t tshoot = gSystem->Now();
3435 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3436 while (fNsubmitted < nmasterjobs) {
3437 Long_t now = gSystem->Now();
3438 if ((now-tshoot)>30000) {
3440 if (!SubmitNext()) return kFALSE;
3446 //______________________________________________________________________________
3447 Bool_t AliAnalysisAlien::SubmitMerging()
3449 // Submit all merging jobs.
3450 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3451 gGrid->Cd(fGridOutputDir);
3452 TString mergeJDLName = fExecutable;
3453 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3455 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3458 Int_t ntosubmit = fInputFiles->GetEntries();
3459 for (Int_t i=0; i<ntosubmit; i++) {
3460 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3461 runOutDir.ReplaceAll(".xml", "");
3462 if (fOutputToRunNo) {
3463 // The output directory is the run number
3464 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3465 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3467 if (!fRunNumbers.Length() && !fRunRange[0]) {
3468 // The output directory is the grid outdir
3469 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3470 runOutDir = fGridOutputDir;
3472 // The output directory is the master number in 3 digits format
3473 printf("### Submitting merging job for master <%03d>\n", i);
3474 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3477 // Check now the number of merging stages.
3478 TObjArray *list = fOutputFiles.Tokenize(",");
3482 while((str=(TObjString*)next())) {
3483 outputFile = str->GetString();
3484 Int_t index = outputFile.Index("@");
3485 if (index > 0) outputFile.Remove(index);
3486 if (!fMergeExcludes.Contains(outputFile) &&
3487 !fRegisterExcludes.Contains(outputFile)) break;
3490 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3491 if (!done && (i==ntosubmit-1)) return kFALSE;
3492 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3494 if (!ntosubmit) return kTRUE;
3495 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3496 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3497 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3498 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3499 \n ################################################################################################################");
3500 gSystem->Exec("aliensh");
3504 //______________________________________________________________________________
3505 Bool_t AliAnalysisAlien::SubmitNext()
3507 // Submit next bunch of master jobs if the queue is free. The first master job is
3508 // submitted right away, while the next will not be unless the previous was split.
3509 // The plugin will not submit new master jobs if there are more that 500 jobs in
3511 static Bool_t iscalled = kFALSE;
3512 static Int_t firstmaster = 0;
3513 static Int_t lastmaster = 0;
3514 static Int_t npermaster = 0;
3515 if (iscalled) return kTRUE;
3517 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3518 Int_t ntosubmit = 0;
3521 Int_t nmasterjobs = fInputFiles->GetEntries();
3524 if (!IsUseSubmitPolicy()) {
3526 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3527 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3528 ntosubmit = nmasterjobs;
3531 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3532 printf("=== master %d: %s\n", lastmaster, status.Data());
3533 // If last master not split, just return
3534 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3535 // No more than 100 waiting jobs
3536 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3537 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3538 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3539 if (!ntosubmit) ntosubmit = 1;
3540 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3541 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3543 for (Int_t i=0; i<ntosubmit; i++) {
3544 // Submit for a range of enumeration of runs.
3545 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3547 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3548 runOutDir.ReplaceAll(".xml", "");
3550 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3552 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3553 printf("********* %s\n",query.Data());
3554 res = gGrid->Command(query);
3556 TString cjobId1 = res->GetKey(0,"jobId");
3557 if (!cjobId1.Length()) {
3561 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3564 Info("StartAnalysis", "\n_______________________________________________________________________ \
3565 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3566 \n_______________________________________________________________________",
3567 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3570 lastmaster = cjobId1.Atoi();
3571 if (!firstmaster) firstmaster = lastmaster;
3576 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3584 //______________________________________________________________________________
3585 void AliAnalysisAlien::WriteAnalysisFile()
3587 // Write current analysis manager into the file <analysisFile>
3588 TString analysisFile = fExecutable;
3589 analysisFile.ReplaceAll(".sh", ".root");
3590 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3591 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3592 if (!mgr || !mgr->IsInitialized()) {
3593 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3596 // Check analysis type
3598 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3599 handler = (TObject*)mgr->GetInputEventHandler();
3601 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3602 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3603 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3604 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3606 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3607 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3610 TDirectory *cdir = gDirectory;
3611 TFile *file = TFile::Open(analysisFile, "RECREATE");
3613 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3614 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3615 // Unless merging makes no sense
3616 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3619 // Enable termination for local jobs
3620 mgr->SetSkipTerminate(kFALSE);
3622 if (cdir) cdir->cd();
3623 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3625 Bool_t copy = kTRUE;
3626 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3629 TString workdir = gGrid->GetHomeDirectory();
3630 workdir += fGridWorkingDir;
3631 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3632 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3633 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3634 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3638 //______________________________________________________________________________
3639 void AliAnalysisAlien::WriteAnalysisMacro()
3641 // Write the analysis macro that will steer the analysis in grid mode.
3642 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3644 out.open(fAnalysisMacro.Data(), ios::out);
3646 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3649 Bool_t hasSTEERBase = kFALSE;
3650 Bool_t hasESD = kFALSE;
3651 Bool_t hasAOD = kFALSE;
3652 Bool_t hasANALYSIS = kFALSE;
3653 Bool_t hasOADB = kFALSE;
3654 Bool_t hasANALYSISalice = kFALSE;
3655 Bool_t hasCORRFW = kFALSE;
3656 TString func = fAnalysisMacro;
3657 TString type = "ESD";
3658 TString comment = "// Analysis using ";
3659 if (IsUseMCchain()) {
3663 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3664 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3669 if (type!="AOD" && fFriendChainName!="") {
3670 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3673 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3674 else comment += " data";
3675 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3676 func.ReplaceAll(".C", "");
3677 out << "void " << func.Data() << "()" << endl;
3679 out << comment.Data() << endl;
3680 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3681 out << " TStopwatch timer;" << endl;
3682 out << " timer.Start();" << endl << endl;
3683 // Change temp directory to current one
3684 out << "// Set temporary merging directory to current one" << endl;
3685 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3686 out << "// Set temporary compilation directory to current one" << endl;
3687 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3688 // Reset existing include path
3689 out << "// Reset existing include path and add current directory first in the search" << endl;
3690 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3691 if (!fExecutableCommand.Contains("aliroot")) {
3692 out << "// load base root libraries" << endl;
3693 out << " gSystem->Load(\"libTree\");" << endl;
3694 out << " gSystem->Load(\"libGeom\");" << endl;
3695 out << " gSystem->Load(\"libVMC\");" << endl;
3696 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3697 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3699 if (fAdditionalRootLibs.Length()) {
3700 // in principle libtree /lib geom libvmc etc. can go into this list, too
3701 out << "// Add aditional libraries" << endl;
3702 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3705 while((str=(TObjString*)next())) {
3706 if (str->GetString().Contains(".so"))
3707 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3709 if (list) delete list;
3711 out << "// Load analysis framework libraries" << endl;
3712 TString setupPar = "AliAnalysisAlien::SetupPar";
3714 if (!fExecutableCommand.Contains("aliroot")) {
3715 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3716 out << " gSystem->Load(\"libESD\");" << endl;
3717 out << " gSystem->Load(\"libAOD\");" << endl;
3719 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3720 out << " gSystem->Load(\"libOADB\");" << endl;
3721 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3722 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3724 TIter next(fPackages);
3727 while ((obj=next())) {
3728 pkgname = obj->GetName();
3729 if (pkgname == "STEERBase" ||
3730 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3731 if (pkgname == "ESD" ||
3732 pkgname == "ESD.par") hasESD = kTRUE;
3733 if (pkgname == "AOD" ||
3734 pkgname == "AOD.par") hasAOD = kTRUE;
3735 if (pkgname == "ANALYSIS" ||
3736 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3737 if (pkgname == "OADB" ||
3738 pkgname == "OADB.par") hasOADB = kTRUE;
3739 if (pkgname == "ANALYSISalice" ||
3740 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3741 if (pkgname == "CORRFW" ||
3742 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3744 if (hasANALYSISalice) setupPar = "SetupPar";
3745 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3746 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3747 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3748 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3749 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3750 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3751 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3752 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3753 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3754 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3755 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3756 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3757 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3758 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3759 out << "// Compile other par packages" << endl;
3761 while ((obj=next())) {
3762 pkgname = obj->GetName();
3763 if (pkgname == "STEERBase" ||
3764 pkgname == "STEERBase.par" ||
3766 pkgname == "ESD.par" ||
3768 pkgname == "AOD.par" ||
3769 pkgname == "ANALYSIS" ||
3770 pkgname == "ANALYSIS.par" ||
3771 pkgname == "OADB" ||
3772 pkgname == "OADB.par" ||
3773 pkgname == "ANALYSISalice" ||
3774 pkgname == "ANALYSISalice.par" ||
3775 pkgname == "CORRFW" ||
3776 pkgname == "CORRFW.par") continue;
3777 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3780 out << "// include path" << endl;
3781 // Get the include path from the interpreter and remove entries pointing to AliRoot
3782 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3783 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3784 out << " TIter nextpath(listpaths);" << endl;
3785 out << " TObjString *pname;" << endl;
3786 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3787 out << " TString current = pname->GetName();" << endl;
3788 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3789 out << " gSystem->AddIncludePath(current);" << endl;
3790 out << " }" << endl;
3791 out << " if (listpaths) delete listpaths;" << endl;
3792 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3793 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3794 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3795 if (fAdditionalLibs.Length()) {
3796 out << "// Add aditional AliRoot libraries" << endl;
3797 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3800 while((str=(TObjString*)next())) {
3801 if (str->GetString().Contains(".so"))
3802 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3803 if (str->GetString().Contains(".par"))
3804 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3806 if (list) delete list;
3809 out << "// analysis source to be compiled at runtime (if any)" << endl;
3810 if (fAnalysisSource.Length()) {
3811 TObjArray *list = fAnalysisSource.Tokenize(" ");
3814 while((str=(TObjString*)next())) {
3815 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3817 if (list) delete list;
3820 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3821 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3822 if (fFastReadOption) {
3823 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 !!! \
3824 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3825 out << "// fast xrootd reading enabled" << endl;
3826 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3827 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3828 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3829 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3830 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3831 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3833 if (!IsLocalTest()) {
3834 out << "// connect to AliEn and make the chain" << endl;
3835 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3837 out << "// read the analysis manager from file" << endl;
3838 TString analysisFile = fExecutable;
3839 analysisFile.ReplaceAll(".sh", ".root");
3840 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3841 << analysisFile << "\");" << endl;
3842 out << " if (!mgr) return;" << endl;
3843 if (IsLocalTest()) {
3844 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3845 out << " plugin->SetRunMode(\"test\");" << endl;
3846 if (fFileForTestMode.IsNull())
3847 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3849 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3850 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3851 out << " mgr->SetGridHandler(plugin);" << endl;
3852 if (AliAnalysisManager::GetAnalysisManager()) {
3853 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3854 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3856 out << " mgr->SetDebugLevel(10);" << endl;
3857 out << " mgr->SetNSysInfo(100);" << endl;
3860 out << " mgr->PrintStatus();" << endl;
3861 if (AliAnalysisManager::GetAnalysisManager()) {
3862 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3863 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3865 if (TestBit(AliAnalysisGrid::kTest))
3866 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3868 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3871 if (!IsLocalTest()) {
3872 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3873 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3875 out << " mgr->StartAnalysis(\"localfile\");" << endl;
3877 out << " timer.Stop();" << endl;
3878 out << " timer.Print();" << endl;
3879 out << "}" << endl << endl;
3880 if (!IsLocalTest()) {
3881 out <<"//________________________________________________________________________________" << endl;
3882 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3884 out << "// Create a chain using url's from xml file" << endl;
3885 out << " TString filename;" << endl;
3886 out << " Int_t run = 0;" << endl;
3887 if (IsUseMCchain()) {
3888 out << " TString treename = \"TE\";" << endl;
3890 out << " TString treename = type;" << endl;
3891 out << " treename.ToLower();" << endl;
3892 out << " treename += \"Tree\";" << endl;
3894 out << " printf(\"***************************************\\n\");" << endl;
3895 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3896 out << " printf(\"***************************************\\n\");" << endl;
3897 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3898 out << " if (!coll) {" << endl;
3899 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3900 out << " return NULL;" << endl;
3901 out << " }" << endl;
3902 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3903 out << " TChain *chain = new TChain(treename);" << endl;
3904 if(fFriendChainName!="") {
3905 out << " TChain *chainFriend = new TChain(treename);" << endl;
3907 out << " coll->Reset();" << endl;
3908 out << " while (coll->Next()) {" << endl;
3909 out << " filename = coll->GetTURL("");" << endl;
3910 out << " if (mgr) {" << endl;
3911 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3912 out << " if (nrun && nrun != run) {" << endl;
3913 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3914 out << " mgr->SetRunFromPath(nrun);" << endl;
3915 out << " run = nrun;" << endl;
3916 out << " }" << endl;
3917 out << " }" << endl;
3918 out << " chain->Add(filename);" << endl;
3919 if(fFriendChainName!="") {
3920 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3921 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3922 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3923 out << " chainFriend->Add(fileFriend.Data());" << endl;
3925 out << " }" << endl;
3926 out << " if (!chain->GetNtrees()) {" << endl;
3927 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3928 out << " return NULL;" << endl;
3929 out << " }" << endl;
3930 if(fFriendChainName!="") {
3931 out << " chain->AddFriend(chainFriend);" << endl;
3933 out << " return chain;" << endl;
3934 out << "}" << endl << endl;
3936 if (hasANALYSISalice) {
3937 out <<"//________________________________________________________________________________" << endl;
3938 out << "Bool_t SetupPar(const char *package) {" << endl;
3939 out << "// Compile the package and set it up." << endl;
3940 out << " TString pkgdir = package;" << endl;
3941 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3942 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3943 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3944 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3945 out << " // Check for BUILD.sh and execute" << endl;
3946 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3947 out << " printf(\"*******************************\\n\");" << endl;
3948 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3949 out << " printf(\"*******************************\\n\");" << endl;
3950 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3951 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3952 out << " gSystem->ChangeDirectory(cdir);" << endl;
3953 out << " return kFALSE;" << endl;
3954 out << " }" << endl;
3955 out << " } else {" << endl;
3956 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3957 out << " gSystem->ChangeDirectory(cdir);" << endl;
3958 out << " return kFALSE;" << endl;
3959 out << " }" << endl;
3960 out << " // Check for SETUP.C and execute" << endl;
3961 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3962 out << " printf(\"*******************************\\n\");" << endl;
3963 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3964 out << " printf(\"*******************************\\n\");" << endl;
3965 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3966 out << " } else {" << endl;
3967 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3968 out << " gSystem->ChangeDirectory(cdir);" << endl;
3969 out << " return kFALSE;" << endl;
3970 out << " }" << endl;
3971 out << " // Restore original workdir" << endl;
3972 out << " gSystem->ChangeDirectory(cdir);" << endl;
3973 out << " return kTRUE;" << endl;
3976 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3978 Bool_t copy = kTRUE;
3979 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3982 TString workdir = gGrid->GetHomeDirectory();
3983 workdir += fGridWorkingDir;
3984 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3985 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3986 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3987 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
3988 Form("alien://%s/%s", workdir.Data(),
3989 fAnalysisMacro.Data()))) Fatal("","Terminating");
3993 //______________________________________________________________________________
3994 void AliAnalysisAlien::WriteMergingMacro()
3996 // Write a macro to merge the outputs per master job.
3997 if (!fMergeViaJDL) return;
3998 if (!fOutputFiles.Length()) {
3999 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4002 TString mergingMacro = fExecutable;
4003 mergingMacro.ReplaceAll(".sh","_merge.C");
4004 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4005 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4007 out.open(mergingMacro.Data(), ios::out);
4009 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4012 Bool_t hasSTEERBase = kFALSE;
4013 Bool_t hasESD = kFALSE;
4014 Bool_t hasAOD = kFALSE;
4015 Bool_t hasANALYSIS = kFALSE;
4016 Bool_t hasOADB = kFALSE;
4017 Bool_t hasANALYSISalice = kFALSE;
4018 Bool_t hasCORRFW = kFALSE;
4019 TString func = mergingMacro;
4021 func.ReplaceAll(".C", "");
4022 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4024 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4025 out << " TStopwatch timer;" << endl;
4026 out << " timer.Start();" << endl << endl;
4027 // Reset existing include path
4028 out << "// Reset existing include path and add current directory first in the search" << endl;
4029 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4030 if (!fExecutableCommand.Contains("aliroot")) {
4031 out << "// load base root libraries" << endl;
4032 out << " gSystem->Load(\"libTree\");" << endl;
4033 out << " gSystem->Load(\"libGeom\");" << endl;
4034 out << " gSystem->Load(\"libVMC\");" << endl;
4035 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4036 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4038 if (fAdditionalRootLibs.Length()) {
4039 // in principle libtree /lib geom libvmc etc. can go into this list, too
4040 out << "// Add aditional libraries" << endl;
4041 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4044 while((str=(TObjString*)next())) {
4045 if (str->GetString().Contains(".so"))
4046 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4048 if (list) delete list;
4050 out << "// Load analysis framework libraries" << endl;
4052 if (!fExecutableCommand.Contains("aliroot")) {
4053 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4054 out << " gSystem->Load(\"libESD\");" << endl;
4055 out << " gSystem->Load(\"libAOD\");" << endl;
4057 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4058 out << " gSystem->Load(\"libOADB\");" << endl;
4059 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4060 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4062 TIter next(fPackages);
4065 TString setupPar = "AliAnalysisAlien::SetupPar";
4066 while ((obj=next())) {
4067 pkgname = obj->GetName();
4068 if (pkgname == "STEERBase" ||
4069 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4070 if (pkgname == "ESD" ||
4071 pkgname == "ESD.par") hasESD = kTRUE;
4072 if (pkgname == "AOD" ||
4073 pkgname == "AOD.par") hasAOD = kTRUE;
4074 if (pkgname == "ANALYSIS" ||
4075 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4076 if (pkgname == "OADB" ||
4077 pkgname == "OADB.par") hasOADB = kTRUE;
4078 if (pkgname == "ANALYSISalice" ||
4079 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4080 if (pkgname == "CORRFW" ||
4081 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4083 if (hasANALYSISalice) setupPar = "SetupPar";
4084 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4085 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4086 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4087 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4088 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4089 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4090 out << " gSystem->Load(\"libOADB\");" << endl;
4091 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4092 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4093 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4094 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4095 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4096 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4097 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4098 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4099 out << "// Compile other par packages" << endl;
4101 while ((obj=next())) {
4102 pkgname = obj->GetName();
4103 if (pkgname == "STEERBase" ||
4104 pkgname == "STEERBase.par" ||
4106 pkgname == "ESD.par" ||
4108 pkgname == "AOD.par" ||
4109 pkgname == "ANALYSIS" ||
4110 pkgname == "ANALYSIS.par" ||
4111 pkgname == "OADB" ||
4112 pkgname == "OADB.par" ||
4113 pkgname == "ANALYSISalice" ||
4114 pkgname == "ANALYSISalice.par" ||
4115 pkgname == "CORRFW" ||
4116 pkgname == "CORRFW.par") continue;
4117 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4120 out << "// include path" << endl;
4121 // Get the include path from the interpreter and remove entries pointing to AliRoot
4122 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4123 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4124 out << " TIter nextpath(listpaths);" << endl;
4125 out << " TObjString *pname;" << endl;
4126 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4127 out << " TString current = pname->GetName();" << endl;
4128 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4129 out << " gSystem->AddIncludePath(current);" << endl;
4130 out << " }" << endl;
4131 out << " if (listpaths) delete listpaths;" << endl;
4132 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4133 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4134 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4135 if (fAdditionalLibs.Length()) {
4136 out << "// Add aditional AliRoot libraries" << endl;
4137 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4140 while((str=(TObjString*)next())) {
4141 if (str->GetString().Contains(".so"))
4142 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4144 if (list) delete list;
4147 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4148 if (fAnalysisSource.Length()) {
4149 TObjArray *list = fAnalysisSource.Tokenize(" ");
4152 while((str=(TObjString*)next())) {
4153 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4155 if (list) delete list;
4159 if (fFastReadOption) {
4160 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 !!!");
4161 out << "// fast xrootd reading enabled" << endl;
4162 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4163 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4164 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4165 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4166 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4167 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4169 // Change temp directory to current one
4170 out << "// Set temporary merging directory to current one" << endl;
4171 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4172 out << "// Set temporary compilation directory to current one" << endl;
4173 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4174 out << "// Connect to AliEn" << endl;
4175 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4176 out << " TString outputDir = dir;" << endl;
4177 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4178 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4179 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4180 out << " TIter *iter = new TIter(list);" << endl;
4181 out << " TObjString *str;" << endl;
4182 out << " TString outputFile;" << endl;
4183 out << " Bool_t merged = kTRUE;" << endl;
4184 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4185 out << " outputFile = str->GetString();" << endl;
4186 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4187 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4188 out << " if (index > 0) outputFile.Remove(index);" << endl;
4189 out << " // Skip already merged outputs" << endl;
4190 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4191 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4192 out << " continue;" << endl;
4193 out << " }" << endl;
4194 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4195 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4196 out << " if (!merged) {" << endl;
4197 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4198 out << " return;" << endl;
4199 out << " }" << endl;
4200 out << " }" << endl;
4201 out << " // all outputs merged, validate" << endl;
4202 out << " ofstream out;" << endl;
4203 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4204 out << " out.close();" << endl;
4205 out << " // read the analysis manager from file" << endl;
4206 TString analysisFile = fExecutable;
4207 analysisFile.ReplaceAll(".sh", ".root");
4208 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4209 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4210 << analysisFile << "\");" << endl;
4211 out << " if (!mgr) return;" << endl;
4212 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4213 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4214 out << " mgr->PrintStatus();" << endl;
4215 if (AliAnalysisManager::GetAnalysisManager()) {
4216 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4217 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4219 if (TestBit(AliAnalysisGrid::kTest))
4220 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4222 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4225 out << " TTree *tree = NULL;" << endl;
4226 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4227 out << "}" << endl << endl;
4228 if (hasANALYSISalice) {
4229 out <<"//________________________________________________________________________________" << endl;
4230 out << "Bool_t SetupPar(const char *package) {" << endl;
4231 out << "// Compile the package and set it up." << endl;
4232 out << " TString pkgdir = package;" << endl;
4233 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4234 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4235 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4236 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4237 out << " // Check for BUILD.sh and execute" << endl;
4238 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4239 out << " printf(\"*******************************\\n\");" << endl;
4240 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4241 out << " printf(\"*******************************\\n\");" << endl;
4242 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4243 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4244 out << " gSystem->ChangeDirectory(cdir);" << endl;
4245 out << " return kFALSE;" << endl;
4246 out << " }" << endl;
4247 out << " } else {" << endl;
4248 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4249 out << " gSystem->ChangeDirectory(cdir);" << endl;
4250 out << " return kFALSE;" << endl;
4251 out << " }" << endl;
4252 out << " // Check for SETUP.C and execute" << endl;
4253 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4254 out << " printf(\"*******************************\\n\");" << endl;
4255 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4256 out << " printf(\"*******************************\\n\");" << endl;
4257 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4258 out << " } else {" << endl;
4259 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4260 out << " gSystem->ChangeDirectory(cdir);" << endl;
4261 out << " return kFALSE;" << endl;
4262 out << " }" << endl;
4263 out << " // Restore original workdir" << endl;
4264 out << " gSystem->ChangeDirectory(cdir);" << endl;
4265 out << " return kTRUE;" << endl;
4269 Bool_t copy = kTRUE;
4270 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4273 TString workdir = gGrid->GetHomeDirectory();
4274 workdir += fGridWorkingDir;
4275 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4276 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4277 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4278 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4279 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4283 //______________________________________________________________________________
4284 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4286 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4287 // Note that for loading the compiled library. The current directory should have precedence in
4289 TString pkgdir = package;
4290 pkgdir.ReplaceAll(".par","");
4291 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4292 TString cdir = gSystem->WorkingDirectory();
4293 gSystem->ChangeDirectory(pkgdir);
4294 // Check for BUILD.sh and execute
4295 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4296 printf("**************************************************\n");
4297 printf("*** Building PAR archive %s\n", package);
4298 printf("**************************************************\n");
4299 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4300 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4301 gSystem->ChangeDirectory(cdir);
4305 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4306 gSystem->ChangeDirectory(cdir);
4309 // Check for SETUP.C and execute
4310 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4311 printf("**************************************************\n");
4312 printf("*** Setup PAR archive %s\n", package);
4313 printf("**************************************************\n");
4314 gROOT->Macro("PROOF-INF/SETUP.C");
4315 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4317 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4318 gSystem->ChangeDirectory(cdir);
4321 // Restore original workdir
4322 gSystem->ChangeDirectory(cdir);
4326 //______________________________________________________________________________
4327 void AliAnalysisAlien::WriteExecutable()
4329 // Generate the alien executable script.
4330 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4332 out.open(fExecutable.Data(), ios::out);
4334 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4337 out << "#!/bin/bash" << endl;
4338 // Make sure we can properly compile par files
4339 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4340 out << "echo \"=========================================\"" << endl;
4341 out << "echo \"############## PATH : ##############\"" << endl;
4342 out << "echo $PATH" << endl;
4343 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4344 out << "echo $LD_LIBRARY_PATH" << endl;
4345 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4346 out << "echo $ROOTSYS" << endl;
4347 out << "echo \"############## which root : ##############\"" << endl;
4348 out << "which root" << endl;
4349 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4350 out << "echo $ALICE_ROOT" << endl;
4351 out << "echo \"############## which aliroot : ##############\"" << endl;
4352 out << "which aliroot" << endl;
4353 out << "echo \"############## system limits : ##############\"" << endl;
4354 out << "ulimit -a" << endl;
4355 out << "echo \"############## memory : ##############\"" << endl;
4356 out << "free -m" << endl;
4357 out << "echo \"=========================================\"" << endl << endl;
4358 out << fExecutableCommand << " ";
4359 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4360 out << "RET=$?" << endl;
4361 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4362 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4363 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4364 out << " let sig=\"$RET - 128\""<<endl;
4365 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4366 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4367 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4368 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4369 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4370 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4372 out << " exit $RET"<< endl;
4373 out << "fi" << endl << endl ;
4374 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4375 out << "echo \"############## memory after: ##############\"" << endl;
4376 out << "free -m" << endl;
4378 Bool_t copy = kTRUE;
4379 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4382 TString workdir = gGrid->GetHomeDirectory();
4383 TString bindir = Form("%s/bin", workdir.Data());
4384 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4385 workdir += fGridWorkingDir;
4386 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4387 if (FileExists(executable)) gGrid->Rm(executable);
4388 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4389 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4390 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4391 executable.Data())) Fatal("","Terminating");
4395 //______________________________________________________________________________
4396 void AliAnalysisAlien::WriteMergeExecutable()
4398 // Generate the alien executable script for the merging job.
4399 if (!fMergeViaJDL) return;
4400 TString mergeExec = fExecutable;
4401 mergeExec.ReplaceAll(".sh", "_merge.sh");
4402 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4404 out.open(mergeExec.Data(), ios::out);
4406 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4409 out << "#!/bin/bash" << endl;
4410 // Make sure we can properly compile par files
4411 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4412 out << "echo \"=========================================\"" << endl;
4413 out << "echo \"############## PATH : ##############\"" << endl;
4414 out << "echo $PATH" << endl;
4415 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4416 out << "echo $LD_LIBRARY_PATH" << endl;
4417 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4418 out << "echo $ROOTSYS" << endl;
4419 out << "echo \"############## which root : ##############\"" << endl;
4420 out << "which root" << endl;
4421 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4422 out << "echo $ALICE_ROOT" << endl;
4423 out << "echo \"############## which aliroot : ##############\"" << endl;
4424 out << "which aliroot" << endl;
4425 out << "echo \"############## system limits : ##############\"" << endl;
4426 out << "ulimit -a" << endl;
4427 out << "echo \"############## memory : ##############\"" << endl;
4428 out << "free -m" << endl;
4429 out << "echo \"=========================================\"" << endl << endl;
4430 TString mergeMacro = fExecutable;
4431 mergeMacro.ReplaceAll(".sh", "_merge.C");
4432 if (IsOneStageMerging())
4433 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4435 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4436 out << fExecutableCommand << " " << "$ARG" << endl;
4437 out << "RET=$?" << endl;
4438 out << "if [ \"$RET\" != \"0\" ];then" << endl;
4439 out << " echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4440 out << " if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4441 out << " let sig=\"$RET - 128\""<<endl;
4442 out << " sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4443 out << " KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4444 out << " CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4445 out << " XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4446 out << " sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4447 out << " echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4449 out << " exit $RET"<< endl;
4450 out << "fi" << endl << endl ;
4451 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4452 out << "echo \"############## memory after: ##############\"" << endl;
4453 out << "free -m" << endl;
4455 Bool_t copy = kTRUE;
4456 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4459 TString workdir = gGrid->GetHomeDirectory();
4460 TString bindir = Form("%s/bin", workdir.Data());
4461 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4462 workdir += fGridWorkingDir;
4463 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4464 if (FileExists(executable)) gGrid->Rm(executable);
4465 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4466 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4467 if (!copyLocal2Alien("WriteMergeExecutable",
4468 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4472 //______________________________________________________________________________
4473 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4475 // Write the production file to be submitted by LPM manager. The format is:
4476 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4477 // Next lines: full_path_to_dataset XXX (XXX is a string)
4478 // To submit, one has to: submit jdl XXX for all lines
4480 out.open(filename, ios::out);
4482 Error("WriteProductionFile", "Bad file name: %s", filename);
4486 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4487 workdir = gGrid->GetHomeDirectory();
4488 workdir += fGridWorkingDir;
4489 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4490 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4491 out << locjdl << " " << njobspermaster << endl;
4492 Int_t nmasterjobs = fInputFiles->GetEntries();
4493 for (Int_t i=0; i<nmasterjobs; i++) {
4494 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4495 runOutDir.ReplaceAll(".xml", "");
4497 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4499 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4502 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4503 if (FileExists(filename)) gGrid->Rm(filename);
4504 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4505 if (!copyLocal2Alien("WriteProductionFile", filename,
4506 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4510 //______________________________________________________________________________
4511 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4513 // Generate the alien validation script.
4514 // Generate the validation script
4516 if (fValidationScript.IsNull()) {
4517 fValidationScript = fExecutable;
4518 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4520 TString validationScript = fValidationScript;
4521 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4523 Error("WriteValidationScript", "Alien connection required");
4526 if (!fTerminateFiles.IsNull()) {
4527 fTerminateFiles.Strip();
4528 fTerminateFiles.ReplaceAll(" ",",");
4530 TString outStream = "";
4531 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4532 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4534 out.open(validationScript, ios::out);
4535 out << "#!/bin/bash" << endl;
4536 out << "##################################################" << endl;
4537 out << "validateout=`dirname $0`" << endl;
4538 out << "validatetime=`date`" << endl;
4539 out << "validated=\"0\";" << endl;
4540 out << "error=0" << endl;
4541 out << "if [ -z $validateout ]" << endl;
4542 out << "then" << endl;
4543 out << " validateout=\".\"" << endl;
4544 out << "fi" << endl << endl;
4545 out << "cd $validateout;" << endl;
4546 out << "validateworkdir=`pwd`;" << endl << endl;
4547 out << "echo \"*******************************************************\"" << outStream << endl;
4548 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4550 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4551 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4552 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4553 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4554 out << "ls -la ./" << outStream << endl;
4555 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4556 out << "##################################################" << endl;
4559 out << "if [ ! -f stderr ] ; then" << endl;
4560 out << " error=1" << endl;
4561 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4562 out << " echo \"Error = $error\" " << outStream << endl;
4563 out << "fi" << endl;
4565 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4566 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4567 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4568 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4571 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4572 out << " error=1" << endl;
4573 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4574 out << " echo \"$parArch\" " << outStream << endl;
4575 out << " echo \"Error = $error\" " << outStream << endl;
4576 out << "fi" << endl;
4578 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4579 out << " error=1" << endl;
4580 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4581 out << " echo \"$segViol\" " << outStream << endl;
4582 out << " echo \"Error = $error\" " << outStream << endl;
4583 out << "fi" << endl;
4585 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4586 out << " error=1" << endl;
4587 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4588 out << " echo \"$segFault\" " << outStream << endl;
4589 out << " echo \"Error = $error\" " << outStream << endl;
4590 out << "fi" << endl;
4592 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4593 out << " error=1" << endl;
4594 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4595 out << " echo \"$glibcErr\" " << outStream << endl;
4596 out << " echo \"Error = $error\" " << outStream << endl;
4597 out << "fi" << endl;
4599 // Part dedicated to the specific analyses running into the train
4601 TString outputFiles = fOutputFiles;
4602 if (merge && !fTerminateFiles.IsNull()) {
4604 outputFiles += fTerminateFiles;
4606 TObjArray *arr = outputFiles.Tokenize(",");
4609 while (!merge && (os=(TObjString*)next1())) {
4610 // No need to validate outputs produced by merging since the merging macro does this
4611 outputFile = os->GetString();
4612 Int_t index = outputFile.Index("@");
4613 if (index > 0) outputFile.Remove(index);
4614 if (fTerminateFiles.Contains(outputFile)) continue;
4615 if (outputFile.Contains("*")) continue;
4616 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4617 out << " error=1" << endl;
4618 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4619 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4620 out << "fi" << endl;
4623 out << "if ! [ -f outputs_valid ] ; then" << endl;
4624 out << " error=1" << endl;
4625 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4626 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4627 out << "fi" << endl;
4629 out << "if [ $error = 0 ] ; then" << endl;
4630 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4631 if (!IsKeepLogs()) {
4632 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4634 out << " rm -f std*" << endl;
4636 out << "fi" << endl;
4638 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4639 out << "echo \"*******************************************************\"" << outStream << endl;
4640 out << "cd -" << endl;
4641 out << "exit $error" << endl;
4643 Bool_t copy = kTRUE;
4644 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4647 TString workdir = gGrid->GetHomeDirectory();
4648 workdir += fGridWorkingDir;
4649 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4650 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4651 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4652 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4653 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");