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);
2189 if (line.IsNull()) continue;
2190 if (count++ == fNtestFiles) break;
2191 TString esdFile(line);
2192 TFile *file = TFile::Open(esdFile);
2194 if (!file->IsZombie()) chain->Add(esdFile);
2197 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2201 if (!chain->GetListOfFiles()->GetEntries()) {
2202 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2210 //______________________________________________________________________________
2211 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2213 // Get job status for all jobs with jobid>jobidstart.
2214 static char mstatus[20];
2220 TGridJobStatusList *list = gGrid->Ps("");
2221 if (!list) return mstatus;
2222 Int_t nentries = list->GetSize();
2223 TGridJobStatus *status;
2225 for (Int_t ijob=0; ijob<nentries; ijob++) {
2226 status = (TGridJobStatus *)list->At(ijob);
2227 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2228 if (pid<jobidstart) continue;
2229 if (pid == lastid) {
2230 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2232 switch (status->GetStatus()) {
2233 case TGridJobStatus::kWAITING:
2235 case TGridJobStatus::kRUNNING:
2237 case TGridJobStatus::kABORTED:
2238 case TGridJobStatus::kFAIL:
2239 case TGridJobStatus::kUNKNOWN:
2241 case TGridJobStatus::kDONE:
2250 //______________________________________________________________________________
2251 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2253 // Returns true if file is a collection. Functionality duplicated from
2254 // TAlien::Type() because we don't want to directly depend on TAlien.
2256 Error("IsCollection", "No connection to grid");
2259 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2260 if (!res) return kFALSE;
2261 const char* typeStr = res->GetKey(0, "type");
2262 if (!typeStr || !strlen(typeStr)) return kFALSE;
2263 if (!strcmp(typeStr, "collection")) return kTRUE;
2268 //______________________________________________________________________________
2269 Bool_t AliAnalysisAlien::IsSingleOutput() const
2271 // Check if single-ouput option is on.
2272 return (!fOutputSingle.IsNull());
2275 //______________________________________________________________________________
2276 void AliAnalysisAlien::Print(Option_t *) const
2278 // Print current plugin settings.
2279 printf("### AliEn analysis plugin current settings ###\n");
2280 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2281 if (mgr && mgr->IsProofMode()) {
2282 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2283 if (TestBit(AliAnalysisGrid::kTest))
2284 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2285 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2286 if (!fProofDataSet.IsNull())
2287 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
2289 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2291 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
2292 if (!fRootVersionForProof.IsNull())
2293 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2295 printf("= ROOT version requested________________________ default\n");
2296 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2297 if (!fAliRootMode.IsNull())
2298 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
2300 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2301 if (fNproofWorkersPerSlave)
2302 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2303 if (TestSpecialBit(kClearPackages))
2304 printf("= ClearPackages requested...\n");
2305 if (fIncludePath.Data())
2306 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2307 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2308 if (fPackages && fPackages->GetEntries()) {
2309 TIter next(fPackages);
2312 while ((obj=next())) list += obj->GetName();
2313 printf("= Par files to be used: ________________________ %s\n", list.Data());
2315 if (TestSpecialBit(kProofConnectGrid))
2316 printf("= Requested PROOF connection to grid\n");
2319 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
2320 if (fOverwriteMode) {
2321 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2322 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2324 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2325 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2326 printf("= Production mode:______________________________ %d\n", fProductionMode);
2327 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2328 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2329 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2331 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
2332 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2333 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2334 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2335 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
2336 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
2337 if (fRunNumbers.Length())
2338 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2340 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2341 if (!fRunRange[0] && !fRunNumbers.Length()) {
2342 TIter next(fInputFiles);
2345 while ((obj=next())) list += obj->GetName();
2346 printf("= Input files to be processed: _________________ %s\n", list.Data());
2348 if (TestBit(AliAnalysisGrid::kTest))
2349 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
2350 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2351 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2352 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2353 printf("= List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2354 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2355 printf("=====================================================================\n");
2356 printf("= Job price: ___________________________________ %d\n", fPrice);
2357 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2358 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2359 if (fMaxInitFailed>0)
2360 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2361 if (fMasterResubmitThreshold>0)
2362 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2363 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2364 if (fNrunsPerMaster>0)
2365 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2366 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2367 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2368 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2369 if (fArguments.Length())
2370 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2371 if (fExecutableArgs.Length())
2372 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2373 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2374 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2375 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2376 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2378 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2379 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2380 if (fIncludePath.Data())
2381 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2382 if (fCloseSE.Length())
2383 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2384 if (fFriendChainName.Length())
2385 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2386 if (fPackages && fPackages->GetEntries()) {
2387 TIter next(fPackages);
2390 while ((obj=next())) list += obj->GetName();
2391 printf("= Par files to be used: ________________________ %s\n", list.Data());
2395 //______________________________________________________________________________
2396 void AliAnalysisAlien::SetDefaults()
2398 // Set default values for everything. What cannot be filled will be left empty.
2399 if (fGridJDL) delete fGridJDL;
2400 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2401 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2404 fSplitMaxInputFileNumber = 100;
2406 fMasterResubmitThreshold = 0;
2412 fNrunsPerMaster = 1;
2413 fMaxMergeFiles = 100;
2415 fExecutable = "analysis.sh";
2416 fExecutableCommand = "root -b -q";
2418 fExecutableArgs = "";
2419 fAnalysisMacro = "myAnalysis.C";
2420 fAnalysisSource = "";
2421 fAdditionalLibs = "";
2425 fAliROOTVersion = "";
2426 fUser = ""; // Your alien user name
2427 fGridWorkingDir = "";
2428 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2429 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2430 fFriendChainName = "";
2431 fGridOutputDir = "output";
2432 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2433 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2434 fInputFormat = "xml-single";
2435 fJDLName = "analysis.jdl";
2436 fJobTag = "Automatically generated analysis JDL";
2437 fMergeExcludes = "";
2440 SetCheckCopy(kTRUE);
2441 SetDefaultOutputs(kTRUE);
2445 //______________________________________________________________________________
2446 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2448 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2449 // First check if the result is already in the output directory.
2450 if (FileExists(Form("%s/%s",aliendir,filename))) {
2451 printf("Final merged results found. Not merging again.\n");
2454 // Now check the last stage done.
2457 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2460 // Next stage of merging
2462 TString pattern = "*root_archive.zip";
2463 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2464 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2465 if (res) delete res;
2466 // Write standard output to file
2467 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2468 // Count the number of files inside
2470 ifile.open(Form("Stage_%d.xml",stage));
2471 if (!ifile.good()) {
2472 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2477 while (!ifile.eof()) {
2479 if (line.Contains("/event")) nfiles++;
2483 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2486 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2488 // Copy the file in the output directory
2489 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2490 // TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2491 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2492 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2493 // Check if this is the last stage to be done.
2494 Bool_t laststage = (nfiles<nperchunk);
2495 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2497 printf("### Submiting final merging stage %d\n", stage);
2498 TString finalJDL = jdl;
2499 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2500 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2501 Int_t jobId = SubmitSingleJob(query);
2502 if (!jobId) return kFALSE;
2504 printf("### Submiting merging stage %d\n", stage);
2505 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2506 Int_t jobId = SubmitSingleJob(query);
2507 if (!jobId) return kFALSE;
2512 //______________________________________________________________________________
2513 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2515 // Loat the analysis manager from a file.
2516 TFile *file = TFile::Open(fname);
2518 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2521 TIter nextkey(file->GetListOfKeys());
2522 AliAnalysisManager *mgr = 0;
2524 while ((key=(TKey*)nextkey())) {
2525 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2526 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2529 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2533 //______________________________________________________________________________
2534 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2536 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2537 if (!gGrid) return 0;
2538 printf("=> %s ------> ",query);
2539 TGridResult *res = gGrid->Command(query);
2541 TString jobId = res->GetKey(0,"jobId");
2543 if (jobId.IsNull()) {
2544 printf("submission failed. Reason:\n");
2547 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2550 printf(" Job id: %s\n", jobId.Data());
2554 //______________________________________________________________________________
2555 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2557 // Merge given output files from basedir. Basedir can be an alien output directory
2558 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2559 // files in a group (ignored for xml input). Merging can be done in stages:
2560 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2561 // stage=1 : works with an xml of all root_archive.zip in the output directory
2562 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2563 TString outputFile = output;
2565 TString outputChunk;
2566 TString previousChunk = "";
2567 TObjArray *listoffiles = new TObjArray();
2568 // listoffiles->SetOwner();
2569 Int_t countChunk = 0;
2570 Int_t countZero = nmaxmerge;
2571 Bool_t merged = kTRUE;
2572 Int_t index = outputFile.Index("@");
2573 if (index > 0) outputFile.Remove(index);
2574 TString inputFile = outputFile;
2575 TString sbasedir = basedir;
2576 if (sbasedir.Contains(".xml")) {
2577 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2578 nmaxmerge = 9999999;
2579 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2581 ::Error("MergeOutput", "Input XML collection empty.");
2584 // Iterate grid collection
2585 while (coll->Next()) {
2586 TString fname = gSystem->DirName(coll->GetTURL());
2589 listoffiles->Add(new TNamed(fname.Data(),""));
2592 command = Form("find %s/ *%s", basedir, inputFile.Data());
2593 printf("command: %s\n", command.Data());
2594 TGridResult *res = gGrid->Command(command);
2596 ::Error("MergeOutput","No result for the find command\n");
2602 while ((map=(TMap*)nextmap())) {
2603 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2604 if (!objs || !objs->GetString().Length()) {
2605 // Nothing found - skip this output
2610 listoffiles->Add(new TNamed(objs->GetName(),""));
2614 if (!listoffiles->GetEntries()) {
2615 ::Error("MergeOutput","No result for the find command\n");
2620 TFileMerger *fm = 0;
2621 TIter next0(listoffiles);
2622 TObjArray *listoffilestmp = new TObjArray();
2623 listoffilestmp->SetOwner();
2626 // Keep only the files at upper level
2627 Int_t countChar = 0;
2628 while ((nextfile=next0())) {
2629 snextfile = nextfile->GetName();
2630 Int_t crtCount = snextfile.CountChar('/');
2631 if (nextfile == listoffiles->First()) countChar = crtCount;
2632 if (crtCount < countChar) countChar = crtCount;
2635 while ((nextfile=next0())) {
2636 snextfile = nextfile->GetName();
2637 Int_t crtCount = snextfile.CountChar('/');
2638 if (crtCount > countChar) {
2642 listoffilestmp->Add(nextfile);
2645 listoffiles = listoffilestmp; // Now contains 'good' files
2646 listoffiles->Print();
2647 TIter next(listoffiles);
2648 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2649 outputChunk = outputFile;
2650 outputChunk.ReplaceAll(".root", "_*.root");
2651 // Check for existent temporary merge files
2652 // Check overwrite mode and remove previous partial results if needed
2653 // Preserve old merging functionality for stage 0.
2655 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2657 // Skip as many input files as in a chunk
2658 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2661 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2665 snextfile = nextfile->GetName();
2667 outputChunk = outputFile;
2668 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2670 if (gSystem->AccessPathName(outputChunk)) continue;
2671 // Merged file with chunks up to <countChunk> found
2672 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2673 previousChunk = outputChunk;
2677 countZero = nmaxmerge;
2679 while ((nextfile=next())) {
2680 snextfile = nextfile->GetName();
2681 // Loop 'find' results and get next LFN
2682 if (countZero == nmaxmerge) {
2683 // First file in chunk - create file merger and add previous chunk if any.
2684 fm = new TFileMerger(kTRUE);
2685 fm->SetFastMethod(kTRUE);
2686 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2687 outputChunk = outputFile;
2688 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2690 // If last file found, put merged results in the output file
2691 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2692 // Add file to be merged and decrement chunk counter.
2693 fm->AddFile(snextfile);
2695 if (countZero==0 || nextfile == listoffiles->Last()) {
2696 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2697 // Nothing found - skip this output
2698 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2702 fm->OutputFile(outputChunk);
2703 // Merge the outputs, then go to next chunk
2705 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2709 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2710 gSystem->Unlink(previousChunk);
2712 if (nextfile == listoffiles->Last()) break;
2714 countZero = nmaxmerge;
2715 previousChunk = outputChunk;
2722 // Merging stage different than 0.
2723 // Move to the begining of the requested chunk.
2724 fm = new TFileMerger(kTRUE);
2725 fm->SetFastMethod(kTRUE);
2726 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2728 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2729 // Nothing found - skip this output
2730 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2734 fm->OutputFile(outputFile);
2735 // Merge the outputs
2737 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2741 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2747 //______________________________________________________________________________
2748 Bool_t AliAnalysisAlien::MergeOutputs()
2750 // Merge analysis outputs existing in the AliEn space.
2751 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2752 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2754 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2758 if (!TestBit(AliAnalysisGrid::kMerge)) {
2759 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2762 if (fProductionMode) {
2763 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2766 Info("MergeOutputs", "Submitting merging JDL");
2767 if (!SubmitMerging()) return kFALSE;
2768 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2769 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2772 // Get the output path
2773 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2774 if (!DirectoryExists(fGridOutputDir)) {
2775 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2778 if (!fOutputFiles.Length()) {
2779 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2782 // Check if fast read option was requested
2783 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2784 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2785 if (fFastReadOption) {
2786 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2787 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2788 gEnv->SetValue("XNet.ConnectTimeout",50);
2789 gEnv->SetValue("XNet.RequestTimeout",50);
2790 gEnv->SetValue("XNet.MaxRedirectCount",2);
2791 gEnv->SetValue("XNet.ReconnectTimeout",50);
2792 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2794 // Make sure we change the temporary directory
2795 gSystem->Setenv("TMPDIR", gSystem->pwd());
2796 // Set temporary compilation directory to current one
2797 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2798 TObjArray *list = fOutputFiles.Tokenize(",");
2802 Bool_t merged = kTRUE;
2803 while((str=(TObjString*)next())) {
2804 outputFile = str->GetString();
2805 Int_t index = outputFile.Index("@");
2806 if (index > 0) outputFile.Remove(index);
2807 TString outputChunk = outputFile;
2808 outputChunk.ReplaceAll(".root", "_*.root");
2809 // Skip already merged outputs
2810 if (!gSystem->AccessPathName(outputFile)) {
2811 if (fOverwriteMode) {
2812 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2813 gSystem->Unlink(outputFile);
2814 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2815 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2816 outputChunk.Data());
2817 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2820 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2824 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2825 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2826 outputChunk.Data());
2827 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2830 if (fMergeExcludes.Contains(outputFile.Data()) ||
2831 fRegisterExcludes.Contains(outputFile.Data())) continue;
2832 // Perform a 'find' command in the output directory, looking for registered outputs
2833 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2835 Error("MergeOutputs", "Terminate() will NOT be executed");
2838 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2839 if (fileOpened) fileOpened->Close();
2844 //______________________________________________________________________________
2845 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2847 // Use the output files connected to output containers from the analysis manager
2848 // rather than the files defined by SetOutputFiles
2849 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2850 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2851 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2854 //______________________________________________________________________________
2855 void AliAnalysisAlien::SetOutputFiles(const char *list)
2857 // Manually set the output files list.
2858 // Removes duplicates. Not allowed if default outputs are not disabled.
2859 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2860 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2863 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2865 TString slist = list;
2866 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2867 TObjArray *arr = slist.Tokenize(" ");
2871 while ((os=(TObjString*)next())) {
2872 sout = os->GetString();
2873 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2874 if (fOutputFiles.Contains(sout)) continue;
2875 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2876 fOutputFiles += sout;
2881 //______________________________________________________________________________
2882 void AliAnalysisAlien::SetOutputArchive(const char *list)
2884 // Manually set the output archive list. Free text - you are on your own...
2885 // Not allowed if default outputs are not disabled.
2886 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2887 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2890 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2891 fOutputArchive = list;
2894 //______________________________________________________________________________
2895 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2897 // Setting a prefered output SE is not allowed anymore.
2898 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2901 //______________________________________________________________________________
2902 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2904 // Set some PROOF special parameter.
2905 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2907 TObject *old = pair->Key();
2908 TObject *val = pair->Value();
2909 fProofParam.Remove(old);
2913 fProofParam.Add(new TObjString(pname), new TObjString(value));
2916 //______________________________________________________________________________
2917 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2919 // Returns a special PROOF parameter.
2920 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2921 if (!pair) return 0;
2922 return pair->Value()->GetName();
2925 //______________________________________________________________________________
2926 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2928 // Start remote grid analysis.
2929 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2930 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2931 if (!mgr || !mgr->IsInitialized()) {
2932 Error("StartAnalysis", "You need an initialized analysis manager for this");
2935 // Are we in PROOF mode ?
2936 if (mgr->IsProofMode()) {
2937 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2938 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2939 if (fProofCluster.IsNull()) {
2940 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2943 if (fProofDataSet.IsNull() && !testMode) {
2944 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2947 // Set the needed environment
2948 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2949 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2950 if (fProofReset && !testMode) {
2951 if (fProofReset==1) {
2952 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2953 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2955 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2956 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2958 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2963 // Check if there is an old active session
2964 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2966 Error("StartAnalysis","You have to reset your old session first\n");
2970 // Do we need to change the ROOT version ? The success of this cannot be checked.
2971 if (!fRootVersionForProof.IsNull() && !testMode) {
2972 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2973 fProofCluster.Data(), fRootVersionForProof.Data()));
2975 // Connect to PROOF and check the status
2978 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2979 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2981 if (!sworkers.IsNull())
2982 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2984 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2986 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2988 Error("StartAnalysis", "Could not start PROOF in test mode");
2993 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2996 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2997 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2998 // Set proof special parameters if any
2999 TIter nextpp(&fProofParam);
3000 TObject *proofparam;
3001 while ((proofparam=nextpp())) {
3002 TString svalue = GetProofParameter(proofparam->GetName());
3003 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3005 // Is dataset existing ?
3007 TString dataset = fProofDataSet;
3008 Int_t index = dataset.Index("#");
3009 if (index>=0) dataset.Remove(index);
3010 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3011 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3014 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
3016 // Is ClearPackages() needed ?
3017 if (TestSpecialBit(kClearPackages)) {
3018 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3019 gROOT->ProcessLine("gProof->ClearPackages();");
3021 // Is a given aliroot mode requested ?
3024 if (!fAliRootMode.IsNull()) {
3025 TString alirootMode = fAliRootMode;
3026 if (alirootMode == "default") alirootMode = "";
3027 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3028 optionsList.SetOwner();
3029 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3030 // Check the additional libs to be loaded
3032 Bool_t parMode = kFALSE;
3033 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3034 // Parse the extra libs for .so
3035 if (fAdditionalLibs.Length()) {
3036 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3039 while((str=(TObjString*)next())) {
3040 if (str->GetString().Contains(".so")) {
3042 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());
3045 TString stmp = str->GetName();
3046 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3047 stmp.ReplaceAll(".so","");
3048 if (!extraLibs.IsNull()) extraLibs += ":";
3052 if (str->GetString().Contains(".par")) {
3053 // The first par file found in the list will not allow any further .so
3055 if (!parLibs.IsNull()) parLibs += ":";
3056 parLibs += str->GetName();
3060 if (list) delete list;
3062 if (!extraLibs.IsNull()) {
3063 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3064 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3066 // Check extra includes
3067 if (!fIncludePath.IsNull()) {
3068 TString includePath = fIncludePath;
3069 includePath.ReplaceAll(" ",":");
3070 includePath.ReplaceAll("$ALICE_ROOT/","");
3071 includePath.ReplaceAll("${ALICE_ROOT}/","");
3072 includePath.ReplaceAll("-I","");
3073 includePath.Remove(TString::kTrailing, ':');
3074 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
3075 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3077 // Check if connection to grid is requested
3078 if (TestSpecialBit(kProofConnectGrid))
3079 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3080 // Enable AliRoot par
3082 // Enable proof lite package
3083 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3084 for (Int_t i=0; i<optionsList.GetSize(); i++) {
3085 TNamed *obj = (TNamed*)optionsList.At(i);
3086 printf("%s %s\n", obj->GetName(), obj->GetTitle());
3088 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3089 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3090 Info("StartAnalysis", "AliRootProofLite enabled");
3092 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3096 if ( ! fAliROOTVersion.IsNull() ) {
3097 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
3098 fAliROOTVersion.Data(), &optionsList))) {
3099 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3104 // Enable first par files from fAdditionalLibs
3105 if (!parLibs.IsNull()) {
3106 TObjArray *list = parLibs.Tokenize(":");
3108 TObjString *package;
3109 while((package=(TObjString*)next())) {
3110 TString spkg = package->GetName();
3111 spkg.ReplaceAll(".par", "");
3112 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3113 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3114 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3115 if (gROOT->ProcessLine(enablePackage)) {
3116 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3120 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3124 if (list) delete list;
3127 if (fAdditionalLibs.Contains(".so") && !testMode) {
3128 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3129 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3133 // Enable par files if requested
3134 if (fPackages && fPackages->GetEntries()) {
3135 TIter next(fPackages);
3137 while ((package=next())) {
3138 // Skip packages already enabled
3139 if (parLibs.Contains(package->GetName())) continue;
3140 TString spkg = package->GetName();
3141 spkg.ReplaceAll(".par", "");
3142 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3143 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3144 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3145 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3149 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3154 // Do we need to load analysis source files ?
3155 // NOTE: don't load on client since this is anyway done by the user to attach his task.
3156 if (fAnalysisSource.Length()) {
3157 TObjArray *list = fAnalysisSource.Tokenize(" ");
3160 while((str=(TObjString*)next())) {
3161 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3163 if (list) delete list;
3166 // Register dataset to proof lite.
3167 if (fFileForTestMode.IsNull()) {
3168 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3171 if (gSystem->AccessPathName(fFileForTestMode)) {
3172 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3175 TFileCollection *coll = new TFileCollection();
3176 coll->AddFromFile(fFileForTestMode);
3177 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3178 gROOT->ProcessLine("gProof->ShowDataSets()");
3183 // Check if output files have to be taken from the analysis manager
3184 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3185 // Add output files and AOD files
3186 fOutputFiles = GetListOfFiles("outaod");
3187 // Add extra files registered to the analysis manager
3188 TString extra = GetListOfFiles("ext");
3189 if (!extra.IsNull()) {
3190 extra.ReplaceAll(".root", "*.root");
3191 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3192 fOutputFiles += extra;
3194 // Compose the output archive.
3195 fOutputArchive = "log_archive.zip:std*@disk=1 ";
3196 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3198 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3199 if (TestBit(AliAnalysisGrid::kOffline)) {
3200 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3201 \n there nor any job run. You can revise the JDL and analysis \
3202 \n macro then run the same in \"submit\" mode.");
3203 } else if (TestBit(AliAnalysisGrid::kTest)) {
3204 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
3206 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3207 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
3208 \n space and job submitted.");
3209 } else if (TestBit(AliAnalysisGrid::kMerge)) {
3210 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
3211 if (fMergeViaJDL) CheckInputData();
3214 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
3219 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3222 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3223 if (!CheckInputData()) {
3224 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3227 if (!CreateDataset(fDataPattern)) {
3229 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3230 if (fRunNumbers.Length()) serror = "run numbers";
3231 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3232 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
3233 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3236 WriteAnalysisFile();
3237 WriteAnalysisMacro();
3239 WriteValidationScript();
3241 WriteMergingMacro();
3242 WriteMergeExecutable();
3243 WriteValidationScript(kTRUE);
3245 if (!CreateJDL()) return kFALSE;
3246 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3248 // Locally testing the analysis
3249 Info("StartAnalysis", "\n_______________________________________________________________________ \
3250 \n Running analysis script in a daughter shell as on a worker node \
3251 \n_______________________________________________________________________");
3252 TObjArray *list = fOutputFiles.Tokenize(",");
3256 while((str=(TObjString*)next())) {
3257 outputFile = str->GetString();
3258 Int_t index = outputFile.Index("@");
3259 if (index > 0) outputFile.Remove(index);
3260 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3263 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3264 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3265 // gSystem->Exec("cat stdout");
3268 // Check if submitting is managed by LPM manager
3269 if (fProductionMode) {
3270 TString prodfile = fJDLName;
3271 prodfile.ReplaceAll(".jdl", ".prod");
3272 WriteProductionFile(prodfile);
3273 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3276 // Submit AliEn job(s)
3277 gGrid->Cd(fGridOutputDir);
3280 if (!fRunNumbers.Length() && !fRunRange[0]) {
3281 // Submit a given xml or a set of runs
3282 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3283 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3285 const char *cjobId = res->GetKey(0,"jobId");
3289 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3292 Info("StartAnalysis", "\n_______________________________________________________________________ \
3293 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3294 \n_______________________________________________________________________",
3295 fJDLName.Data(), cjobId);
3300 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3304 // Submit for a range of enumeration of runs.
3305 if (!Submit()) return kFALSE;
3308 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3309 \n You may exit at any time and terminate the job later using the option <terminate> \
3310 \n ##################################################################################", jobID.Data());
3311 gSystem->Exec("aliensh");
3315 //______________________________________________________________________________
3316 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3318 // Get a comma-separated list of output files of the requested type.
3319 // Type can be (case unsensitive):
3320 // aod - list of aod files (std, extensions and filters)
3321 // out - list of output files connected to containers (but not aod's or extras)
3322 // ext - list of extra files registered to the manager
3323 // ter - list of files produced in terminate
3324 static TString files;
3326 TString stype = type;
3328 TString aodfiles, extra;
3329 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3331 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3332 return files.Data();
3334 if (mgr->GetOutputEventHandler()) {
3335 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3336 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3337 if (!extraaod.IsNull()) {
3339 aodfiles += extraaod;
3342 if (stype.Contains("aod")) {
3344 if (stype == "aod") return files.Data();
3346 // Add output files that are not in the list of AOD files
3347 TString outputfiles = "";
3348 TIter next(mgr->GetOutputs());
3349 AliAnalysisDataContainer *output;
3350 const char *filename = 0;
3351 while ((output=(AliAnalysisDataContainer*)next())) {
3352 filename = output->GetFileName();
3353 if (!(strcmp(filename, "default"))) continue;
3354 if (outputfiles.Contains(filename)) continue;
3355 if (aodfiles.Contains(filename)) continue;
3356 if (!outputfiles.IsNull()) outputfiles += ",";
3357 outputfiles += filename;
3359 if (stype.Contains("out")) {
3360 if (!files.IsNull()) files += ",";
3361 files += outputfiles;
3362 if (stype == "out") return files.Data();
3364 // Add extra files registered to the analysis manager
3366 extra = mgr->GetExtraFiles();
3367 if (!extra.IsNull()) {
3369 extra.ReplaceAll(" ", ",");
3370 TObjArray *fextra = extra.Tokenize(",");
3371 TIter nextx(fextra);
3373 while ((obj=nextx())) {
3374 if (aodfiles.Contains(obj->GetName())) continue;
3375 if (outputfiles.Contains(obj->GetName())) continue;
3376 if (sextra.Contains(obj->GetName())) continue;
3377 if (!sextra.IsNull()) sextra += ",";
3378 sextra += obj->GetName();
3381 if (stype.Contains("ext")) {
3382 if (!files.IsNull()) files += ",";
3386 if (stype == "ext") return files.Data();
3388 if (!fTerminateFiles.IsNull()) {
3389 fTerminateFiles.Strip();
3390 fTerminateFiles.ReplaceAll(" ",",");
3391 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3392 TIter nextx(fextra);
3394 while ((obj=nextx())) {
3395 if (aodfiles.Contains(obj->GetName())) continue;
3396 if (outputfiles.Contains(obj->GetName())) continue;
3397 if (termfiles.Contains(obj->GetName())) continue;
3398 if (sextra.Contains(obj->GetName())) continue;
3399 if (!termfiles.IsNull()) termfiles += ",";
3400 termfiles += obj->GetName();
3404 if (stype.Contains("ter")) {
3405 if (!files.IsNull() && !termfiles.IsNull()) {
3410 return files.Data();
3413 //______________________________________________________________________________
3414 Bool_t AliAnalysisAlien::Submit()
3416 // Submit all master jobs.
3417 Int_t nmasterjobs = fInputFiles->GetEntries();
3418 Long_t tshoot = gSystem->Now();
3419 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3420 while (fNsubmitted < nmasterjobs) {
3421 Long_t now = gSystem->Now();
3422 if ((now-tshoot)>30000) {
3424 if (!SubmitNext()) return kFALSE;
3430 //______________________________________________________________________________
3431 Bool_t AliAnalysisAlien::SubmitMerging()
3433 // Submit all merging jobs.
3434 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3435 gGrid->Cd(fGridOutputDir);
3436 TString mergeJDLName = fExecutable;
3437 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3439 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3442 Int_t ntosubmit = fInputFiles->GetEntries();
3443 for (Int_t i=0; i<ntosubmit; i++) {
3444 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3445 runOutDir.ReplaceAll(".xml", "");
3446 if (fOutputToRunNo) {
3447 // The output directory is the run number
3448 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3449 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3451 if (!fRunNumbers.Length() && !fRunRange[0]) {
3452 // The output directory is the grid outdir
3453 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3454 runOutDir = fGridOutputDir;
3456 // The output directory is the master number in 3 digits format
3457 printf("### Submitting merging job for master <%03d>\n", i);
3458 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3461 // Check now the number of merging stages.
3462 TObjArray *list = fOutputFiles.Tokenize(",");
3466 while((str=(TObjString*)next())) {
3467 outputFile = str->GetString();
3468 Int_t index = outputFile.Index("@");
3469 if (index > 0) outputFile.Remove(index);
3470 if (!fMergeExcludes.Contains(outputFile) &&
3471 !fRegisterExcludes.Contains(outputFile)) break;
3474 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3475 if (!done && (i==ntosubmit-1)) return kFALSE;
3476 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3478 if (!ntosubmit) return kTRUE;
3479 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3480 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3481 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3482 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3483 \n ################################################################################################################");
3484 gSystem->Exec("aliensh");
3488 //______________________________________________________________________________
3489 Bool_t AliAnalysisAlien::SubmitNext()
3491 // Submit next bunch of master jobs if the queue is free. The first master job is
3492 // submitted right away, while the next will not be unless the previous was split.
3493 // The plugin will not submit new master jobs if there are more that 500 jobs in
3495 static Bool_t iscalled = kFALSE;
3496 static Int_t firstmaster = 0;
3497 static Int_t lastmaster = 0;
3498 static Int_t npermaster = 0;
3499 if (iscalled) return kTRUE;
3501 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3502 Int_t ntosubmit = 0;
3505 Int_t nmasterjobs = fInputFiles->GetEntries();
3508 if (!IsUseSubmitPolicy()) {
3510 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3511 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3512 ntosubmit = nmasterjobs;
3515 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3516 printf("=== master %d: %s\n", lastmaster, status.Data());
3517 // If last master not split, just return
3518 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3519 // No more than 100 waiting jobs
3520 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3521 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3522 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3523 if (!ntosubmit) ntosubmit = 1;
3524 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3525 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3527 for (Int_t i=0; i<ntosubmit; i++) {
3528 // Submit for a range of enumeration of runs.
3529 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3531 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3532 runOutDir.ReplaceAll(".xml", "");
3534 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3536 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3537 printf("********* %s\n",query.Data());
3538 res = gGrid->Command(query);
3540 TString cjobId1 = res->GetKey(0,"jobId");
3541 if (!cjobId1.Length()) {
3545 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3548 Info("StartAnalysis", "\n_______________________________________________________________________ \
3549 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3550 \n_______________________________________________________________________",
3551 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3554 lastmaster = cjobId1.Atoi();
3555 if (!firstmaster) firstmaster = lastmaster;
3560 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3568 //______________________________________________________________________________
3569 void AliAnalysisAlien::WriteAnalysisFile()
3571 // Write current analysis manager into the file <analysisFile>
3572 TString analysisFile = fExecutable;
3573 analysisFile.ReplaceAll(".sh", ".root");
3574 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3575 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3576 if (!mgr || !mgr->IsInitialized()) {
3577 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3580 // Check analysis type
3582 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3583 handler = (TObject*)mgr->GetInputEventHandler();
3585 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3586 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3587 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3588 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3590 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3591 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3594 TDirectory *cdir = gDirectory;
3595 TFile *file = TFile::Open(analysisFile, "RECREATE");
3597 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3598 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3599 // Unless merging makes no sense
3600 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3603 // Enable termination for local jobs
3604 mgr->SetSkipTerminate(kFALSE);
3606 if (cdir) cdir->cd();
3607 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3609 Bool_t copy = kTRUE;
3610 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3613 TString workdir = gGrid->GetHomeDirectory();
3614 workdir += fGridWorkingDir;
3615 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3616 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3617 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3618 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3622 //______________________________________________________________________________
3623 void AliAnalysisAlien::WriteAnalysisMacro()
3625 // Write the analysis macro that will steer the analysis in grid mode.
3626 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3628 out.open(fAnalysisMacro.Data(), ios::out);
3630 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3633 Bool_t hasSTEERBase = kFALSE;
3634 Bool_t hasESD = kFALSE;
3635 Bool_t hasAOD = kFALSE;
3636 Bool_t hasANALYSIS = kFALSE;
3637 Bool_t hasOADB = kFALSE;
3638 Bool_t hasANALYSISalice = kFALSE;
3639 Bool_t hasCORRFW = kFALSE;
3640 TString func = fAnalysisMacro;
3641 TString type = "ESD";
3642 TString comment = "// Analysis using ";
3643 if (IsUseMCchain()) {
3647 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3648 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3653 if (type!="AOD" && fFriendChainName!="") {
3654 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3657 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3658 else comment += " data";
3659 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3660 func.ReplaceAll(".C", "");
3661 out << "void " << func.Data() << "()" << endl;
3663 out << comment.Data() << endl;
3664 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3665 out << " TStopwatch timer;" << endl;
3666 out << " timer.Start();" << endl << endl;
3667 // Change temp directory to current one
3668 out << "// Set temporary merging directory to current one" << endl;
3669 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3670 out << "// Set temporary compilation directory to current one" << endl;
3671 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3672 // Reset existing include path
3673 out << "// Reset existing include path and add current directory first in the search" << endl;
3674 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3675 if (!fExecutableCommand.Contains("aliroot")) {
3676 out << "// load base root libraries" << endl;
3677 out << " gSystem->Load(\"libTree\");" << endl;
3678 out << " gSystem->Load(\"libGeom\");" << endl;
3679 out << " gSystem->Load(\"libVMC\");" << endl;
3680 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3681 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3683 if (fAdditionalRootLibs.Length()) {
3684 // in principle libtree /lib geom libvmc etc. can go into this list, too
3685 out << "// Add aditional libraries" << endl;
3686 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3689 while((str=(TObjString*)next())) {
3690 if (str->GetString().Contains(".so"))
3691 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3693 if (list) delete list;
3695 out << "// Load analysis framework libraries" << endl;
3696 TString setupPar = "AliAnalysisAlien::SetupPar";
3698 if (!fExecutableCommand.Contains("aliroot")) {
3699 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3700 out << " gSystem->Load(\"libESD\");" << endl;
3701 out << " gSystem->Load(\"libAOD\");" << endl;
3703 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3704 out << " gSystem->Load(\"libOADB\");" << endl;
3705 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3706 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3708 TIter next(fPackages);
3711 while ((obj=next())) {
3712 pkgname = obj->GetName();
3713 if (pkgname == "STEERBase" ||
3714 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3715 if (pkgname == "ESD" ||
3716 pkgname == "ESD.par") hasESD = kTRUE;
3717 if (pkgname == "AOD" ||
3718 pkgname == "AOD.par") hasAOD = kTRUE;
3719 if (pkgname == "ANALYSIS" ||
3720 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3721 if (pkgname == "OADB" ||
3722 pkgname == "OADB.par") hasOADB = kTRUE;
3723 if (pkgname == "ANALYSISalice" ||
3724 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3725 if (pkgname == "CORRFW" ||
3726 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3728 if (hasANALYSISalice) setupPar = "SetupPar";
3729 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3730 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3731 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3732 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3733 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3734 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3735 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3736 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3737 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3738 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3739 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3740 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3741 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3742 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3743 out << "// Compile other par packages" << endl;
3745 while ((obj=next())) {
3746 pkgname = obj->GetName();
3747 if (pkgname == "STEERBase" ||
3748 pkgname == "STEERBase.par" ||
3750 pkgname == "ESD.par" ||
3752 pkgname == "AOD.par" ||
3753 pkgname == "ANALYSIS" ||
3754 pkgname == "ANALYSIS.par" ||
3755 pkgname == "OADB" ||
3756 pkgname == "OADB.par" ||
3757 pkgname == "ANALYSISalice" ||
3758 pkgname == "ANALYSISalice.par" ||
3759 pkgname == "CORRFW" ||
3760 pkgname == "CORRFW.par") continue;
3761 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3764 out << "// include path" << endl;
3765 // Get the include path from the interpreter and remove entries pointing to AliRoot
3766 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3767 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3768 out << " TIter nextpath(listpaths);" << endl;
3769 out << " TObjString *pname;" << endl;
3770 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3771 out << " TString current = pname->GetName();" << endl;
3772 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3773 out << " gSystem->AddIncludePath(current);" << endl;
3774 out << " }" << endl;
3775 out << " if (listpaths) delete listpaths;" << endl;
3776 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3777 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3778 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3779 if (fAdditionalLibs.Length()) {
3780 out << "// Add aditional AliRoot libraries" << endl;
3781 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3784 while((str=(TObjString*)next())) {
3785 if (str->GetString().Contains(".so"))
3786 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3787 if (str->GetString().Contains(".par"))
3788 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3790 if (list) delete list;
3793 out << "// analysis source to be compiled at runtime (if any)" << endl;
3794 if (fAnalysisSource.Length()) {
3795 TObjArray *list = fAnalysisSource.Tokenize(" ");
3798 while((str=(TObjString*)next())) {
3799 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3801 if (list) delete list;
3804 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3805 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3806 if (fFastReadOption) {
3807 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 !!! \
3808 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3809 out << "// fast xrootd reading enabled" << endl;
3810 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3811 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3812 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3813 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3814 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3815 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3817 if (!IsLocalTest()) {
3818 out << "// connect to AliEn and make the chain" << endl;
3819 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3821 out << "// read the analysis manager from file" << endl;
3822 TString analysisFile = fExecutable;
3823 analysisFile.ReplaceAll(".sh", ".root");
3824 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3825 << analysisFile << "\");" << endl;
3826 out << " if (!mgr) return;" << endl;
3827 if (IsLocalTest()) {
3828 out << " AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3829 out << " plugin->SetRunMode(\"test\");" << endl;
3830 if (fFileForTestMode.IsNull())
3831 out << " plugin->SetFileForTestMode(\"data.txt\");" << endl;
3833 out << " plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3834 out << " plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3835 out << " mgr->SetGridHandler(plugin);" << endl;
3836 if (AliAnalysisManager::GetAnalysisManager()) {
3837 out << " mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3838 out << " mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3840 out << " mgr->SetDebugLevel(10);" << endl;
3841 out << " mgr->SetNSysInfo(100);" << endl;
3844 out << " mgr->PrintStatus();" << endl;
3845 if (AliAnalysisManager::GetAnalysisManager()) {
3846 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3847 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3849 if (TestBit(AliAnalysisGrid::kTest))
3850 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3852 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3855 if (!IsLocalTest()) {
3856 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3857 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3859 out << " mgr->StartAnalysis(\"localfile\");" << endl;
3861 out << " timer.Stop();" << endl;
3862 out << " timer.Print();" << endl;
3863 out << "}" << endl << endl;
3864 if (!IsLocalTest()) {
3865 out <<"//________________________________________________________________________________" << endl;
3866 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3868 out << "// Create a chain using url's from xml file" << endl;
3869 out << " TString filename;" << endl;
3870 out << " Int_t run = 0;" << endl;
3871 if (IsUseMCchain()) {
3872 out << " TString treename = \"TE\";" << endl;
3874 out << " TString treename = type;" << endl;
3875 out << " treename.ToLower();" << endl;
3876 out << " treename += \"Tree\";" << endl;
3878 out << " printf(\"***************************************\\n\");" << endl;
3879 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3880 out << " printf(\"***************************************\\n\");" << endl;
3881 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3882 out << " if (!coll) {" << endl;
3883 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3884 out << " return NULL;" << endl;
3885 out << " }" << endl;
3886 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3887 out << " TChain *chain = new TChain(treename);" << endl;
3888 if(fFriendChainName!="") {
3889 out << " TChain *chainFriend = new TChain(treename);" << endl;
3891 out << " coll->Reset();" << endl;
3892 out << " while (coll->Next()) {" << endl;
3893 out << " filename = coll->GetTURL("");" << endl;
3894 out << " if (mgr) {" << endl;
3895 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3896 out << " if (nrun && nrun != run) {" << endl;
3897 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3898 out << " mgr->SetRunFromPath(nrun);" << endl;
3899 out << " run = nrun;" << endl;
3900 out << " }" << endl;
3901 out << " }" << endl;
3902 out << " chain->Add(filename);" << endl;
3903 if(fFriendChainName!="") {
3904 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3905 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3906 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3907 out << " chainFriend->Add(fileFriend.Data());" << endl;
3909 out << " }" << endl;
3910 out << " if (!chain->GetNtrees()) {" << endl;
3911 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3912 out << " return NULL;" << endl;
3913 out << " }" << endl;
3914 if(fFriendChainName!="") {
3915 out << " chain->AddFriend(chainFriend);" << endl;
3917 out << " return chain;" << endl;
3918 out << "}" << endl << endl;
3920 if (hasANALYSISalice) {
3921 out <<"//________________________________________________________________________________" << endl;
3922 out << "Bool_t SetupPar(const char *package) {" << endl;
3923 out << "// Compile the package and set it up." << endl;
3924 out << " TString pkgdir = package;" << endl;
3925 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3926 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3927 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3928 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3929 out << " // Check for BUILD.sh and execute" << endl;
3930 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3931 out << " printf(\"*******************************\\n\");" << endl;
3932 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3933 out << " printf(\"*******************************\\n\");" << endl;
3934 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3935 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3936 out << " gSystem->ChangeDirectory(cdir);" << endl;
3937 out << " return kFALSE;" << endl;
3938 out << " }" << endl;
3939 out << " } else {" << endl;
3940 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3941 out << " gSystem->ChangeDirectory(cdir);" << endl;
3942 out << " return kFALSE;" << endl;
3943 out << " }" << endl;
3944 out << " // Check for SETUP.C and execute" << endl;
3945 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3946 out << " printf(\"*******************************\\n\");" << endl;
3947 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3948 out << " printf(\"*******************************\\n\");" << endl;
3949 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3950 out << " } else {" << endl;
3951 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3952 out << " gSystem->ChangeDirectory(cdir);" << endl;
3953 out << " return kFALSE;" << endl;
3954 out << " }" << endl;
3955 out << " // Restore original workdir" << endl;
3956 out << " gSystem->ChangeDirectory(cdir);" << endl;
3957 out << " return kTRUE;" << endl;
3960 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3962 Bool_t copy = kTRUE;
3963 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3966 TString workdir = gGrid->GetHomeDirectory();
3967 workdir += fGridWorkingDir;
3968 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3969 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3970 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3971 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
3972 Form("alien://%s/%s", workdir.Data(),
3973 fAnalysisMacro.Data()))) Fatal("","Terminating");
3977 //______________________________________________________________________________
3978 void AliAnalysisAlien::WriteMergingMacro()
3980 // Write a macro to merge the outputs per master job.
3981 if (!fMergeViaJDL) return;
3982 if (!fOutputFiles.Length()) {
3983 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3986 TString mergingMacro = fExecutable;
3987 mergingMacro.ReplaceAll(".sh","_merge.C");
3988 if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3989 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3991 out.open(mergingMacro.Data(), ios::out);
3993 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3996 Bool_t hasSTEERBase = kFALSE;
3997 Bool_t hasESD = kFALSE;
3998 Bool_t hasAOD = kFALSE;
3999 Bool_t hasANALYSIS = kFALSE;
4000 Bool_t hasOADB = kFALSE;
4001 Bool_t hasANALYSISalice = kFALSE;
4002 Bool_t hasCORRFW = kFALSE;
4003 TString func = mergingMacro;
4005 func.ReplaceAll(".C", "");
4006 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4008 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4009 out << " TStopwatch timer;" << endl;
4010 out << " timer.Start();" << endl << endl;
4011 // Reset existing include path
4012 out << "// Reset existing include path and add current directory first in the search" << endl;
4013 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
4014 if (!fExecutableCommand.Contains("aliroot")) {
4015 out << "// load base root libraries" << endl;
4016 out << " gSystem->Load(\"libTree\");" << endl;
4017 out << " gSystem->Load(\"libGeom\");" << endl;
4018 out << " gSystem->Load(\"libVMC\");" << endl;
4019 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
4020 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
4022 if (fAdditionalRootLibs.Length()) {
4023 // in principle libtree /lib geom libvmc etc. can go into this list, too
4024 out << "// Add aditional libraries" << endl;
4025 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4028 while((str=(TObjString*)next())) {
4029 if (str->GetString().Contains(".so"))
4030 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4032 if (list) delete list;
4034 out << "// Load analysis framework libraries" << endl;
4036 if (!fExecutableCommand.Contains("aliroot")) {
4037 out << " gSystem->Load(\"libSTEERBase\");" << endl;
4038 out << " gSystem->Load(\"libESD\");" << endl;
4039 out << " gSystem->Load(\"libAOD\");" << endl;
4041 out << " gSystem->Load(\"libANALYSIS\");" << endl;
4042 out << " gSystem->Load(\"libOADB\");" << endl;
4043 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4044 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4046 TIter next(fPackages);
4049 TString setupPar = "AliAnalysisAlien::SetupPar";
4050 while ((obj=next())) {
4051 pkgname = obj->GetName();
4052 if (pkgname == "STEERBase" ||
4053 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4054 if (pkgname == "ESD" ||
4055 pkgname == "ESD.par") hasESD = kTRUE;
4056 if (pkgname == "AOD" ||
4057 pkgname == "AOD.par") hasAOD = kTRUE;
4058 if (pkgname == "ANALYSIS" ||
4059 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
4060 if (pkgname == "OADB" ||
4061 pkgname == "OADB.par") hasOADB = kTRUE;
4062 if (pkgname == "ANALYSISalice" ||
4063 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4064 if (pkgname == "CORRFW" ||
4065 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
4067 if (hasANALYSISalice) setupPar = "SetupPar";
4068 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
4069 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4070 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
4071 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
4072 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
4073 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
4074 out << " gSystem->Load(\"libOADB\");" << endl;
4075 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
4076 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4077 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
4078 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
4079 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
4080 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4081 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4082 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4083 out << "// Compile other par packages" << endl;
4085 while ((obj=next())) {
4086 pkgname = obj->GetName();
4087 if (pkgname == "STEERBase" ||
4088 pkgname == "STEERBase.par" ||
4090 pkgname == "ESD.par" ||
4092 pkgname == "AOD.par" ||
4093 pkgname == "ANALYSIS" ||
4094 pkgname == "ANALYSIS.par" ||
4095 pkgname == "OADB" ||
4096 pkgname == "OADB.par" ||
4097 pkgname == "ANALYSISalice" ||
4098 pkgname == "ANALYSISalice.par" ||
4099 pkgname == "CORRFW" ||
4100 pkgname == "CORRFW.par") continue;
4101 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4104 out << "// include path" << endl;
4105 // Get the include path from the interpreter and remove entries pointing to AliRoot
4106 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
4107 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4108 out << " TIter nextpath(listpaths);" << endl;
4109 out << " TObjString *pname;" << endl;
4110 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
4111 out << " TString current = pname->GetName();" << endl;
4112 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4113 out << " gSystem->AddIncludePath(current);" << endl;
4114 out << " }" << endl;
4115 out << " if (listpaths) delete listpaths;" << endl;
4116 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4117 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4118 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4119 if (fAdditionalLibs.Length()) {
4120 out << "// Add aditional AliRoot libraries" << endl;
4121 TObjArray *list = fAdditionalLibs.Tokenize(" ");
4124 while((str=(TObjString*)next())) {
4125 if (str->GetString().Contains(".so"))
4126 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4128 if (list) delete list;
4131 out << "// Analysis source to be compiled at runtime (if any)" << endl;
4132 if (fAnalysisSource.Length()) {
4133 TObjArray *list = fAnalysisSource.Tokenize(" ");
4136 while((str=(TObjString*)next())) {
4137 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4139 if (list) delete list;
4143 if (fFastReadOption) {
4144 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 !!!");
4145 out << "// fast xrootd reading enabled" << endl;
4146 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4147 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4148 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4149 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4150 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4151 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4153 // Change temp directory to current one
4154 out << "// Set temporary merging directory to current one" << endl;
4155 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
4156 out << "// Set temporary compilation directory to current one" << endl;
4157 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
4158 out << "// Connect to AliEn" << endl;
4159 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
4160 out << " TString outputDir = dir;" << endl;
4161 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4162 out << " TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4163 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4164 out << " TIter *iter = new TIter(list);" << endl;
4165 out << " TObjString *str;" << endl;
4166 out << " TString outputFile;" << endl;
4167 out << " Bool_t merged = kTRUE;" << endl;
4168 out << " while((str=(TObjString*)iter->Next())) {" << endl;
4169 out << " outputFile = str->GetString();" << endl;
4170 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
4171 out << " Int_t index = outputFile.Index(\"@\");" << endl;
4172 out << " if (index > 0) outputFile.Remove(index);" << endl;
4173 out << " // Skip already merged outputs" << endl;
4174 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
4175 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4176 out << " continue;" << endl;
4177 out << " }" << endl;
4178 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4179 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4180 out << " if (!merged) {" << endl;
4181 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4182 out << " return;" << endl;
4183 out << " }" << endl;
4184 out << " }" << endl;
4185 out << " // all outputs merged, validate" << endl;
4186 out << " ofstream out;" << endl;
4187 out << " out.open(\"outputs_valid\", ios::out);" << endl;
4188 out << " out.close();" << endl;
4189 out << " // read the analysis manager from file" << endl;
4190 TString analysisFile = fExecutable;
4191 analysisFile.ReplaceAll(".sh", ".root");
4192 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
4193 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
4194 << analysisFile << "\");" << endl;
4195 out << " if (!mgr) return;" << endl;
4196 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4197 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
4198 out << " mgr->PrintStatus();" << endl;
4199 if (AliAnalysisManager::GetAnalysisManager()) {
4200 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4201 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4203 if (TestBit(AliAnalysisGrid::kTest))
4204 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4206 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4209 out << " TTree *tree = NULL;" << endl;
4210 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4211 out << "}" << endl << endl;
4212 if (hasANALYSISalice) {
4213 out <<"//________________________________________________________________________________" << endl;
4214 out << "Bool_t SetupPar(const char *package) {" << endl;
4215 out << "// Compile the package and set it up." << endl;
4216 out << " TString pkgdir = package;" << endl;
4217 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4218 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4219 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
4220 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
4221 out << " // Check for BUILD.sh and execute" << endl;
4222 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4223 out << " printf(\"*******************************\\n\");" << endl;
4224 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
4225 out << " printf(\"*******************************\\n\");" << endl;
4226 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4227 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4228 out << " gSystem->ChangeDirectory(cdir);" << endl;
4229 out << " return kFALSE;" << endl;
4230 out << " }" << endl;
4231 out << " } else {" << endl;
4232 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4233 out << " gSystem->ChangeDirectory(cdir);" << endl;
4234 out << " return kFALSE;" << endl;
4235 out << " }" << endl;
4236 out << " // Check for SETUP.C and execute" << endl;
4237 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4238 out << " printf(\"*******************************\\n\");" << endl;
4239 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
4240 out << " printf(\"*******************************\\n\");" << endl;
4241 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4242 out << " } else {" << endl;
4243 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4244 out << " gSystem->ChangeDirectory(cdir);" << endl;
4245 out << " return kFALSE;" << endl;
4246 out << " }" << endl;
4247 out << " // Restore original workdir" << endl;
4248 out << " gSystem->ChangeDirectory(cdir);" << endl;
4249 out << " return kTRUE;" << endl;
4253 Bool_t copy = kTRUE;
4254 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4257 TString workdir = gGrid->GetHomeDirectory();
4258 workdir += fGridWorkingDir;
4259 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4260 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4261 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4262 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
4263 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4267 //______________________________________________________________________________
4268 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4270 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4271 // Note that for loading the compiled library. The current directory should have precedence in
4273 TString pkgdir = package;
4274 pkgdir.ReplaceAll(".par","");
4275 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4276 TString cdir = gSystem->WorkingDirectory();
4277 gSystem->ChangeDirectory(pkgdir);
4278 // Check for BUILD.sh and execute
4279 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4280 printf("**************************************************\n");
4281 printf("*** Building PAR archive %s\n", package);
4282 printf("**************************************************\n");
4283 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4284 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4285 gSystem->ChangeDirectory(cdir);
4289 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4290 gSystem->ChangeDirectory(cdir);
4293 // Check for SETUP.C and execute
4294 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4295 printf("**************************************************\n");
4296 printf("*** Setup PAR archive %s\n", package);
4297 printf("**************************************************\n");
4298 gROOT->Macro("PROOF-INF/SETUP.C");
4299 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4301 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4302 gSystem->ChangeDirectory(cdir);
4305 // Restore original workdir
4306 gSystem->ChangeDirectory(cdir);
4310 //______________________________________________________________________________
4311 void AliAnalysisAlien::WriteExecutable()
4313 // Generate the alien executable script.
4314 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4316 out.open(fExecutable.Data(), ios::out);
4318 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4321 out << "#!/bin/bash" << endl;
4322 // Make sure we can properly compile par files
4323 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4324 out << "echo \"=========================================\"" << endl;
4325 out << "echo \"############## PATH : ##############\"" << endl;
4326 out << "echo $PATH" << endl;
4327 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4328 out << "echo $LD_LIBRARY_PATH" << endl;
4329 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4330 out << "echo $ROOTSYS" << endl;
4331 out << "echo \"############## which root : ##############\"" << endl;
4332 out << "which root" << endl;
4333 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4334 out << "echo $ALICE_ROOT" << endl;
4335 out << "echo \"############## which aliroot : ##############\"" << endl;
4336 out << "which aliroot" << endl;
4337 out << "echo \"############## system limits : ##############\"" << endl;
4338 out << "ulimit -a" << endl;
4339 out << "echo \"############## memory : ##############\"" << endl;
4340 out << "free -m" << endl;
4341 out << "echo \"=========================================\"" << endl << endl;
4342 out << fExecutableCommand << " ";
4343 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
4344 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
4345 out << "echo \"############## memory after: ##############\"" << endl;
4346 out << "free -m" << endl;
4348 Bool_t copy = kTRUE;
4349 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4352 TString workdir = gGrid->GetHomeDirectory();
4353 TString bindir = Form("%s/bin", workdir.Data());
4354 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4355 workdir += fGridWorkingDir;
4356 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4357 if (FileExists(executable)) gGrid->Rm(executable);
4358 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4359 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4360 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4361 executable.Data())) Fatal("","Terminating");
4365 //______________________________________________________________________________
4366 void AliAnalysisAlien::WriteMergeExecutable()
4368 // Generate the alien executable script for the merging job.
4369 if (!fMergeViaJDL) return;
4370 TString mergeExec = fExecutable;
4371 mergeExec.ReplaceAll(".sh", "_merge.sh");
4372 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4374 out.open(mergeExec.Data(), ios::out);
4376 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4379 out << "#!/bin/bash" << endl;
4380 // Make sure we can properly compile par files
4381 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4382 out << "echo \"=========================================\"" << endl;
4383 out << "echo \"############## PATH : ##############\"" << endl;
4384 out << "echo $PATH" << endl;
4385 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4386 out << "echo $LD_LIBRARY_PATH" << endl;
4387 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4388 out << "echo $ROOTSYS" << endl;
4389 out << "echo \"############## which root : ##############\"" << endl;
4390 out << "which root" << endl;
4391 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4392 out << "echo $ALICE_ROOT" << endl;
4393 out << "echo \"############## which aliroot : ##############\"" << endl;
4394 out << "which aliroot" << endl;
4395 out << "echo \"############## system limits : ##############\"" << endl;
4396 out << "ulimit -a" << endl;
4397 out << "echo \"############## memory : ##############\"" << endl;
4398 out << "free -m" << endl;
4399 out << "echo \"=========================================\"" << endl << endl;
4400 TString mergeMacro = fExecutable;
4401 mergeMacro.ReplaceAll(".sh", "_merge.C");
4402 if (IsOneStageMerging())
4403 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4405 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4406 out << fExecutableCommand << " " << "$ARG" << endl;
4407 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4408 out << "echo \"############## memory after: ##############\"" << endl;
4409 out << "free -m" << endl;
4411 Bool_t copy = kTRUE;
4412 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4415 TString workdir = gGrid->GetHomeDirectory();
4416 TString bindir = Form("%s/bin", workdir.Data());
4417 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4418 workdir += fGridWorkingDir;
4419 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4420 if (FileExists(executable)) gGrid->Rm(executable);
4421 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4422 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4423 if (!copyLocal2Alien("WriteMergeExecutable",
4424 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4428 //______________________________________________________________________________
4429 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4431 // Write the production file to be submitted by LPM manager. The format is:
4432 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4433 // Next lines: full_path_to_dataset XXX (XXX is a string)
4434 // To submit, one has to: submit jdl XXX for all lines
4436 out.open(filename, ios::out);
4438 Error("WriteProductionFile", "Bad file name: %s", filename);
4442 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4443 workdir = gGrid->GetHomeDirectory();
4444 workdir += fGridWorkingDir;
4445 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4446 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4447 out << locjdl << " " << njobspermaster << endl;
4448 Int_t nmasterjobs = fInputFiles->GetEntries();
4449 for (Int_t i=0; i<nmasterjobs; i++) {
4450 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4451 runOutDir.ReplaceAll(".xml", "");
4453 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4455 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4458 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4459 if (FileExists(filename)) gGrid->Rm(filename);
4460 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4461 if (!copyLocal2Alien("WriteProductionFile", filename,
4462 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4466 //______________________________________________________________________________
4467 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4469 // Generate the alien validation script.
4470 // Generate the validation script
4472 if (fValidationScript.IsNull()) {
4473 fValidationScript = fExecutable;
4474 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4476 TString validationScript = fValidationScript;
4477 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4479 Error("WriteValidationScript", "Alien connection required");
4482 if (!fTerminateFiles.IsNull()) {
4483 fTerminateFiles.Strip();
4484 fTerminateFiles.ReplaceAll(" ",",");
4486 TString outStream = "";
4487 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4488 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4490 out.open(validationScript, ios::out);
4491 out << "#!/bin/bash" << endl;
4492 out << "##################################################" << endl;
4493 out << "validateout=`dirname $0`" << endl;
4494 out << "validatetime=`date`" << endl;
4495 out << "validated=\"0\";" << endl;
4496 out << "error=0" << endl;
4497 out << "if [ -z $validateout ]" << endl;
4498 out << "then" << endl;
4499 out << " validateout=\".\"" << endl;
4500 out << "fi" << endl << endl;
4501 out << "cd $validateout;" << endl;
4502 out << "validateworkdir=`pwd`;" << endl << endl;
4503 out << "echo \"*******************************************************\"" << outStream << endl;
4504 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4506 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4507 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4508 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4509 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4510 out << "ls -la ./" << outStream << endl;
4511 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4512 out << "##################################################" << endl;
4515 out << "if [ ! -f stderr ] ; then" << endl;
4516 out << " error=1" << endl;
4517 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4518 out << " echo \"Error = $error\" " << outStream << endl;
4519 out << "fi" << endl;
4521 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4522 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4523 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4524 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4527 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4528 out << " error=1" << endl;
4529 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4530 out << " echo \"$parArch\" " << outStream << endl;
4531 out << " echo \"Error = $error\" " << outStream << endl;
4532 out << "fi" << endl;
4534 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4535 out << " error=1" << endl;
4536 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4537 out << " echo \"$segViol\" " << outStream << endl;
4538 out << " echo \"Error = $error\" " << outStream << endl;
4539 out << "fi" << endl;
4541 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4542 out << " error=1" << endl;
4543 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4544 out << " echo \"$segFault\" " << outStream << endl;
4545 out << " echo \"Error = $error\" " << outStream << endl;
4546 out << "fi" << endl;
4548 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4549 out << " error=1" << endl;
4550 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4551 out << " echo \"$glibcErr\" " << outStream << endl;
4552 out << " echo \"Error = $error\" " << outStream << endl;
4553 out << "fi" << endl;
4555 // Part dedicated to the specific analyses running into the train
4557 TString outputFiles = fOutputFiles;
4558 if (merge && !fTerminateFiles.IsNull()) {
4560 outputFiles += fTerminateFiles;
4562 TObjArray *arr = outputFiles.Tokenize(",");
4565 while (!merge && (os=(TObjString*)next1())) {
4566 // No need to validate outputs produced by merging since the merging macro does this
4567 outputFile = os->GetString();
4568 Int_t index = outputFile.Index("@");
4569 if (index > 0) outputFile.Remove(index);
4570 if (fTerminateFiles.Contains(outputFile)) continue;
4571 if (outputFile.Contains("*")) continue;
4572 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4573 out << " error=1" << endl;
4574 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4575 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4576 out << "fi" << endl;
4579 out << "if ! [ -f outputs_valid ] ; then" << endl;
4580 out << " error=1" << endl;
4581 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4582 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4583 out << "fi" << endl;
4585 out << "if [ $error = 0 ] ; then" << endl;
4586 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4587 if (!IsKeepLogs()) {
4588 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4590 out << " rm -f std*" << endl;
4592 out << "fi" << endl;
4594 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4595 out << "echo \"*******************************************************\"" << outStream << endl;
4596 out << "cd -" << endl;
4597 out << "exit $error" << endl;
4599 Bool_t copy = kTRUE;
4600 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4603 TString workdir = gGrid->GetHomeDirectory();
4604 workdir += fGridWorkingDir;
4605 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4606 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4607 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4608 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4609 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");