]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisAlien.cxx
changing number of cluster cut to 50 (Jacek's suggestion for 2011 PbPb data)
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisAlien.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 // Author: Mihaela Gheata, 01/09/2008
17
18 //==============================================================================
19 //   AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
22
23 #include "AliAnalysisAlien.h"
24
25 #include "Riostream.h"
26 #include "TEnv.h"
27 #include "TKey.h"
28 #include "TBits.h"
29 #include "TError.h"
30 #include "TROOT.h"
31 #include "TSystem.h"
32 #include "TFile.h"
33 #include "TFileCollection.h"
34 #include "TChain.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
37 #include "TMacro.h"
38 #include "TGrid.h"
39 #include "TGridResult.h"
40 #include "TGridCollection.h"
41 #include "TGridJDL.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"
50
51 ClassImp(AliAnalysisAlien)
52 #if 0
53 ;
54 #endif  
55
56 namespace {
57   Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
58   {
59     TString sl(Form("file:%s", loc));
60     TString sr(Form("alien://%s", rem));
61     Bool_t ret = TFile::Cp(sl, sr);
62     if (!ret) { 
63       Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
64     }
65     return ret;
66   }
67 }
68     
69 //______________________________________________________________________________
70 AliAnalysisAlien::AliAnalysisAlien()
71                  :AliAnalysisGrid(),
72                   fGridJDL(NULL),
73                   fMergingJDL(NULL),
74                   fPrice(0),
75                   fTTL(0),
76                   fSplitMaxInputFileNumber(0),
77                   fMaxInitFailed(0),
78                   fMasterResubmitThreshold(0),
79                   fNtestFiles(0),
80                   fNrunsPerMaster(0),
81                   fMaxMergeFiles(0),
82                   fMaxMergeStages(0),
83                   fNsubmitted(0),
84                   fProductionMode(0),
85                   fOutputToRunNo(0),
86                   fMergeViaJDL(0),
87                   fFastReadOption(0),
88                   fOverwriteMode(1),
89                   fNreplicas(2),
90                   fNproofWorkers(0),
91                   fNproofWorkersPerSlave(0),
92                   fProofReset(0),
93                   fRunNumbers(),
94                   fExecutable(),
95                   fExecutableCommand(),
96                   fArguments(),
97                   fExecutableArgs(),
98                   fAnalysisMacro(),
99                   fAnalysisSource(),
100                   fValidationScript(),
101                   fAdditionalRootLibs(),
102                   fAdditionalLibs(),
103                   fSplitMode(),
104                   fAPIVersion(),
105                   fROOTVersion(),
106                   fAliROOTVersion(),
107                   fExternalPackages(),
108                   fUser(),
109                   fGridWorkingDir(),
110                   fGridDataDir(),
111                   fDataPattern(),
112                   fGridOutputDir(),
113                   fOutputArchive(),
114                   fOutputFiles(),
115                   fInputFormat(),
116                   fDatasetName(),
117                   fJDLName(),
118                   fTerminateFiles(),
119                             fMergeExcludes(),
120                   fRegisterExcludes(),
121                   fIncludePath(),
122                   fCloseSE(),
123                   fFriendChainName(),
124                   fJobTag(),
125                   fOutputSingle(),
126                   fRunPrefix(),
127                   fProofCluster(),
128                   fProofDataSet(),
129                   fFileForTestMode(),
130                   fRootVersionForProof(),
131                   fAliRootMode(),
132                   fMergeDirName(),
133                   fInputFiles(0),
134                   fPackages(0),
135                   fModules(0),
136                   fProofParam()
137 {
138 // Dummy ctor.
139    SetDefaults();
140 }
141
142 //______________________________________________________________________________
143 AliAnalysisAlien::AliAnalysisAlien(const char *name)
144                  :AliAnalysisGrid(name),
145                   fGridJDL(NULL),
146                   fMergingJDL(NULL),
147                   fPrice(0),
148                   fTTL(0),
149                   fSplitMaxInputFileNumber(0),
150                   fMaxInitFailed(0),
151                   fMasterResubmitThreshold(0),
152                   fNtestFiles(0),
153                   fNrunsPerMaster(0),
154                   fMaxMergeFiles(0),
155                   fMaxMergeStages(0),
156                   fNsubmitted(0),
157                   fProductionMode(0),
158                   fOutputToRunNo(0),
159                   fMergeViaJDL(0),
160                   fFastReadOption(0),
161                   fOverwriteMode(1),
162                   fNreplicas(2),
163                   fNproofWorkers(0),
164                   fNproofWorkersPerSlave(0),
165                   fProofReset(0),
166                   fRunNumbers(),
167                   fExecutable(),
168                   fExecutableCommand(),
169                   fArguments(),
170                   fExecutableArgs(),
171                   fAnalysisMacro(),
172                   fAnalysisSource(),
173                   fValidationScript(),
174                   fAdditionalRootLibs(),
175                   fAdditionalLibs(),
176                   fSplitMode(),
177                   fAPIVersion(),
178                   fROOTVersion(),
179                   fAliROOTVersion(),
180                   fExternalPackages(),
181                   fUser(),
182                   fGridWorkingDir(),
183                   fGridDataDir(),
184                   fDataPattern(),
185                   fGridOutputDir(),
186                   fOutputArchive(),
187                   fOutputFiles(),
188                   fInputFormat(),
189                   fDatasetName(),
190                   fJDLName(),
191                   fTerminateFiles(),
192                   fMergeExcludes(),
193                   fRegisterExcludes(),
194                   fIncludePath(),
195                   fCloseSE(),
196                   fFriendChainName(),
197                   fJobTag(),
198                   fOutputSingle(),
199                   fRunPrefix(),
200                   fProofCluster(),
201                   fProofDataSet(),
202                   fFileForTestMode(),
203                   fRootVersionForProof(),
204                   fAliRootMode(),
205                   fMergeDirName(),
206                   fInputFiles(0),
207                   fPackages(0),
208                   fModules(0),
209                   fProofParam()
210 {
211 // Default ctor.
212    SetDefaults();
213 }
214
215 //______________________________________________________________________________
216 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
217                  :AliAnalysisGrid(other),
218                   fGridJDL(NULL),
219                   fMergingJDL(NULL),
220                   fPrice(other.fPrice),
221                   fTTL(other.fTTL),
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),
254                   fUser(other.fUser),
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),
279                   fInputFiles(0),
280                   fPackages(0),
281                   fModules(0),
282                   fProofParam()
283 {
284 // Copy ctor.
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);
292       TObject *obj;
293       while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
294       fInputFiles->SetOwner();
295    }   
296    if (other.fPackages) {
297       fPackages = new TObjArray();
298       TIter next(other.fPackages);
299       TObject *obj;
300       while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
301       fPackages->SetOwner();
302    }   
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);
310          fModules->Add(mod);
311       }
312    }   
313 }
314
315 //______________________________________________________________________________
316 AliAnalysisAlien::~AliAnalysisAlien()
317 {
318 // Destructor.
319    delete fGridJDL;
320    delete fMergingJDL;
321    delete fInputFiles;
322    delete fPackages;
323    delete fModules;
324    fProofParam.DeleteAll();
325 }   
326
327 //______________________________________________________________________________
328 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
329 {
330 // Assignment.
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;
336       fTTL                     = other.fTTL;
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;
369       fUser                    = other.fUser;
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);
397          TObject *obj;
398          while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
399          fInputFiles->SetOwner();
400       }   
401       if (other.fPackages) {
402          fPackages = new TObjArray();
403          TIter next(other.fPackages);
404          TObject *obj;
405          while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
406          fPackages->SetOwner();
407       }   
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);
415             fModules->Add(mod);
416          }
417       }   
418    }
419    return *this;
420 }
421
422 //______________________________________________________________________________
423 void AliAnalysisAlien::AddAdditionalLibrary(const char *name)
424 {
425 // Add a single additional library to be loaded. Extension must be present.
426    TString lib(name);
427    if (!lib.Contains(".")) {
428       Error("AddAdditionalLibrary", "Extension not defined for %s", name);
429       return;
430    }
431    if (fAdditionalLibs.Contains(name)) {
432       Warning("AddAdditionalLibrary", "Library %s already added.", name);
433       return;
434    }
435    if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
436    fAdditionalLibs += lib;
437 }   
438
439 //______________________________________________________________________________
440 void AliAnalysisAlien::AddModule(AliAnalysisTaskCfg *module)
441 {
442 // Adding a module. Checks if already existing. Becomes owned by this.
443    if (!module) return;
444    if (GetModule(module->GetName())) {
445       Error("AddModule", "A module having the same name %s already added", module->GetName());
446       return;
447    }
448    if (!fModules) {
449       fModules = new TObjArray();
450       fModules->SetOwner();
451    }
452    fModules->Add(module);
453 }
454
455 //______________________________________________________________________________
456 void AliAnalysisAlien::AddModules(TObjArray *list)
457 {
458 // Adding a list of modules. Checks if already existing. Becomes owned by this.
459    TIter next(list);
460    AliAnalysisTaskCfg *module;
461    while ((module = (AliAnalysisTaskCfg*)next())) AddModule(module);
462 }   
463
464 //______________________________________________________________________________
465 Bool_t AliAnalysisAlien::CheckDependencies()
466 {
467 // Check if all dependencies are satisfied. Reorder modules if needed.
468    Int_t nmodules = GetNmodules();
469    if (!nmodules) {
470       Warning("CheckDependencies", "No modules added yet to check their dependencies");
471       return kTRUE;
472    }   
473    AliAnalysisTaskCfg *mod = 0;
474    AliAnalysisTaskCfg *dep = 0;
475    TString depname;
476    Int_t i, j, k;
477    for (i=0; i<nmodules; i++) {
478       mod = (AliAnalysisTaskCfg*) fModules->At(i);
479       Int_t ndeps = mod->GetNdeps();
480       Int_t istart = i;
481       for (j=0; j<ndeps; j++) {
482          depname = mod->GetDependency(j);
483          dep = GetModule(depname);
484          if (!dep) {
485             Error("CheckDependencies","Dependency %s not added for module %s",
486                    depname.Data(), mod->GetName());
487             return kFALSE;
488          }
489          if (dep->NeedsDependency(mod->GetName())) {
490             Error("CheckDependencies","Modules %s and %s circularly depend on each other",
491                    mod->GetName(), dep->GetName());
492             return kFALSE;
493          }                  
494          Int_t idep = fModules->IndexOf(dep);
495          // The dependency task must come first
496          if (idep>i) {
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++);
502          }
503          //Redo from istart if dependencies were inserted
504          if (i>istart) i=istart-1;
505       }
506    }
507    return kTRUE;
508 }      
509
510 //______________________________________________________________________________
511 AliAnalysisManager *AliAnalysisAlien::CreateAnalysisManager(const char *name, const char *filename)
512 {
513 // Create the analysis manager and optionally execute the macro in filename.
514    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
515    if (mgr) return mgr;
516    mgr = new AliAnalysisManager(name);
517    mgr->SetGridHandler((AliAnalysisGrid*)this);
518    if (strlen(filename)) {
519       TString line = gSystem->ExpandPathName(filename);
520       line.Prepend(".x ");
521       gROOT->ProcessLine(line.Data());
522    }
523    return mgr;
524 }      
525       
526 //______________________________________________________________________________
527 Int_t AliAnalysisAlien::GetNmodules() const
528 {
529 // Get number of modules.
530    if (!fModules) return 0;
531    return fModules->GetEntries();
532 }
533
534 //______________________________________________________________________________
535 AliAnalysisTaskCfg *AliAnalysisAlien::GetModule(const char *name)
536 {
537 // Get a module by name.
538    if (!fModules) return 0;
539    return (AliAnalysisTaskCfg*)fModules->FindObject(name);
540 }
541    
542 //______________________________________________________________________________
543 Bool_t AliAnalysisAlien::LoadModule(AliAnalysisTaskCfg *mod)
544 {
545 // Load a given module.
546    if (mod->IsLoaded()) return kTRUE;
547    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
548    if (!mgr) {
549       Error("LoadModule", "No analysis manager created yet. Use CreateAnalysisManager first.");
550       return kFALSE;
551    }   
552    Int_t ndeps = mod->GetNdeps();
553    TString depname;
554    for (Int_t j=0; j<ndeps; j++) {
555       depname = mod->GetDependency(j);
556       AliAnalysisTaskCfg *dep = GetModule(depname);
557       if (!dep) {
558          Error("LoadModule","Dependency %s not existing for module %s",
559                 depname.Data(), mod->GetName());
560          return kFALSE;
561       }
562       if (!LoadModule(dep)) {
563          Error("LoadModule","Dependency %s for module %s could not be loaded",
564                 depname.Data(), mod->GetName());
565          return kFALSE;
566       }
567    }
568    // Load libraries for the module
569    if (!mod->CheckLoadLibraries()) {
570       Error("LoadModule", "Cannot load all libraries for module %s", mod->GetName());
571       return kFALSE;
572    }
573    // Check if a custom file name was requested
574    if (strlen(mod->GetOutputFileName())) mgr->SetCommonFileName(mod->GetOutputFileName());
575
576    // Check if a custom terminate file name was requested
577    if (strlen(mod->GetTerminateFileName())) {
578       if (!fTerminateFiles.IsNull()) fTerminateFiles += ",";
579       fTerminateFiles += mod->GetTerminateFileName();
580    }   
581
582    // Execute the macro
583    if (mod->ExecuteMacro()<0) {
584       Error("LoadModule", "Executing the macro %s with arguments: %s for module %s returned a negative value",
585              mod->GetMacroName(), mod->GetMacroArgs(), mod->GetName());
586       return kFALSE;
587    }
588    // Configure dependencies
589    if (mod->GetConfigMacro() && mod->ExecuteConfigMacro()<0) {
590       Error("LoadModule", "There was an error executing the deps config macro %s for module %s",
591             mod->GetConfigMacro()->GetTitle(), mod->GetName());
592       return kFALSE;
593    }
594    // Adjust extra libraries
595    Int_t nlibs = mod->GetNlibs();
596    TString lib;
597    for (Int_t i=0; i<nlibs; i++) {
598       lib = mod->GetLibrary(i);
599       if (fAdditionalLibs.Contains(lib)) continue;
600       lib = Form("lib%s.so", lib.Data());
601       if (!fAdditionalLibs.IsNull()) fAdditionalLibs += " ";
602       fAdditionalLibs += lib;
603    }
604    return kTRUE;
605 }
606
607 //______________________________________________________________________________
608 Bool_t AliAnalysisAlien::GenerateTrain(const char *name)
609 {
610 // Generate the full train.
611    fAdditionalLibs = "";
612    if (!LoadModules()) return kFALSE;
613    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
614    if (!mgr->InitAnalysis()) return kFALSE;
615    mgr->RunLocalInit();
616    mgr->PrintStatus();
617    Int_t productionMode = fProductionMode;
618    SetProductionMode();
619    TString macro = fAnalysisMacro;
620    TString executable = fExecutable;
621    TString validation = fValidationScript;
622    TString execCommand = fExecutableCommand;
623    SetAnalysisMacro(Form("%s.C", name));
624    SetExecutable(Form("%s.sh", name));
625 //   SetExecutableCommand("aliroot -b -q ");
626    SetValidationScript(Form("%s_validation.sh", name));
627    StartAnalysis();
628    SetProductionMode(productionMode);
629    fAnalysisMacro = macro;
630    fExecutable = executable;
631    fExecutableCommand = execCommand;
632    fValidationScript = validation;
633    return kTRUE;   
634 }   
635
636 //______________________________________________________________________________
637 Bool_t AliAnalysisAlien::GenerateTest(const char *name, const char *modname)
638 {
639 // Generate test macros for a single module or for the full train.
640    fAdditionalLibs = "";
641    if (strlen(modname)) {
642       if (!CheckDependencies()) return kFALSE;
643       AliAnalysisTaskCfg *mod = GetModule(modname);
644       if (!mod) {
645          Error("GenerateTest", "cannot generate test for inexistent module %s", modname);
646          return kFALSE;
647       }
648       if (!LoadModule(mod)) return kFALSE;
649    } else if (!LoadModules()) return kFALSE;
650    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
651    if (!mgr->InitAnalysis()) return kFALSE;
652    mgr->RunLocalInit();
653    mgr->PrintStatus();
654    SetLocalTest(kTRUE);
655    Int_t productionMode = fProductionMode;
656    SetProductionMode();
657    TString macro = fAnalysisMacro;
658    TString executable = fExecutable;
659    TString validation = fValidationScript;
660    TString execCommand = fExecutableCommand;
661    SetAnalysisMacro(Form("%s.C", name));
662    SetExecutable(Form("%s.sh", name));
663 //   SetExecutableCommand("aliroot -b -q ");
664    SetValidationScript(Form("%s_validation.sh", name));
665    WriteAnalysisFile();   
666    WriteAnalysisMacro();
667    WriteExecutable();
668    WriteValidationScript();   
669    SetLocalTest(kFALSE);
670    SetProductionMode(productionMode);
671    fAnalysisMacro = macro;
672    fExecutable = executable;
673    fExecutableCommand = execCommand;
674    fValidationScript = validation;
675    return kTRUE;   
676 }
677
678 //______________________________________________________________________________
679 Bool_t AliAnalysisAlien::LoadModules()
680 {
681 // Load all modules by executing the AddTask macros. Checks first the dependencies.
682    fAdditionalLibs = "";
683    Int_t nmodules = GetNmodules();
684    if (!nmodules) {
685       Warning("LoadModules", "No module to be loaded");
686       return kTRUE;
687    }   
688    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
689    if (!mgr) {
690       Error("LoadModules", "No analysis manager created yet. Use CreateAnalysisManager first.");
691       return kFALSE;
692    }   
693    if (!CheckDependencies()) return kFALSE;
694    nmodules = GetNmodules();
695    AliAnalysisTaskCfg *mod;
696    for (Int_t imod=0; imod<nmodules; imod++) {
697       mod = (AliAnalysisTaskCfg*)fModules->At(imod);
698       if (!LoadModule(mod)) return kFALSE;
699    }
700    return kTRUE;
701 }      
702
703 //______________________________________________________________________________
704 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
705 {
706 // Set the run number format. Can be a prefix or a format like "%09d"
707    fRunPrefix = prefix;
708    if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
709 }   
710
711 //______________________________________________________________________________
712 void AliAnalysisAlien::AddIncludePath(const char *path)
713 {
714 // Add include path in the remote analysis macro.
715    TString p(path);
716    if (p.Contains("-I")) fIncludePath += Form("%s ", path);
717    else                  fIncludePath += Form("-I%s ", path);
718 }
719
720 //______________________________________________________________________________
721 void AliAnalysisAlien::AddRunNumber(Int_t run)
722 {
723 // Add a run number to the list of runs to be processed.
724    if (fRunNumbers.Length()) fRunNumbers += " ";
725    fRunNumbers += Form(fRunPrefix.Data(), run);
726 }   
727
728 //______________________________________________________________________________
729 void AliAnalysisAlien::AddRunList(const char* runList)
730 {
731 // Add several runs into the list of runs; they are expected to be separated by a blank character.  
732   TString    sList = runList;
733   TObjArray *list  = sList.Tokenize(" ");
734   Int_t n = list->GetEntries();
735   for (Int_t i = 0; i < n; i++) {
736     TObjString *os = (TObjString*)list->At(i);
737     AddRunNumber(os->GetString().Atoi());
738   }
739   delete list;
740 }
741
742 //______________________________________________________________________________
743 void AliAnalysisAlien::AddRunNumber(const char* run)
744 {
745 // Add a run number to the list of runs to be processed.
746    TString runs = run;
747    TObjString *os;
748    TObjArray *arr = runs.Tokenize(" ");
749    TIter next(arr);
750    TString prefix; 
751    prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
752    while ((os=(TObjString*)next())){
753        if (fRunNumbers.Length()) fRunNumbers += " ";
754        fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
755    }
756    delete arr;
757 }   
758
759 //______________________________________________________________________________
760 void AliAnalysisAlien::AddDataFile(const char *lfn)
761 {
762 // Adds a data file to the input to be analysed. The file should be a valid LFN
763 // or point to an existing file in the alien workdir.
764    if (!fInputFiles) fInputFiles = new TObjArray();
765    fInputFiles->Add(new TObjString(lfn));
766 }
767
768 //______________________________________________________________________________
769 void AliAnalysisAlien::AddExternalPackage(const char *package)
770 {
771 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
772    if (fExternalPackages) fExternalPackages += " ";
773    fExternalPackages += package;
774 }   
775       
776 //______________________________________________________________________________
777 Bool_t AliAnalysisAlien::Connect()
778 {
779 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
780    if (gGrid && gGrid->IsConnected()) return kTRUE;
781    if (fProductionMode) return kTRUE;
782    if (!gGrid) {
783       Info("Connect", "Trying to connect to AliEn ...");
784       TGrid::Connect("alien://");
785    }
786    if (!gGrid || !gGrid->IsConnected()) {
787       Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
788       return kFALSE;
789    }  
790    fUser = gGrid->GetUser();
791    Info("Connect", "\n#####   Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
792    return kTRUE;
793 }
794
795 //______________________________________________________________________________
796 void AliAnalysisAlien::CdWork()
797 {
798 // Check validity of alien workspace. Create directory if possible.
799    if (!Connect()) {
800       Error("CdWork", "Alien connection required");
801       return;
802    } 
803    TString homedir = gGrid->GetHomeDirectory();
804    TString workdir = homedir + fGridWorkingDir;
805    if (DirectoryExists(workdir)) {
806       gGrid->Cd(workdir);
807       return;
808    }   
809    // Work directory not existing - create it
810    gGrid->Cd(homedir);
811    if (gGrid->Mkdir(workdir, "-p")) {
812       gGrid->Cd(fGridWorkingDir);
813       Info("CdWork", "\n#####   Created alien working directory %s", fGridWorkingDir.Data());
814    } else {
815       Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
816               workdir.Data(), homedir.Data());
817       fGridWorkingDir = "";
818    }          
819 }
820
821 //______________________________________________________________________________
822 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
823 {
824 // Check if file copying is possible.
825    if (fProductionMode) return kTRUE;
826    TString salienpath(alienpath);
827    if (salienpath.Contains(" ")) {
828       Error("CheckFileCopy", "path: <%s> contains blancs - FIX IT !",alienpath);
829       return kFALSE;
830    }   
831    if (!Connect()) {
832       Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
833       return kFALSE;
834    }
835    Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
836         \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
837    // Check if alien_CLOSE_SE is defined
838    TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
839    if (!closeSE.IsNull()) {
840       Info("CheckFileCopy", "Your current close storage is pointing to: \
841            \n      alien_CLOSE_SE = \"%s\"", closeSE.Data());
842    } else {
843       Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
844    }        
845    // Check if grid directory exists.
846    if (!DirectoryExists(alienpath)) {
847       Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
848       return kFALSE;
849    }
850    TString stest = "plugin_test_copy";
851    TFile f(stest, "RECREATE");
852    // User may not have write permissions to current directory 
853    if (f.IsZombie()) {
854       Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
855             gSystem->WorkingDirectory());
856       return kFALSE;
857    }
858    f.Close();
859    if (FileExists(Form("alien://%s/%s",alienpath, stest.Data()))) gGrid->Rm(Form("alien://%s/%s",alienpath, stest.Data()));
860    if (!TFile::Cp(stest.Data(), Form("alien://%s/%s",alienpath, stest.Data()))) {
861       Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
862            \n# 1. Make sure you have write permissions there. If this is the case: \
863            \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
864            \n#    Do:           export alien_CLOSE_SE=\"working_disk_SE\" \
865            \n#    To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
866            \n#    Redo token:   rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
867       gSystem->Unlink(stest.Data());
868       return kFALSE;
869    }   
870    gSystem->Unlink(stest.Data());
871    gGrid->Rm(Form("%s/%s",alienpath,stest.Data()));
872    Info("CheckFileCopy", "### ...SUCCESS ###");
873    return kTRUE;
874 }   
875
876 //______________________________________________________________________________
877 Bool_t AliAnalysisAlien::CheckInputData()
878 {
879 // Check validity of input data. If necessary, create xml files.
880    if (fProductionMode) return kTRUE;
881    if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
882       if (!fGridDataDir.Length()) {
883          Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
884          return kFALSE;
885       }
886       if (fMergeViaJDL) {
887          Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
888          return kFALSE;
889       }   
890       Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
891       if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
892          TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode) 
893       return kTRUE;
894    }
895    // Process declared files
896    Bool_t isCollection = kFALSE;
897    Bool_t isXml = kFALSE;
898    Bool_t useTags = kFALSE;
899    Bool_t checked = kFALSE;
900    if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
901    TString file;
902    TString workdir = gGrid->GetHomeDirectory();
903    workdir += fGridWorkingDir;
904    if (fInputFiles) {
905       TObjString *objstr;
906       TIter next(fInputFiles);
907       while ((objstr=(TObjString*)next())) {
908          file = workdir;
909          file += "/";
910          file += objstr->GetString();
911          // Store full lfn path
912          if (FileExists(file)) objstr->SetString(file);
913          else {
914             file = objstr->GetName();
915             if (!FileExists(objstr->GetName())) {
916                Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
917                      objstr->GetName(), workdir.Data());
918                return kFALSE;
919             }         
920          }
921          Bool_t iscoll, isxml, usetags;
922          CheckDataType(file, iscoll, isxml, usetags);
923          if (!checked) {
924             checked = kTRUE;
925             isCollection = iscoll;
926             isXml = isxml;
927             useTags = usetags;
928             TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
929          } else {
930             if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
931                Error("CheckInputData", "Some conflict was found in the types of inputs");
932                return kFALSE;
933             } 
934          }
935       }
936    }
937    // Process requested run numbers
938    if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
939    // Check validity of alien data directory
940    if (!fGridDataDir.Length()) {
941       Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
942       return kFALSE;
943    }
944    if (!DirectoryExists(fGridDataDir)) {
945       Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
946       return kFALSE;
947    }
948    if (isCollection) {
949       Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
950       return kFALSE;   
951    }
952    
953    if (checked && !isXml) {
954       Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
955       return kFALSE;   
956    }
957    // Check validity of run number(s)
958    TObjArray *arr;
959    TObjString *os;
960    TString format;
961    Int_t nruns = 0;
962    TString schunk, schunk2;
963    TString path;
964    if (!checked) {
965       checked = kTRUE;
966       useTags = fDataPattern.Contains("tag");
967       TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
968    }   
969    if (useTags != fDataPattern.Contains("tag")) {
970       Error("CheckInputData", "Cannot mix input files using/not using tags");
971       return kFALSE;
972    }
973    if (fRunNumbers.Length()) {
974       Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
975       arr = fRunNumbers.Tokenize(" ");
976       TIter next(arr);
977       while ((os=(TObjString*)next())) {
978          path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
979          if (!DirectoryExists(path)) {
980             Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
981             continue;
982          }
983          path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
984          TString msg = "\n#####   file: ";
985          msg += path;
986          msg += " type: xml_collection;";
987          if (useTags) msg += " using_tags: Yes";
988          else          msg += " using_tags: No";
989          Info("CheckDataType", "%s", msg.Data());
990          if (fNrunsPerMaster<2) {
991             AddDataFile(Form("%s.xml", os->GetString().Data()));
992          } else {
993             nruns++;
994             if (((nruns-1)%fNrunsPerMaster) == 0) {
995                schunk = os->GetString();
996             }   
997             if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
998             schunk += Form("_%s.xml", os->GetString().Data());
999             AddDataFile(schunk);
1000          }   
1001       }
1002       delete arr;   
1003    } else {
1004       Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
1005       for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1006          format = Form("%%s/%s ", fRunPrefix.Data());
1007          path = Form(format.Data(), fGridDataDir.Data(), irun);
1008          if (!DirectoryExists(path)) {
1009             continue;
1010          }
1011          format = Form("%%s/%s.xml", fRunPrefix.Data());
1012          path = Form(format.Data(), workdir.Data(),irun);
1013          TString msg = "\n#####   file: ";
1014          msg += path;
1015          msg += " type: xml_collection;";
1016          if (useTags) msg += " using_tags: Yes";
1017          else          msg += " using_tags: No";
1018          Info("CheckDataType", "%s", msg.Data());
1019          if (fNrunsPerMaster<2) {
1020             format = Form("%s.xml", fRunPrefix.Data());
1021             AddDataFile(Form(format.Data(),irun));
1022          } else {
1023             nruns++;
1024             if (((nruns-1)%fNrunsPerMaster) == 0) {
1025                schunk = Form(fRunPrefix.Data(),irun);
1026             }
1027             format = Form("_%s.xml", fRunPrefix.Data());
1028             schunk2 = Form(format.Data(), irun);
1029             if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
1030             schunk += schunk2;
1031             AddDataFile(schunk);
1032          }   
1033       }
1034       if (!fInputFiles) {
1035          schunk += schunk2;
1036          AddDataFile(schunk);
1037       }   
1038    }
1039    return kTRUE;      
1040 }   
1041
1042 //______________________________________________________________________________
1043 Bool_t AliAnalysisAlien::CopyLocalDataset(const char *griddir, const char *pattern, Int_t nfiles, const char *output, const char *archivefile, const char *outputdir)
1044 {
1045 // Copy data from the given grid directory according a pattern and make a local
1046 // dataset.
1047 // archivefile (optional) results in that the archive containing the file <pattern> is copied. archivefile can contain a list of files (semicolon-separated) which are all copied
1048    if (!Connect()) {
1049       Error("CopyLocalDataset", "Cannot copy local dataset with no grid connection");
1050       return kFALSE;
1051    }
1052    if (!DirectoryExists(griddir)) {
1053       Error("CopyLocalDataset", "Data directory %s not existing.", griddir);
1054       return kFALSE;
1055    }
1056    TString command = Form("find -z -l %d %s %s", nfiles, griddir, pattern);
1057    printf("Running command: %s\n", command.Data());
1058    TGridResult *res = gGrid->Command(command);
1059    Int_t nfound = res->GetEntries();
1060    if (!nfound) {
1061       Error("CopyLocalDataset", "No file found in <%s> having pattern <%s>", griddir, pattern);
1062       return kFALSE;
1063    }
1064    printf("... found %d files. Copying locally ...\n", nfound);
1065    
1066    // archives
1067    TObjArray* additionalArchives = 0;
1068    if (strlen(archivefile) > 0 && TString(archivefile).Contains(";")) {
1069       additionalArchives = TString(archivefile).Tokenize(";");
1070       archivefile = additionalArchives->At(0)->GetName();
1071       additionalArchives->RemoveAt(0);
1072       additionalArchives->Compress();
1073    }
1074    
1075    // Copy files locally
1076    ofstream out;
1077    out.open(output, ios::out);
1078    TMap *map;
1079    TString turl, dirname, filename, temp;
1080    TString cdir = gSystem->WorkingDirectory();
1081    gSystem->MakeDirectory(outputdir);
1082    gSystem->ChangeDirectory(outputdir);
1083    for (Int_t i=0; i<nfound; i++) {
1084       map = (TMap*)res->At(i);
1085       turl = map->GetValue("turl")->GetName();
1086       filename = gSystem->BaseName(turl.Data());
1087       dirname = gSystem->DirName(turl.Data());
1088       dirname = gSystem->BaseName(dirname.Data());
1089       gSystem->MakeDirectory(dirname);
1090       
1091       TString source(turl);
1092       TString targetFileName(filename);
1093       
1094       if (strlen(archivefile) > 0) {
1095         // TODO here the archive in which the file resides should be determined
1096         // however whereis returns only a guid, and guid2lfn does not work
1097         // Therefore we use the one provided as argument for now
1098         source = Form("%s/%s", gSystem->DirName(source.Data()), archivefile);
1099         targetFileName = archivefile;
1100       }
1101       if (TFile::Cp(source, Form("file:./%s/%s", dirname.Data(), targetFileName.Data()))) {
1102          Bool_t success = kTRUE;
1103          if (additionalArchives)
1104             for (Int_t j=0; j<additionalArchives->GetEntriesFast(); j++)
1105             {
1106                TString target;
1107                target.Form("./%s/%s", dirname.Data(), additionalArchives->At(j)->GetName());
1108                gSystem->MakeDirectory(gSystem->DirName(target));
1109                success &= TFile::Cp(Form("%s/%s", gSystem->DirName(source.Data()), additionalArchives->At(j)->GetName()), Form("file:%s", target.Data()));
1110             }
1111
1112          if (success) {
1113             if (strlen(archivefile) > 0) targetFileName = Form("%s#%s", targetFileName.Data(), gSystem->BaseName(turl.Data()));
1114             out << cdir << Form("/%s/%s/%s", outputdir, dirname.Data(), targetFileName.Data()) << endl;
1115          }
1116       }
1117    }
1118    gSystem->ChangeDirectory(cdir);
1119    delete res;
1120    if (additionalArchives)
1121      delete additionalArchives;
1122    return kTRUE;
1123 }   
1124
1125 //______________________________________________________________________________
1126 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
1127 {
1128 // Create dataset for the grid data directory + run number.
1129    const Int_t gMaxEntries = 15000;
1130    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
1131    if (!Connect()) {
1132       Error("CreateDataset", "Cannot create dataset with no grid connection");
1133       return kFALSE;
1134    }   
1135
1136    // Cd workspace
1137    if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
1138    TString workdir = gGrid->GetHomeDirectory();
1139    workdir += fGridWorkingDir;
1140
1141    // Compose the 'find' command arguments
1142    TString format;
1143    TString command;
1144    TString options = "-x collection ";
1145    if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
1146    else options += Form("-l %d ", gMaxEntries);  // Protection for the find command
1147    TString conditions = "";
1148    Int_t nstart = 0;
1149    Int_t ncount = 0;
1150    Int_t stage = 0;
1151    TString file;
1152    TString path;
1153    Int_t nruns = 0;
1154    TString schunk, schunk2;
1155    TGridCollection *cbase=0, *cadd=0;
1156    if (!fRunNumbers.Length() && !fRunRange[0]) {
1157       if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
1158       // Make a single data collection from data directory.
1159       path = fGridDataDir;
1160       if (!DirectoryExists(path)) {
1161          Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
1162          return kFALSE;
1163       }   
1164 //      CdWork();
1165       if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1166       else file = Form("%s.xml", gSystem->BaseName(path));
1167       while (1) {
1168          ncount = 0;
1169          stage++;
1170          if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1171             command = "find ";
1172             command += Form("%s -o %d ",options.Data(), nstart);
1173             command += path;
1174             command += " ";
1175             command += pattern;
1176             command += conditions;
1177             printf("command: %s\n", command.Data());
1178             TGridResult *res = gGrid->Command(command);
1179             if (res) delete res;
1180             // Write standard output to file
1181             gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
1182             Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1183             Bool_t nullFile = kFALSE;
1184             if (!hasGrep) {
1185                 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1186             } else {
1187                nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1188                if (nullFile) {
1189                   Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
1190                   gSystem->Exec("rm -f __tmp*");
1191                   return kFALSE;
1192                }
1193                TString line;
1194                ifstream in;
1195                in.open("__tmp__");
1196                in >> line;
1197                in.close();
1198                gSystem->Exec("rm -f __tmp__");
1199                ncount = line.Atoi();
1200             }         
1201          }
1202          if (ncount == gMaxEntries) {
1203             Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1204             cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1205             if (!cbase) cbase = cadd;
1206             else {
1207                cbase->Add(cadd);
1208                delete cadd;
1209             }   
1210             nstart += ncount;
1211          } else {
1212             if (cbase) {
1213                cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1214                printf("... please wait - TAlienCollection::Add() scales badly...\n");
1215                cbase->Add(cadd);
1216                delete cadd;
1217                cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1218                delete cbase; cbase = 0;               
1219             } else {
1220                TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1221             }
1222             gSystem->Exec("rm -f __tmp*");   
1223             Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1224             break;
1225          }
1226       }
1227       Bool_t fileExists = FileExists(file);
1228       if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
1229          // Copy xml file to alien space
1230          if (fileExists) gGrid->Rm(file);
1231          TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1232          if (!FileExists(file)) {
1233             Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1234             return kFALSE;
1235          }
1236          // Update list of files to be processed.
1237       }
1238       AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
1239       return kTRUE;
1240    }   
1241    // Several runs
1242    Bool_t nullResult = kTRUE;
1243    if (fRunNumbers.Length()) {
1244       TObjArray *arr = fRunNumbers.Tokenize(" ");
1245       TObjString *os;
1246       TIter next(arr);
1247       while ((os=(TObjString*)next())) {
1248          nstart = 0;
1249          stage = 0;
1250          path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
1251          if (!DirectoryExists(path)) continue;
1252 //         CdWork();
1253          if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1254          else file = Form("%s.xml", os->GetString().Data());
1255          // If local collection file does not exist, create it via 'find' command.
1256          while (1) {
1257             ncount = 0;
1258             stage++;
1259             if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1260                command = "find ";
1261                command +=  Form("%s -o %d ",options.Data(), nstart);
1262                command += path;
1263                command += pattern;
1264                command += conditions;
1265                TGridResult *res = gGrid->Command(command);
1266                if (res) delete res;
1267                // Write standard output to file
1268                gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1269                Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1270                Bool_t nullFile = kFALSE;
1271                if (!hasGrep) {
1272                   Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1273                } else {
1274                   nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1275                   if (nullFile) {
1276                      Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1277                      gSystem->Exec("rm -f __tmp*");
1278                      fRunNumbers.ReplaceAll(os->GetString().Data(), "");
1279                      break;
1280                   }   
1281                   TString line;
1282                   ifstream in;
1283                   in.open("__tmp__");
1284                   in >> line;
1285                   in.close();
1286                   gSystem->Exec("rm -f __tmp__");   
1287                   ncount = line.Atoi();
1288                }
1289                nullResult = kFALSE;         
1290             }
1291             if (ncount == gMaxEntries) {
1292                Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1293                if (fNrunsPerMaster > 1) {
1294                   Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !", 
1295                           file.Data(),gMaxEntries);
1296                   return kFALSE;
1297                }           
1298                cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1299                if (!cbase) cbase = cadd;
1300                else {
1301                   cbase->Add(cadd);
1302                   delete cadd;
1303                }   
1304                nstart += ncount;
1305             } else {
1306                if (cbase && fNrunsPerMaster<2) {
1307                   cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1308                   printf("... please wait - TAlienCollection::Add() scales badly...\n");
1309                   cbase->Add(cadd);
1310                   delete cadd;
1311                   cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1312                   delete cbase; cbase = 0;               
1313                } else {
1314                   TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1315                }
1316                gSystem->Exec("rm -f __tmp*");   
1317                Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1318                break;
1319             }
1320          }   
1321          if (TestBit(AliAnalysisGrid::kTest)) break;
1322          // Check if there is one run per master job.
1323          if (fNrunsPerMaster<2) {
1324             if (FileExists(file)) {
1325                if (fOverwriteMode) gGrid->Rm(file);
1326                else {
1327                   Info("CreateDataset", "\n#####   Dataset %s exist. Skipping creation...", file.Data());
1328                   continue;
1329                }   
1330             }        
1331             // Copy xml file to alien space
1332             TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1333             if (!FileExists(file)) {
1334                Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1335                delete arr;
1336                return kFALSE;
1337             }
1338          } else {
1339             nruns++;
1340             if (((nruns-1)%fNrunsPerMaster) == 0) {
1341                schunk = os->GetString();
1342                cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1343             } else {
1344                cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1345                printf("   Merging collection <%s> into masterjob input...\n", file.Data());
1346                cbase->Add(cadd);
1347                delete cadd;
1348             }
1349             if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
1350                continue;
1351             }   
1352             schunk += Form("_%s.xml", os->GetString().Data());
1353             if (FileExists(schunk)) {               
1354                if (fOverwriteMode) gGrid->Rm(file);
1355                else {
1356                   Info("CreateDataset", "\n#####   Dataset %s exist. Skipping creation...", schunk.Data());
1357                   continue;
1358                }   
1359             }        
1360             printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
1361             cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1362             TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1363             if (!FileExists(schunk)) {
1364                Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1365                delete arr;
1366                return kFALSE;
1367             }
1368          }
1369       }   
1370       delete arr;
1371       if (nullResult) {
1372          Error("CreateDataset", "No valid dataset corresponding to the query!");
1373          return kFALSE;
1374       }
1375    } else {
1376       // Process a full run range.
1377       for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1378          format = Form("%%s/%s ", fRunPrefix.Data());
1379          nstart = 0;
1380          stage = 0;
1381          path = Form(format.Data(), fGridDataDir.Data(), irun);
1382          if (!DirectoryExists(path)) continue;
1383 //         CdWork();
1384          format = Form("%s.xml", fRunPrefix.Data());
1385          if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
1386          else file = Form(format.Data(), irun);
1387          if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {         
1388             if (fOverwriteMode) gGrid->Rm(file);
1389             else {
1390                Info("CreateDataset", "\n#####   Dataset %s exist. Skipping creation...", file.Data());
1391                continue;
1392             }   
1393          }
1394          // If local collection file does not exist, create it via 'find' command.
1395          while (1) {
1396             ncount = 0;
1397             stage++;
1398             if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1399                command = "find ";
1400                command +=  Form("%s -o %d ",options.Data(), nstart);
1401                command += path;
1402                command += pattern;
1403                command += conditions;
1404                TGridResult *res = gGrid->Command(command);
1405                if (res) delete res;
1406                // Write standard output to file
1407                gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1408                Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1409                Bool_t nullFile = kFALSE;
1410                if (!hasGrep) {
1411                   Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1412                } else {
1413                   nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1414                   if (nullFile) {
1415                      Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1416                      gSystem->Exec("rm -f __tmp*");
1417                      break;
1418                   }   
1419                   TString line;
1420                   ifstream in;
1421                   in.open("__tmp__");
1422                   in >> line;
1423                   in.close();
1424                   gSystem->Exec("rm -f __tmp__");   
1425                   ncount = line.Atoi();
1426                }
1427                nullResult = kFALSE;         
1428             }   
1429             if (ncount == gMaxEntries) {
1430                Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1431                if (fNrunsPerMaster > 1) {
1432                   Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !", 
1433                           file.Data(),gMaxEntries);
1434                   return kFALSE;
1435                }           
1436                cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1437                if (!cbase) cbase = cadd;
1438                else {
1439                   cbase->Add(cadd);
1440                   delete cadd;
1441                }   
1442                nstart += ncount;
1443             } else {
1444                if (cbase && fNrunsPerMaster<2) {
1445                   cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1446                   printf("... please wait - TAlienCollection::Add() scales badly...\n");
1447                   cbase->Add(cadd);
1448                   delete cadd;
1449                   cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1450                   delete cbase; cbase = 0;               
1451                } else {
1452                   TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1453                }
1454                Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1455                break;
1456             }
1457          }   
1458          if (TestBit(AliAnalysisGrid::kTest)) break;
1459          // Check if there is one run per master job.
1460          if (fNrunsPerMaster<2) {
1461             if (FileExists(file)) {
1462                if (fOverwriteMode) gGrid->Rm(file);
1463                else {
1464                   Info("CreateDataset", "\n#####   Dataset %s exist. Skipping creation...", file.Data());
1465                   continue;
1466                }   
1467             }        
1468             // Copy xml file to alien space
1469             TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1470             if (!FileExists(file)) {
1471                Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1472                return kFALSE;
1473             }
1474          } else {
1475             nruns++;
1476             // Check if the collection for the chunk exist locally.
1477             Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1478             if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1479                if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1480                else continue;
1481             }   
1482             printf("   Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1483             if (((nruns-1)%fNrunsPerMaster) == 0) {
1484                schunk = Form(fRunPrefix.Data(), irun);
1485                cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1486             } else {
1487                cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1488                cbase->Add(cadd);
1489                delete cadd;
1490             }
1491             format = Form("%%s_%s.xml", fRunPrefix.Data());
1492             schunk2 = Form(format.Data(), schunk.Data(), irun);
1493             if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1494                continue;
1495             }   
1496             schunk = schunk2;
1497             if (FileExists(schunk)) {
1498                if (fOverwriteMode) gGrid->Rm(schunk);
1499                else {
1500                   Info("CreateDataset", "\n#####   Dataset %s exist. Skipping creation...", schunk.Data());
1501                   continue;
1502                }   
1503             }        
1504             printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1505             cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1506             if (FileExists(schunk)) {
1507                if (fOverwriteMode) gGrid->Rm(schunk);
1508                else {
1509                   Info("CreateDataset", "\n#####   Dataset %s exist. Skipping copy...", schunk.Data());
1510                   continue;
1511                }   
1512             }   
1513             TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1514             if (!FileExists(schunk)) {
1515                Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1516                return kFALSE;
1517             }
1518          }   
1519       }
1520       if (nullResult) {
1521          Error("CreateDataset", "No valid dataset corresponding to the query!");
1522          return kFALSE;
1523       }      
1524    }      
1525    return kTRUE;
1526 }
1527
1528 //______________________________________________________________________________
1529 Bool_t AliAnalysisAlien::CreateJDL()
1530 {
1531 // Generate a JDL file according to current settings. The name of the file is 
1532 // specified by fJDLName.
1533    Bool_t error = kFALSE;
1534    TObjArray *arr = 0;
1535    Bool_t copy = kTRUE;
1536    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1537    Bool_t generate = kTRUE;
1538    if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1539    if (!Connect()) {
1540       Error("CreateJDL", "Alien connection required");
1541       return kFALSE;
1542    }   
1543    // Check validity of alien workspace
1544    TString workdir;
1545    if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1546    if (!fProductionMode &&  !TestBit(AliAnalysisGrid::kTest)) CdWork();
1547    workdir += fGridWorkingDir;
1548    if (generate) {
1549       TObjString *os;
1550       if (!fInputFiles) {
1551          Error("CreateJDL()", "Define some input files for your analysis.");
1552          error = kTRUE;
1553       }
1554       // Compose list of input files   
1555       // Check if output files were defined
1556       if (!fOutputFiles.Length()) {
1557          Error("CreateJDL", "You must define at least one output file");
1558          error = kTRUE;
1559       }   
1560       // Check if an output directory was defined and valid
1561       if (!fGridOutputDir.Length()) {
1562          Error("CreateJDL", "You must define AliEn output directory");
1563          error = kTRUE;
1564       } else {
1565          if (!fProductionMode) {
1566             if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1567             if (!DirectoryExists(fGridOutputDir)) {
1568                if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1569                   Info("CreateJDL", "\n#####   Created alien output directory %s", fGridOutputDir.Data());
1570                } else {
1571                   Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1572                   // error = kTRUE;
1573                }
1574             } else {
1575                Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1576             }   
1577             gGrid->Cd(workdir);
1578          }   
1579       }   
1580       // Exit if any error up to now
1581       if (error) return kFALSE;   
1582       // Set JDL fields
1583       if (!fUser.IsNull()) {
1584          fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1585          fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1586       }   
1587       fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1588       TString mergeExec = fExecutable;
1589       mergeExec.ReplaceAll(".sh", "_merge.sh");
1590       fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1591       mergeExec.ReplaceAll(".sh", ".C");
1592       fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1593       if (!fArguments.IsNull())
1594          fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1595       if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1596       else {
1597          if (fProductionMode)  fMergingJDL->SetArguments("wn.xml $4");    // xml, stage
1598          else                  fMergingJDL->SetArguments("wn.xml $2");    // xml, stage
1599      }               
1600
1601       fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1602       fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1603       fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1604       fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1605         
1606       if (fMaxInitFailed > 0) {
1607          fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1608          fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1609       }   
1610       if (fSplitMaxInputFileNumber > 0) {
1611          fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1612          fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1613       }
1614       if (!IsOneStageMerging()) {
1615          fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1616          fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1617       }   
1618       if (fSplitMode.Length()) {
1619          fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1620          fGridJDL->SetDescription("Split", "We split per SE or file");
1621       }
1622       fMergingJDL->SetValue("Split", "\"se\""); 
1623       fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1624       if (!fAliROOTVersion.IsNull()) {
1625          fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1626          fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1627       }   
1628       if (!fROOTVersion.IsNull()) {
1629          fGridJDL->AddToPackages("ROOT", fROOTVersion);
1630          fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1631       }   
1632       if (!fAPIVersion.IsNull()) {
1633          fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1634          fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1635       }   
1636       if (!fExternalPackages.IsNull()) {
1637          arr = fExternalPackages.Tokenize(" ");
1638          TIter next(arr);
1639          while ((os=(TObjString*)next())) {
1640             TString pkgname = os->GetString();
1641             Int_t index = pkgname.Index("::");
1642             TString pkgversion = pkgname(index+2, pkgname.Length());
1643             pkgname.Remove(index);
1644             fGridJDL->AddToPackages(pkgname, pkgversion);
1645             fMergingJDL->AddToPackages(pkgname, pkgversion);
1646          }   
1647          delete arr;   
1648       }   
1649       fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1650       fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1651       fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1652       fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1653       fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1654       TString analysisFile = fExecutable;
1655       analysisFile.ReplaceAll(".sh", ".root");
1656       fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1657       fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1658       if (fAdditionalLibs.Length()) {
1659          arr = fAdditionalLibs.Tokenize(" ");
1660          TIter next(arr);
1661          while ((os=(TObjString*)next())) {
1662             if (os->GetString().Contains(".so")) continue;
1663             fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1664             fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1665          }   
1666          delete arr;   
1667       }
1668       if (fPackages) {
1669          TIter next(fPackages);
1670          TObject *obj;
1671          while ((obj=next())) {
1672             fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1673             fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1674          }
1675       }
1676       if (fOutputArchive.Length()) {
1677          arr = fOutputArchive.Tokenize(" ");
1678          TIter next(arr);
1679          Bool_t first = kTRUE;
1680          const char *comment = "Files to be archived";
1681          const char *comment1 = comment;
1682          while ((os=(TObjString*)next())) {
1683             if (!first) comment = NULL;
1684             if (!os->GetString().Contains("@") && fCloseSE.Length())
1685                fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment); 
1686             else
1687                fGridJDL->AddToOutputArchive(os->GetString(), comment);
1688             first = kFALSE;   
1689          }      
1690          delete arr;
1691          // Output archive for the merging jdl
1692          TString outputArchive;
1693          if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1694             outputArchive = "log_archive.zip:std*@disk=1 ";
1695             // Add normal output files, extra files + terminate files
1696             TString files = GetListOfFiles("outextter");
1697             // Do not register files in fRegisterExcludes
1698             if (!fRegisterExcludes.IsNull()) {
1699                arr = fRegisterExcludes.Tokenize(" ");
1700                TIter next1(arr);
1701                while ((os=(TObjString*)next1())) {
1702                   files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1703                   files.ReplaceAll(os->GetString(),"");
1704                }   
1705                delete arr;
1706             }
1707             files.ReplaceAll(".root", "*.root");
1708             outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1709          } else {
1710             TString files = fOutputArchive;
1711             files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1712             outputArchive = files;
1713          }   
1714          arr = outputArchive.Tokenize(" ");
1715          TIter next2(arr);
1716          comment = comment1;
1717          first = kTRUE;
1718          while ((os=(TObjString*)next2())) {
1719             if (!first) comment = NULL;
1720             TString currentfile = os->GetString();
1721             if (!currentfile.Contains("@") && fCloseSE.Length())
1722                fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1723             else
1724                fMergingJDL->AddToOutputArchive(currentfile, comment);
1725             first = kFALSE;   
1726          }      
1727          delete arr;         
1728       }      
1729       arr = fOutputFiles.Tokenize(",");
1730       TIter next(arr);
1731       Bool_t first = kTRUE;
1732       const char *comment = "Files to be saved";
1733       while ((os=(TObjString*)next())) {
1734          // Ignore ouputs in jdl that are also in outputarchive
1735          TString sout = os->GetString();
1736          sout.ReplaceAll("*", "");
1737          sout.ReplaceAll(".root", "");
1738          if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1739          if (fOutputArchive.Contains(sout)) continue;
1740          // Ignore fRegisterExcludes
1741          if (fRegisterExcludes.Contains(sout)) continue;
1742          if (!first) comment = NULL;
1743          if (!os->GetString().Contains("@") && fCloseSE.Length())
1744             fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment); 
1745          else
1746             fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1747          first = kFALSE;
1748          if (fMergeExcludes.Contains(sout)) continue;   
1749          if (!os->GetString().Contains("@") && fCloseSE.Length())
1750             fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment); 
1751          else
1752             fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1753       }   
1754       delete arr;
1755       fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1756       fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1757       TString validationScript = fValidationScript;
1758       fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1759       validationScript.ReplaceAll(".sh", "_merge.sh");
1760       fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1761       if (fMasterResubmitThreshold) {
1762          fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1763          fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1764       }   
1765       // Write a jdl with 2 input parameters: collection name and output dir name.
1766       WriteJDL(copy);
1767    }
1768    // Copy jdl to grid workspace   
1769    if (copy) {
1770       // Check if an output directory was defined and valid
1771       if (!fGridOutputDir.Length()) {
1772          Error("CreateJDL", "You must define AliEn output directory");
1773          return kFALSE;
1774       } else {
1775          if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1776          if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1777             if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1778                Info("CreateJDL", "\n#####   Created alien output directory %s", fGridOutputDir.Data());
1779             } else {
1780                Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1781                return kFALSE;
1782             }
1783          }
1784          gGrid->Cd(workdir);
1785       }   
1786       if (TestBit(AliAnalysisGrid::kSubmit)) {
1787          TString mergeJDLName = fExecutable;
1788          mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1789          TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1790          TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1791          if (fProductionMode) {
1792             locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1793             locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1794          }   
1795          if (FileExists(locjdl)) gGrid->Rm(locjdl);
1796          if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1797          Info("CreateJDL", "\n#####   Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1798          if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl)) 
1799             Fatal("","Terminating");
1800 //         TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1801          if (fMergeViaJDL) {
1802             Info("CreateJDL", "\n#####   Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1803 //            TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1804             if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1)) 
1805                Fatal("","Terminating");
1806          }   
1807       }
1808       if (fAdditionalLibs.Length()) {
1809          arr = fAdditionalLibs.Tokenize(" ");
1810          TObjString *os;
1811          TIter next(arr);
1812          while ((os=(TObjString*)next())) {
1813             if (os->GetString().Contains(".so")) continue;
1814             Info("CreateJDL", "\n#####   Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1815             if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1816 //            TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1817             if (!copyLocal2Alien("CreateJDL", os->GetString().Data(), 
1818                 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1819               Fatal("","Terminating");
1820          }   
1821          delete arr;   
1822       }
1823       if (fPackages) {
1824          TIter next(fPackages);
1825          TObject *obj;
1826          while ((obj=next())) {
1827             if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1828             Info("CreateJDL", "\n#####   Copying dependency: <%s> to your alien workspace", obj->GetName());
1829 //            TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1830             if (!copyLocal2Alien("CreateJDL",obj->GetName(), 
1831                 Form("%s/%s", workdir.Data(), obj->GetName()))) 
1832               Fatal("","Terminating"); 
1833          }   
1834       }      
1835    } 
1836    return kTRUE;
1837 }
1838
1839 //______________________________________________________________________________
1840 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1841 {
1842 // Writes one or more JDL's corresponding to findex. If findex is negative,
1843 // all run numbers are considered in one go (jdl). For non-negative indices
1844 // they correspond to the indices in the array fInputFiles.
1845    if (!fInputFiles) return kFALSE;
1846    TObject *os;
1847    TString workdir;
1848    if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1849    workdir += fGridWorkingDir;
1850    TString stageName = "$2";
1851    if (fProductionMode) stageName = "$4";
1852    if (!fMergeDirName.IsNull()) {
1853      fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1854      fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1855    } else {
1856      fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1857      fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1858    }
1859    if (fProductionMode) {
1860       TIter next(fInputFiles);
1861       while ((os=next())) {
1862          fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1863       }
1864       if (!fOutputToRunNo)
1865          fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1866       else  
1867          fGridJDL->SetOutputDirectory(fGridOutputDir);
1868    } else {            
1869       if (!fRunNumbers.Length() && !fRunRange[0]) {
1870          // One jdl with no parameters in case input data is specified by name.
1871          TIter next(fInputFiles);
1872          while ((os=next()))
1873             fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1874          if (!fOutputSingle.IsNull())
1875             fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1876          else {
1877             fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1878             fMergingJDL->SetOutputDirectory(fGridOutputDir);         
1879          }   
1880       } else {
1881          // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1882          fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1883          if (!fOutputSingle.IsNull()) {
1884             if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1885             else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1886          } else {   
1887             fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1888          }   
1889       }
1890    }
1891       
1892    // Generate the JDL as a string
1893    TString sjdl = fGridJDL->Generate();
1894    TString sjdl1 = fMergingJDL->Generate();
1895    // Final merge jdl
1896    if (!fMergeDirName.IsNull()) {
1897      fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1898      fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1899    } else {  
1900      fMergingJDL->SetOutputDirectory("$1", "Output directory");
1901      fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1902    }  
1903    TString sjdl2 = fMergingJDL->Generate();
1904    Int_t index, index1;
1905    sjdl.ReplaceAll("\"LF:", "\n   \"LF:");
1906    sjdl.ReplaceAll("(member", "\n   (member");
1907    sjdl.ReplaceAll("\",\"VO_", "\",\n   \"VO_");
1908    sjdl.ReplaceAll("{", "{\n   ");
1909    sjdl.ReplaceAll("};", "\n};");
1910    sjdl.ReplaceAll("{\n   \n", "{\n");
1911    sjdl.ReplaceAll("\n\n", "\n");
1912    sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1913    sjdl1.ReplaceAll("\"LF:", "\n   \"LF:");
1914    sjdl1.ReplaceAll("(member", "\n   (member");
1915    sjdl1.ReplaceAll("\",\"VO_", "\",\n   \"VO_");
1916    sjdl1.ReplaceAll("{", "{\n   ");
1917    sjdl1.ReplaceAll("};", "\n};");
1918    sjdl1.ReplaceAll("{\n   \n", "{\n");
1919    sjdl1.ReplaceAll("\n\n", "\n");
1920    sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1921    sjdl2.ReplaceAll("\"LF:", "\n   \"LF:");
1922    sjdl2.ReplaceAll("(member", "\n   (member");
1923    sjdl2.ReplaceAll("\",\"VO_", "\",\n   \"VO_");
1924    sjdl2.ReplaceAll("{", "{\n   ");
1925    sjdl2.ReplaceAll("};", "\n};");
1926    sjdl2.ReplaceAll("{\n   \n", "{\n");
1927    sjdl2.ReplaceAll("\n\n", "\n");
1928    sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1929    sjdl += "JDLVariables = \n{\n   \"Packages\",\n   \"OutputDir\"\n};\n";
1930    sjdl.Prepend(Form("Jobtag = {\n   \"comment:%s\"\n};\n", fJobTag.Data()));
1931    index = sjdl.Index("JDLVariables");
1932    if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1933    sjdl += "Workdirectorysize = {\"5000MB\"};";
1934    sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1935    sjdl1 += "JDLVariables = \n{\n   \"Packages\",\n   \"OutputDir\"\n};\n";
1936    index = fJobTag.Index(":");
1937    if (index < 0) index = fJobTag.Length();
1938    TString jobTag = fJobTag;
1939    if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1940    sjdl1.Prepend(Form("Jobtag = {\n   \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1941    if (fProductionMode) {   
1942      sjdl1.Prepend("# Generated merging jdl (production mode) \
1943                     \n# $1 = full alien path to output directory to be merged \
1944                     \n# $2 = train number \
1945                     \n# $3 = production (like LHC10b) \
1946                     \n# $4 = merging stage \
1947                     \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1948      sjdl2.Prepend(Form("Jobtag = {\n   \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1949      sjdl2.Prepend("# Generated merging jdl \
1950                     \n# $1 = full alien path to output directory to be merged \
1951                     \n# $2 = train number \
1952                     \n# $3 = production (like LHC10b) \
1953                     \n# $4 = merging stage \
1954                     \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1955    } else {
1956      sjdl1.Prepend("# Generated merging jdl \
1957                     \n# $1 = full alien path to output directory to be merged \
1958                     \n# $2 = merging stage \
1959                     \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1960      sjdl2.Prepend(Form("Jobtag = {\n   \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1961      sjdl2.Prepend("# Generated merging jdl \
1962                     \n# $1 = full alien path to output directory to be merged \
1963                     \n# $2 = merging stage \
1964                     \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1965    }
1966    index = sjdl1.Index("JDLVariables");
1967    if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1968    index = sjdl2.Index("JDLVariables");
1969    if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1970    sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1971    sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1972    index = sjdl2.Index("Split =");
1973    if (index>=0) {
1974       index1 = sjdl2.Index("\n", index);
1975       sjdl2.Remove(index, index1-index+1);
1976    }
1977    index = sjdl2.Index("SplitMaxInputFileNumber");
1978    if (index>=0) {
1979       index1 = sjdl2.Index("\n", index);
1980       sjdl2.Remove(index, index1-index+1);
1981    }
1982    index = sjdl2.Index("InputDataCollection");
1983    if (index>=0) {
1984       index1 = sjdl2.Index(";", index);
1985       sjdl2.Remove(index, index1-index+1);
1986    }
1987    index = sjdl2.Index("InputDataListFormat");
1988    if (index>=0) {
1989       index1 = sjdl2.Index("\n", index);
1990       sjdl2.Remove(index, index1-index+1);
1991    }
1992    index = sjdl2.Index("InputDataList");
1993    if (index>=0) {
1994       index1 = sjdl2.Index("\n", index);
1995       sjdl2.Remove(index, index1-index+1);
1996    }
1997    sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1998    // Write jdl to file
1999    ofstream out;
2000    out.open(fJDLName.Data(), ios::out);
2001    if (out.bad()) {
2002       Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
2003       return kFALSE;
2004    }
2005    out << sjdl << endl;
2006    out.close();
2007    TString mergeJDLName = fExecutable;
2008    mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2009    if (fMergeViaJDL) {
2010       ofstream out1;
2011       out1.open(mergeJDLName.Data(), ios::out);
2012       if (out1.bad()) {
2013          Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
2014          return kFALSE;
2015       }
2016       out1 << sjdl1 << endl;
2017       out1.close();
2018       ofstream out2;
2019       TString finalJDL = mergeJDLName;
2020       finalJDL.ReplaceAll(".jdl", "_final.jdl");
2021       out2.open(finalJDL.Data(), ios::out);
2022       if (out2.bad()) {
2023          Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
2024          return kFALSE;
2025       }
2026       out2 << sjdl2 << endl;
2027       out2.close();
2028    }   
2029
2030    // Copy jdl to grid workspace   
2031    if (!copy) {
2032       Info("WriteJDL", "\n#####   You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
2033    } else {
2034       TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
2035       TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
2036       TString finalJDL = mergeJDLName;
2037       finalJDL.ReplaceAll(".jdl", "_final.jdl");
2038       TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
2039       if (fProductionMode) {
2040          locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2041          locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
2042          locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
2043       }   
2044       if (FileExists(locjdl)) gGrid->Rm(locjdl);
2045       if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
2046       if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
2047       Info("WriteJDL", "\n#####   Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
2048 //      TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
2049       if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data())) 
2050          Fatal("","Terminating");
2051       if (fMergeViaJDL) {
2052          Info("WriteJDL", "\n#####   Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
2053 //         TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
2054 //         TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
2055          if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
2056             Fatal("","Terminating");
2057          if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
2058            Fatal("","Terminating");
2059       }   
2060    } 
2061    return kTRUE;
2062 }
2063
2064 //______________________________________________________________________________
2065 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
2066 {
2067 // Returns true if file exists.
2068    if (!gGrid) return kFALSE;
2069    TString slfn = lfn;
2070    slfn.ReplaceAll("alien://","");
2071    TGridResult *res = gGrid->Ls(slfn);
2072    if (!res) return kFALSE;
2073    TMap *map = dynamic_cast<TMap*>(res->At(0));
2074    if (!map) {
2075       delete res;
2076       return kFALSE;
2077    }   
2078    TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
2079    if (!objs || !objs->GetString().Length()) {
2080       delete res;
2081       return kFALSE;
2082    }
2083    delete res;   
2084    return kTRUE;
2085 }
2086
2087 //______________________________________________________________________________
2088 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
2089 {
2090 // Returns true if directory exists. Can be also a path.
2091    if (!gGrid) return kFALSE;
2092    // Check if dirname is a path
2093    TString dirstripped = dirname;
2094    dirstripped = dirstripped.Strip();
2095    dirstripped = dirstripped.Strip(TString::kTrailing, '/');
2096    TString dir = gSystem->BaseName(dirstripped);
2097    dir += "/";
2098    TString path = gSystem->DirName(dirstripped);
2099    TGridResult *res = gGrid->Ls(path, "-F");
2100    if (!res) return kFALSE;
2101    TIter next(res);
2102    TMap *map;
2103    TObject *obj;
2104    while ((map=dynamic_cast<TMap*>(next()))) {
2105       obj = map->GetValue("name");
2106       if (!obj) break;
2107       if (dir == obj->GetName()) {
2108          delete res;
2109          return kTRUE;
2110       }
2111    }
2112    delete res;
2113    return kFALSE;
2114 }      
2115
2116 //______________________________________________________________________________
2117 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
2118 {
2119 // Check input data type.
2120    isCollection = kFALSE;
2121    isXml = kFALSE;
2122    useTags = kFALSE;
2123    if (!gGrid) {
2124       Error("CheckDataType", "No connection to grid");
2125       return;
2126    }
2127    isCollection = IsCollection(lfn);
2128    TString msg = "\n#####   file: ";
2129    msg += lfn;
2130    if (isCollection) {
2131       msg += " type: raw_collection;";
2132    // special treatment for collections
2133       isXml = kFALSE;
2134       // check for tag files in the collection
2135       TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
2136       if (!res) {
2137          msg += " using_tags: No (unknown)";
2138          Info("CheckDataType", "%s", msg.Data());
2139          return;
2140       }   
2141       const char* typeStr = res->GetKey(0, "origLFN");
2142       if (!typeStr || !strlen(typeStr)) {
2143          msg += " using_tags: No (unknown)";
2144          Info("CheckDataType", "%s", msg.Data());
2145          return;
2146       }   
2147       TString file = typeStr;
2148       useTags = file.Contains(".tag");
2149       if (useTags) msg += " using_tags: Yes";
2150       else          msg += " using_tags: No";
2151       Info("CheckDataType", "%s", msg.Data());
2152       return;
2153    }
2154    TString slfn(lfn);
2155    slfn.ToLower();
2156    isXml = slfn.Contains(".xml");
2157    if (isXml) {
2158    // Open xml collection and check if there are tag files inside
2159       msg += " type: xml_collection;";
2160       TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
2161       if (!coll) {
2162          msg += " using_tags: No (unknown)";
2163          Info("CheckDataType", "%s", msg.Data());
2164          return;
2165       }   
2166       TMap *map = coll->Next();
2167       if (!map) {
2168          msg += " using_tags: No (unknown)";
2169          Info("CheckDataType", "%s", msg.Data());
2170          return;
2171       }   
2172       map = (TMap*)map->GetValue("");
2173       TString file;
2174       if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
2175       useTags = file.Contains(".tag");
2176       delete coll;
2177       if (useTags) msg += " using_tags: Yes";
2178       else          msg += " using_tags: No";
2179       Info("CheckDataType", "%s", msg.Data());
2180       return;
2181    }
2182    useTags = slfn.Contains(".tag");
2183    if (slfn.Contains(".root")) msg += " type: root file;";
2184    else                        msg += " type: unknown file;";
2185    if (useTags) msg += " using_tags: Yes";
2186    else          msg += " using_tags: No";
2187    Info("CheckDataType", "%s", msg.Data());
2188 }
2189
2190 //______________________________________________________________________________
2191 void AliAnalysisAlien::EnablePackage(const char *package)
2192 {
2193 // Enables a par file supposed to exist in the current directory.
2194    TString pkg(package);
2195    pkg.ReplaceAll(".par", "");
2196    pkg += ".par";
2197    if (gSystem->AccessPathName(pkg)) {
2198       Fatal("EnablePackage", "Package %s not found", pkg.Data());
2199       return;
2200    }
2201    if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
2202       Info("EnablePackage", "AliEn plugin will use .par packages");
2203    TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
2204    if (!fPackages) {
2205       fPackages = new TObjArray();
2206       fPackages->SetOwner();
2207    }
2208    fPackages->Add(new TObjString(pkg));
2209 }      
2210
2211 //______________________________________________________________________________
2212 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
2213 {
2214 // Make a tree from files having the location specified in fFileForTestMode. 
2215 // Inspired from JF's CreateESDChain.
2216    if (fFileForTestMode.IsNull()) {
2217       Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2218       return NULL;
2219    }
2220    if (gSystem->AccessPathName(fFileForTestMode)) {
2221       Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2222       return NULL;
2223    }   
2224    // Open the file
2225    ifstream in;
2226    in.open(fFileForTestMode);
2227    Int_t count = 0;
2228     // Read the input list of files and add them to the chain
2229    TString line;
2230    TChain *chain = new TChain(treeName);
2231    TChain *chainFriend = 0;
2232    if (!fFriendChainName.IsNull()) chainFriend = new TChain(treeName);       
2233    while (in.good())
2234    {
2235       in >> line;
2236       if (line.IsNull()) continue;
2237       if (count++ == fNtestFiles) break;
2238       TString esdFile(line);
2239       TFile *file = TFile::Open(esdFile);
2240       if (file && !file->IsZombie()) {
2241          chain->Add(esdFile);
2242          file->Close();
2243          if (!fFriendChainName.IsNull()) {
2244             esdFile.ReplaceAll("AliAOD.root", fFriendChainName.Data());
2245             esdFile.ReplaceAll("AliAODs.root", fFriendChainName.Data());
2246             file = TFile::Open(esdFile);
2247             if (file && !file->IsZombie()) {
2248                file->Close();
2249                chainFriend->Add(esdFile);
2250             } else {
2251                Fatal("GetChainForTestMode", "Cannot open friend file: %s", esdFile.Data());
2252                return 0;
2253             }   
2254          }   
2255       } else {
2256          Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
2257       }   
2258    }
2259    in.close();
2260    if (!chain->GetListOfFiles()->GetEntries()) {
2261        Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
2262        delete chain;
2263        delete chainFriend;
2264        return NULL;
2265    }
2266 //    chain->ls();
2267    if (!fFriendChainName.IsNull()) chain->AddFriend(chainFriend);
2268    return chain;
2269 }    
2270
2271 //______________________________________________________________________________
2272 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
2273 {
2274 // Get job status for all jobs with jobid>jobidstart.
2275    static char mstatus[20];
2276    mstatus[0] = '\0';
2277    nrunning = 0;
2278    nwaiting = 0;
2279    nerror   = 0;
2280    ndone    = 0;
2281    TGridJobStatusList *list = gGrid->Ps("");
2282    if (!list) return mstatus;
2283    Int_t nentries = list->GetSize();
2284    TGridJobStatus *status;
2285    Int_t pid;
2286    for (Int_t ijob=0; ijob<nentries; ijob++) {
2287       status = (TGridJobStatus *)list->At(ijob);
2288       pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
2289       if (pid<jobidstart) continue;
2290       if (pid == lastid) {
2291          gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
2292       }   
2293       switch (status->GetStatus()) {
2294          case TGridJobStatus::kWAITING:
2295             nwaiting++; break;
2296          case TGridJobStatus::kRUNNING:
2297             nrunning++; break;
2298          case TGridJobStatus::kABORTED:
2299          case TGridJobStatus::kFAIL:
2300          case TGridJobStatus::kUNKNOWN:
2301             nerror++; break;
2302          case TGridJobStatus::kDONE:
2303             ndone++;
2304       }
2305    }
2306    list->Delete();
2307    delete list;
2308    return mstatus;
2309 }
2310
2311 //______________________________________________________________________________
2312 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
2313 {
2314 // Returns true if file is a collection. Functionality duplicated from
2315 // TAlien::Type() because we don't want to directly depend on TAlien.
2316    if (!gGrid) {
2317       Error("IsCollection", "No connection to grid");
2318       return kFALSE;
2319    }
2320    TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
2321    if (!res) return kFALSE;
2322    const char* typeStr = res->GetKey(0, "type");
2323    if (!typeStr || !strlen(typeStr)) return kFALSE;
2324    if (!strcmp(typeStr, "collection")) return kTRUE;
2325    delete res;
2326    return kFALSE;
2327 }   
2328
2329 //______________________________________________________________________________
2330 Bool_t AliAnalysisAlien::IsSingleOutput() const
2331 {
2332 // Check if single-ouput option is on.
2333    return (!fOutputSingle.IsNull());
2334 }
2335    
2336 //______________________________________________________________________________
2337 void AliAnalysisAlien::Print(Option_t *) const
2338 {
2339 // Print current plugin settings.
2340    printf("### AliEn analysis plugin current settings ###\n");
2341    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2342    if (mgr && mgr->IsProofMode()) {
2343       TString proofType = "=   PLUGIN IN PROOF MODE ON CLUSTER:_________________";
2344       if (TestBit(AliAnalysisGrid::kTest))
2345          proofType = "=   PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
2346       printf("%s %s\n", proofType.Data(), fProofCluster.Data());
2347       if (!fProofDataSet.IsNull())
2348       printf("=   Requested data set:___________________________ %s\n", fProofDataSet.Data());
2349       if (fProofReset==1)
2350       printf("=   Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");      
2351       if (fProofReset>1)   
2352       printf("=   Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");      
2353       if (!fRootVersionForProof.IsNull())
2354       printf("=   ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
2355       else
2356       printf("=   ROOT version requested________________________ default\n");
2357       printf("=   AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
2358       if (!fAliRootMode.IsNull())
2359       printf("=   Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());  
2360       if (fNproofWorkers)
2361       printf("=   Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
2362       if  (fNproofWorkersPerSlave)
2363       printf("=   Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
2364       if (TestSpecialBit(kClearPackages))
2365       printf("=   ClearPackages requested...\n");
2366       if (fIncludePath.Data())
2367       printf("=   Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2368       printf("=   Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2369       if (fPackages && fPackages->GetEntries()) {
2370          TIter next(fPackages);
2371          TObject *obj;
2372          TString list;
2373          while ((obj=next())) list += obj->GetName();
2374          printf("=   Par files to be used: ________________________ %s\n", list.Data());
2375       } 
2376       if (TestSpecialBit(kProofConnectGrid))
2377       printf("=   Requested PROOF connection to grid\n");
2378       return;
2379    }
2380    printf("=   OverwriteMode:________________________________ %d\n", fOverwriteMode);
2381    if (fOverwriteMode) {
2382       printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
2383             \n*****       To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
2384    }
2385    printf("=   Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
2386    printf("=   Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
2387    printf("=   Production mode:______________________________ %d\n", fProductionMode);
2388    printf("=   Version of API requested: ____________________ %s\n", fAPIVersion.Data());
2389    printf("=   Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
2390    printf("=   Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
2391    if (fUser.Length()) 
2392    printf("=   User running the plugin: _____________________ %s\n", fUser.Data());
2393    printf("=   Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
2394    printf("=   Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
2395    printf("=   Data base directory path requested: __________ %s\n", fGridDataDir.Data());
2396    printf("=   Data search pattern: _________________________ %s\n", fDataPattern.Data());
2397    printf("=   Input data format: ___________________________ %s\n", fInputFormat.Data());
2398    if (fRunNumbers.Length()) 
2399    printf("=   Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
2400    if (fRunRange[0])
2401    printf("=   Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
2402    if (!fRunRange[0] && !fRunNumbers.Length()) {
2403       TIter next(fInputFiles);
2404       TObject *obj;
2405       TString list;
2406       while ((obj=next())) list += obj->GetName();
2407       printf("=   Input files to be processed: _________________ %s\n", list.Data());
2408    }
2409    if (TestBit(AliAnalysisGrid::kTest))
2410    printf("=   Number of input files used in test mode: _____ %d\n", fNtestFiles);
2411    printf("=   List of output files to be registered: _______ %s\n", fOutputFiles.Data());
2412    printf("=   List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
2413    printf("=   List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
2414    printf("=   List of outputs that should not be registered: %s\n", fRegisterExcludes.Data());
2415    printf("=   List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
2416    printf("=====================================================================\n");
2417    printf("=   Job price: ___________________________________ %d\n", fPrice);
2418    printf("=   Time to live (TTL): __________________________ %d\n", fTTL);
2419    printf("=   Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2420    if (fMaxInitFailed>0) 
2421    printf("=   Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2422    if (fMasterResubmitThreshold>0) 
2423    printf("=   Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2424    printf("=   Number of replicas for the output files_______ %d\n", fNreplicas);
2425    if (fNrunsPerMaster>0)
2426    printf("=   Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2427    printf("=   Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2428    printf("=   Name of the generated execution script: ______ %s\n", fExecutable.Data());
2429    printf("=   Executable command: __________________________ %s\n", fExecutableCommand.Data());
2430    if (fArguments.Length()) 
2431    printf("=   Arguments for the execution script: __________ %s\n",fArguments.Data());
2432    if (fExecutableArgs.Length()) 
2433    printf("=   Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2434    printf("=   Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2435    printf("=   User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2436    printf("=   Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2437    printf("=   Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2438    if (fDatasetName)
2439    printf("=   Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2440    printf("=   Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2441    if (fIncludePath.Data())
2442    printf("=   Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2443    if (fCloseSE.Length())
2444    printf("=   Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2445    if (fFriendChainName.Length())
2446    printf("=   Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2447    if (fPackages && fPackages->GetEntries()) {
2448       TIter next(fPackages);
2449       TObject *obj;
2450       TString list;
2451       while ((obj=next())) list += obj->GetName();
2452       printf("=   Par files to be used: ________________________ %s\n", list.Data());
2453    }   
2454 }
2455
2456 //______________________________________________________________________________
2457 void AliAnalysisAlien::SetDefaults()
2458 {
2459 // Set default values for everything. What cannot be filled will be left empty.
2460    if (fGridJDL) delete fGridJDL;
2461    fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2462    fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2463    fPrice                      = 1;
2464    fTTL                        = 30000;
2465    fSplitMaxInputFileNumber    = 100;
2466    fMaxInitFailed              = 0;
2467    fMasterResubmitThreshold    = 0;
2468    fNtestFiles                 = 10;
2469    fNreplicas                  = 2;
2470    fRunRange[0]                = 0;
2471    fRunRange[1]                = 0;
2472    fRunPrefix                  = "%d";
2473    fNrunsPerMaster             = 1;
2474    fMaxMergeFiles              = 100;
2475    fRunNumbers                 = "";
2476    fExecutable                 = "analysis.sh";
2477    fExecutableCommand          = "root -b -q";
2478    fArguments                  = "";
2479    fExecutableArgs             = "";
2480    fAnalysisMacro              = "myAnalysis.C";
2481    fAnalysisSource             = "";
2482    fAdditionalLibs             = "";
2483    fSplitMode                  = "se";
2484    fAPIVersion                 = "";
2485    fROOTVersion                = "";
2486    fAliROOTVersion             = "";
2487    fUser                       = "";  // Your alien user name
2488    fGridWorkingDir             = "";
2489    fGridDataDir                = "";  // Can be like: /alice/sim/PDC_08a/LHC08c9/
2490    fDataPattern                = "*AliESDs.root";  // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2491    fFriendChainName            = "";
2492    fGridOutputDir              = "output";
2493    fOutputArchive              = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2494    fOutputFiles                = "";  // Like "AliAODs.root histos.root"
2495    fInputFormat                = "xml-single";
2496    fJDLName                    = "analysis.jdl";
2497    fJobTag                     = "Automatically generated analysis JDL";
2498    fMergeExcludes              = "";
2499    fMergeViaJDL                = 0;
2500    SetUseCopy(kTRUE);
2501    SetCheckCopy(kTRUE);
2502    SetDefaultOutputs(kTRUE);
2503    fOverwriteMode              = 1;
2504 }   
2505
2506 //______________________________________________________________________________
2507 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2508 {
2509 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2510    // First check if the result is already in the output directory.
2511    if (FileExists(Form("%s/%s",aliendir,filename))) {
2512       printf("Final merged results found. Not merging again.\n");
2513       return kFALSE;
2514    }
2515    // Now check the last stage done.
2516    Int_t stage = 0;
2517    while (1) {
2518       if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2519       stage++;
2520    }
2521    // Next stage of merging
2522    stage++;
2523    TString pattern = "*root_archive.zip";
2524    if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2525    TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2526    if (res) delete res;
2527    // Write standard output to file
2528    gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2529    // Count the number of files inside
2530    ifstream ifile;
2531    ifile.open(Form("Stage_%d.xml",stage));
2532    if (!ifile.good()) {
2533       ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2534       return kFALSE;
2535    }   
2536    TString line;
2537    Int_t nfiles = 0;
2538    while (!ifile.eof()) {
2539       ifile >> line;
2540       if (line.Contains("/event")) nfiles++;
2541    }
2542    ifile.close();
2543    if (!nfiles) {
2544       ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2545       return kFALSE;
2546    } else {
2547       printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2548    }   
2549    // Copy the file in the output directory
2550    printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2551 //   TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2552    if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage), 
2553         Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2554    // Check if this is the last stage to be done.
2555    Bool_t laststage = (nfiles<nperchunk);
2556    if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2557    if (laststage) {
2558       printf("### Submiting final merging stage %d\n", stage);
2559       TString finalJDL = jdl;
2560       finalJDL.ReplaceAll(".jdl", "_final.jdl");
2561       TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2562       Int_t jobId = SubmitSingleJob(query);
2563       if (!jobId) return kFALSE;      
2564    } else {
2565       printf("### Submiting merging stage %d\n", stage);
2566       TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2567       Int_t jobId = SubmitSingleJob(query);
2568       if (!jobId) return kFALSE;           
2569    }
2570    return kTRUE;   
2571 }        
2572
2573 //______________________________________________________________________________
2574 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2575 {
2576 // Loat the analysis manager from a file.
2577    TFile *file = TFile::Open(fname);
2578    if (!file) {
2579       ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2580       return 0;
2581    }   
2582    TIter nextkey(file->GetListOfKeys());
2583    AliAnalysisManager *mgr = 0;
2584    TKey *key;
2585    while ((key=(TKey*)nextkey())) {
2586       if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2587          mgr = (AliAnalysisManager*)file->Get(key->GetName());
2588    }
2589    if (!mgr) 
2590       ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2591    return mgr;
2592 }      
2593
2594 //______________________________________________________________________________
2595 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2596 {
2597 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2598    if (!gGrid) return 0;
2599    printf("=> %s ------> ",query);
2600    TGridResult *res = gGrid->Command(query);
2601    if (!res) return 0;
2602    TString jobId = res->GetKey(0,"jobId");
2603    delete res;
2604    if (jobId.IsNull()) {
2605       printf("submission failed. Reason:\n");
2606       gGrid->Stdout();
2607       gGrid->Stderr();
2608       ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2609       return 0;
2610    }
2611    printf(" Job id: %s\n", jobId.Data());
2612    return atoi(jobId);
2613 }  
2614
2615 //______________________________________________________________________________
2616 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2617 {
2618 // Merge given output files from basedir. Basedir can be an alien output directory
2619 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2620 // files in a group (ignored for xml input). Merging can be done in stages:
2621 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2622 // stage=1 : works with an xml of all root_archive.zip in the output directory
2623 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2624    TString outputFile = output;
2625    TString command;
2626    TString outputChunk;
2627    TString previousChunk = "";
2628    TObjArray *listoffiles = new TObjArray();
2629 //   listoffiles->SetOwner();
2630    Int_t countChunk = 0;
2631    Int_t countZero = nmaxmerge;
2632    Bool_t merged = kTRUE;
2633    Int_t index = outputFile.Index("@");
2634    if (index > 0) outputFile.Remove(index);
2635    TString inputFile = outputFile;
2636    TString sbasedir = basedir;
2637    if (sbasedir.Contains(".xml")) {
2638       // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2639       nmaxmerge = 9999999;
2640       TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2641       if (!coll) {
2642          ::Error("MergeOutput", "Input XML collection empty.");
2643          return kFALSE;
2644       }
2645       // Iterate grid collection
2646       while (coll->Next()) {
2647          TString fname = gSystem->DirName(coll->GetTURL());
2648          fname += "/";
2649          fname += inputFile;      
2650          listoffiles->Add(new TNamed(fname.Data(),""));
2651       }   
2652    } else {   
2653       command = Form("find %s/ *%s", basedir, inputFile.Data());
2654       printf("command: %s\n", command.Data());
2655       TGridResult *res = gGrid->Command(command);
2656       if (!res) {
2657          ::Error("MergeOutput","No result for the find command\n");
2658          delete listoffiles;
2659          return kFALSE;
2660       }     
2661       TIter nextmap(res);
2662       TMap *map = 0;
2663       while ((map=(TMap*)nextmap())) {
2664          TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2665          if (!objs || !objs->GetString().Length()) {
2666             // Nothing found - skip this output
2667             delete res;
2668             delete listoffiles;
2669             return kFALSE;
2670          }
2671          listoffiles->Add(new TNamed(objs->GetName(),""));
2672       }
2673       delete res;
2674    }
2675    if (!listoffiles->GetEntries()) {
2676       ::Error("MergeOutput","No result for the find command\n");
2677       delete listoffiles;
2678       return kFALSE;
2679    }     
2680
2681    TFileMerger *fm = 0;
2682    TIter next0(listoffiles);
2683    TObjArray *listoffilestmp = new TObjArray();
2684    listoffilestmp->SetOwner();
2685    TObject *nextfile;
2686    TString snextfile;
2687    // Keep only the files at upper level
2688    Int_t countChar = 0;
2689    while ((nextfile=next0())) {
2690       snextfile = nextfile->GetName();
2691       Int_t crtCount = snextfile.CountChar('/');
2692       if (nextfile == listoffiles->First()) countChar = crtCount;
2693       if (crtCount < countChar) countChar = crtCount;
2694    }
2695    next0.Reset();
2696    while ((nextfile=next0())) {
2697       snextfile = nextfile->GetName();
2698       Int_t crtCount = snextfile.CountChar('/');
2699       if (crtCount > countChar) {
2700          delete nextfile;
2701          continue;
2702       }   
2703       listoffilestmp->Add(nextfile);
2704    }
2705    delete listoffiles;
2706    listoffiles = listoffilestmp;  // Now contains 'good' files
2707    listoffiles->Print();
2708    TIter next(listoffiles);   
2709    // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2710    outputChunk = outputFile;
2711    outputChunk.ReplaceAll(".root", "_*.root");
2712    // Check for existent temporary merge files
2713    // Check overwrite mode and remove previous partial results if needed
2714    // Preserve old merging functionality for stage 0.
2715    if (stage==0) {
2716       if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2717          while (1) {
2718             // Skip as many input files as in a chunk
2719             for (Int_t counter=0; counter<nmaxmerge; counter++) {
2720                nextfile = next();
2721                if (!nextfile) {
2722                   ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2723                   delete listoffiles;
2724                   return kFALSE;
2725                }   
2726                snextfile = nextfile->GetName();
2727             }
2728             outputChunk = outputFile;
2729             outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2730             countChunk++;
2731             if (gSystem->AccessPathName(outputChunk)) continue;
2732             // Merged file with chunks up to <countChunk> found
2733             ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2734             previousChunk = outputChunk;
2735             break;
2736          }
2737       }   
2738       countZero = nmaxmerge;
2739    
2740       while ((nextfile=next())) {
2741          snextfile = nextfile->GetName();
2742          // Loop 'find' results and get next LFN
2743          if (countZero == nmaxmerge) {
2744             // First file in chunk - create file merger and add previous chunk if any.
2745             fm = new TFileMerger(kTRUE);
2746             fm->SetFastMethod(kTRUE);
2747             if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2748             outputChunk = outputFile;
2749             outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2750          }
2751          // If last file found, put merged results in the output file
2752          if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2753          // Add file to be merged and decrement chunk counter.
2754          fm->AddFile(snextfile);
2755          countZero--;
2756          if (countZero==0 || nextfile == listoffiles->Last()) {            
2757             if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2758             // Nothing found - skip this output
2759                ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2760                merged = kFALSE;
2761                break;
2762             }
2763             fm->OutputFile(outputChunk);
2764             // Merge the outputs, then go to next chunk      
2765             if (!fm->Merge()) {
2766                ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2767                merged = kFALSE;
2768                break;
2769             } else {
2770                ::Info("MergeOutputs", "\n#####   Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2771                gSystem->Unlink(previousChunk);
2772             }
2773             if (nextfile == listoffiles->Last()) break;
2774             countChunk++;
2775             countZero = nmaxmerge;
2776             previousChunk = outputChunk;
2777          }
2778       }
2779       delete listoffiles;
2780       delete fm;
2781       return merged;
2782    }
2783    // Merging stage different than 0.
2784    // Move to the begining of the requested chunk.
2785    fm = new TFileMerger(kTRUE);
2786    fm->SetFastMethod(kTRUE);
2787    while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2788    delete listoffiles;
2789    if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2790       // Nothing found - skip this output
2791       ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2792       delete fm;
2793       return kFALSE;
2794    }
2795    fm->OutputFile(outputFile);
2796    // Merge the outputs
2797    if (!fm->Merge()) {
2798       ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2799       delete fm;
2800       return kFALSE;
2801    } else {
2802       ::Info("MergeOutput", "\n#####   Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2803    }
2804    delete fm;
2805    return kTRUE;
2806
2807
2808 //______________________________________________________________________________
2809 Bool_t AliAnalysisAlien::MergeOutputs()
2810 {
2811 // Merge analysis outputs existing in the AliEn space.
2812    if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2813    if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2814    if (!Connect()) {
2815       Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2816       return kFALSE;
2817    }
2818    if (fMergeViaJDL) {
2819       if (!TestBit(AliAnalysisGrid::kMerge)) {
2820          Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2821          return kFALSE; 
2822       }     
2823       if (fProductionMode) {
2824          Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2825          return kFALSE;
2826       }
2827       Info("MergeOutputs", "Submitting merging JDL");
2828       if (!SubmitMerging()) return kFALSE;
2829       Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2830       Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2831       return kFALSE;
2832    }   
2833    // Get the output path
2834    if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2835    if (!DirectoryExists(fGridOutputDir)) {
2836       Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2837       return kFALSE;
2838    }
2839    if (!fOutputFiles.Length()) {
2840       Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2841       return kFALSE;
2842    }
2843    // Check if fast read option was requested
2844    Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2845         \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2846    if (fFastReadOption) {
2847       Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2848              \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2849       gEnv->SetValue("XNet.ConnectTimeout",50);
2850       gEnv->SetValue("XNet.RequestTimeout",50);
2851       gEnv->SetValue("XNet.MaxRedirectCount",2);
2852       gEnv->SetValue("XNet.ReconnectTimeout",50);
2853       gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2854    }   
2855    // Make sure we change the temporary directory
2856    gSystem->Setenv("TMPDIR", gSystem->pwd());
2857    // Set temporary compilation directory to current one
2858    gSystem->SetBuildDir(gSystem->pwd(), kTRUE);   
2859    TObjArray *list = fOutputFiles.Tokenize(",");
2860    TIter next(list);
2861    TObjString *str;
2862    TString outputFile;
2863    Bool_t merged = kTRUE;
2864    while((str=(TObjString*)next())) {
2865       outputFile = str->GetString();
2866       Int_t index = outputFile.Index("@");
2867       if (index > 0) outputFile.Remove(index);
2868       TString outputChunk = outputFile;
2869       outputChunk.ReplaceAll(".root", "_*.root");
2870       // Skip already merged outputs
2871       if (!gSystem->AccessPathName(outputFile)) {
2872          if (fOverwriteMode) {
2873             Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2874             gSystem->Unlink(outputFile);
2875             if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2876                Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2877                      outputChunk.Data());
2878                gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2879             }
2880          } else {   
2881             Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2882             continue;
2883          }   
2884       } else {
2885          if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2886             Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2887                   outputChunk.Data());
2888             gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2889          }   
2890       }
2891       if (fMergeExcludes.Contains(outputFile.Data()) || 
2892           fRegisterExcludes.Contains(outputFile.Data())) continue;
2893       // Perform a 'find' command in the output directory, looking for registered outputs    
2894       merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2895       if (!merged) {
2896          Error("MergeOutputs", "Terminate() will  NOT be executed");
2897          return kFALSE;
2898       }
2899       TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2900       if (fileOpened) fileOpened->Close();
2901    } 
2902    return kTRUE;
2903 }   
2904
2905 //______________________________________________________________________________
2906 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2907 {
2908 // Use the output files connected to output containers from the analysis manager
2909 // rather than the files defined by SetOutputFiles
2910    if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2911       Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2912    TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2913 }
2914       
2915 //______________________________________________________________________________
2916 void AliAnalysisAlien::SetOutputFiles(const char *list)
2917 {
2918 // Manually set the output files list.
2919 // Removes duplicates. Not allowed if default outputs are not disabled.
2920    if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2921       Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2922       return;
2923    }
2924    Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2925    fOutputFiles = "";
2926    TString slist = list;
2927    if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2928    TObjArray *arr = slist.Tokenize(" "); 
2929    TObjString *os;
2930    TIter next(arr);
2931    TString sout;
2932    while ((os=(TObjString*)next())) {
2933       sout = os->GetString();
2934       if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2935       if (fOutputFiles.Contains(sout)) continue;
2936       if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2937       fOutputFiles += sout;
2938    }
2939    delete arr;   
2940 }
2941
2942 //______________________________________________________________________________
2943 void AliAnalysisAlien::SetOutputArchive(const char *list)
2944 {
2945 // Manually set the output archive list. Free text - you are on your own...
2946 // Not allowed if default outputs are not disabled.
2947    if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2948       Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2949       return;
2950    }
2951    Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2952    fOutputArchive = list;
2953 }
2954
2955 //______________________________________________________________________________
2956 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2957 {
2958 // Setting a prefered output SE is not allowed anymore.
2959    Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2960 }
2961
2962 //______________________________________________________________________________
2963 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2964 {
2965 // Set some PROOF special parameter.
2966    TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2967    if (pair) {
2968       TObject *old = pair->Key();
2969       TObject *val = pair->Value();
2970       fProofParam.Remove(old);
2971       delete old;
2972       delete val;
2973    }
2974    fProofParam.Add(new TObjString(pname), new TObjString(value));
2975 }
2976
2977 //______________________________________________________________________________
2978 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2979 {
2980 // Returns a special PROOF parameter.
2981    TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2982    if (!pair) return 0;
2983    return pair->Value()->GetName();
2984 }      
2985
2986 //______________________________________________________________________________
2987 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2988 {
2989 // Start remote grid analysis.
2990    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2991    Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2992    if (!mgr || !mgr->IsInitialized()) {
2993       Error("StartAnalysis", "You need an initialized analysis manager for this");
2994       return kFALSE;
2995    }
2996    // Are we in PROOF mode ?
2997    if (mgr->IsProofMode()) {
2998       if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2999       else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3000       if (fProofCluster.IsNull()) {
3001          Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
3002          return kFALSE;
3003       }   
3004       if (fProofDataSet.IsNull() && !testMode) {
3005          Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
3006          return kFALSE;
3007       }   
3008       // Set the needed environment
3009       gEnv->SetValue("XSec.GSI.DelegProxy","2");
3010       // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
3011       if (fProofReset && !testMode) {
3012          if (fProofReset==1) {
3013             Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
3014             gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
3015          } else {         
3016             Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
3017             gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
3018          }
3019          Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
3020          return kFALSE;
3021       }
3022       
3023       if (!testMode) {
3024         // Check if there is an old active session
3025         Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
3026         if (nsessions) {
3027           Error("StartAnalysis","You have to reset your old session first\n");
3028           return kFALSE;
3029         }
3030       }
3031       // Do we need to change the ROOT version ? The success of this cannot be checked.
3032       if (!fRootVersionForProof.IsNull() && !testMode) {
3033          gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");", 
3034                             fProofCluster.Data(), fRootVersionForProof.Data()));
3035       }
3036       // Connect to PROOF and check the status
3037       Long_t proof = 0;
3038       TString sworkers;
3039       if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
3040       else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3041       if (!testMode) {
3042          if (!sworkers.IsNull()) 
3043             proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3044          else   
3045             proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
3046       } else {
3047          proof = gROOT->ProcessLine("TProof::Open(\"\");");
3048          if (!proof) {
3049             Error("StartAnalysis", "Could not start PROOF in test mode");
3050             return kFALSE;
3051          }   
3052       }
3053       if (!proof) {
3054          Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
3055          return kFALSE;
3056       }   
3057       if (fNproofWorkersPerSlave*fNproofWorkers > 0)
3058          gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3059       // Set proof special parameters if any
3060       TIter nextpp(&fProofParam);
3061       TObject *proofparam;
3062       while ((proofparam=nextpp())) {
3063          TString svalue = GetProofParameter(proofparam->GetName());
3064          gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
3065       }   
3066       // Is dataset existing ?
3067       if (!testMode) {
3068          TString dataset = fProofDataSet;
3069          Int_t index = dataset.Index("#");
3070          if (index>=0) dataset.Remove(index);
3071 //         if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
3072 //            Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
3073 //            return kFALSE;
3074 //         }
3075 //         Info("StartAnalysis", "Dataset %s found", dataset.Data());
3076       }
3077       // Is ClearPackages() needed ?
3078       if (TestSpecialBit(kClearPackages)) {
3079          Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
3080          gROOT->ProcessLine("gProof->ClearPackages();");
3081       }
3082       // Is a given aliroot mode requested ?
3083       TList optionsList;
3084       TString parLibs;
3085       if (!fAliRootMode.IsNull()) {
3086          TString alirootMode = fAliRootMode;
3087          if (alirootMode == "default") alirootMode = "";
3088          Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
3089          optionsList.SetOwner();
3090          optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
3091          // Check the additional libs to be loaded
3092          TString extraLibs;
3093          Bool_t parMode = kFALSE;
3094          if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
3095          // Parse the extra libs for .so
3096          if (fAdditionalLibs.Length()) {
3097             TObjArray *list = fAdditionalLibs.Tokenize(" ");
3098             TIter next(list);
3099             TObjString *str;
3100             while((str=(TObjString*)next())) {
3101                if (str->GetString().Contains(".so")) {
3102                   if (parMode) {
3103                      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());
3104                      break;
3105                   }   
3106                   TString stmp = str->GetName();
3107                   if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
3108                   stmp.ReplaceAll(".so","");
3109                   if (!extraLibs.IsNull()) extraLibs += ":";
3110                   extraLibs += stmp;
3111                   continue;
3112                }
3113                if (str->GetString().Contains(".par")) {
3114                   // The first par file found in the list will not allow any further .so
3115                   parMode = kTRUE;
3116                   if (!parLibs.IsNull()) parLibs += ":";
3117                   parLibs += str->GetName();
3118                   continue;
3119                }   
3120             }
3121             if (list) delete list;            
3122          }
3123         if (!extraLibs.IsNull()) {
3124           Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
3125           optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
3126         }
3127          // Check extra includes
3128          if (!fIncludePath.IsNull()) {
3129             TString includePath = fIncludePath;
3130             includePath.ReplaceAll(" ",":");
3131             includePath.ReplaceAll("$ALICE_ROOT/","");
3132             includePath.ReplaceAll("${ALICE_ROOT}/","");
3133             includePath.ReplaceAll("-I","");
3134             includePath.Remove(TString::kTrailing, ':');
3135             Info("StartAnalysis", "Adding extra includes: %s",includePath.Data()); 
3136             optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
3137          }
3138          // Check if connection to grid is requested
3139          if (TestSpecialBit(kProofConnectGrid)) 
3140             optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
3141          // Enable AliRoot par
3142          if (testMode) {
3143          // Enable proof lite package
3144             TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
3145             for (Int_t i=0; i<optionsList.GetSize(); i++) {
3146                TNamed *obj = (TNamed*)optionsList.At(i);
3147                printf("%s  %s\n", obj->GetName(), obj->GetTitle());
3148             }   
3149             if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
3150               && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
3151                   Info("StartAnalysis", "AliRootProofLite enabled");
3152             } else {                      
3153                Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
3154                return kFALSE;
3155             }   
3156          } else {
3157            if ( ! fAliROOTVersion.IsNull() ) {
3158              if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);", 
3159                                          fAliROOTVersion.Data(), &optionsList))) {
3160                 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
3161                 return kFALSE;
3162              }
3163            }
3164          }
3165          // Enable first par files from fAdditionalLibs
3166          if (!parLibs.IsNull()) {
3167             TObjArray *list = parLibs.Tokenize(":");
3168             TIter next(list);
3169             TObjString *package;
3170             while((package=(TObjString*)next())) {
3171                TString spkg = package->GetName();
3172                spkg.ReplaceAll(".par", "");
3173                gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3174                if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3175                   TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
3176                   if (gROOT->ProcessLine(enablePackage)) {
3177                      Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3178                      return kFALSE;
3179                   }
3180                } else {
3181                   Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3182                   return kFALSE;
3183                }
3184             }
3185             if (list) delete list; 
3186          }
3187       } else {
3188          if (fAdditionalLibs.Contains(".so") && !testMode) {
3189             Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
3190                    \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
3191             return kFALSE;       
3192          }
3193       }
3194       // Enable par files if requested
3195       if (fPackages && fPackages->GetEntries()) {
3196          TIter next(fPackages);
3197          TObject *package;
3198          while ((package=next())) {
3199             // Skip packages already enabled
3200             if (parLibs.Contains(package->GetName())) continue;
3201             TString spkg = package->GetName();
3202             spkg.ReplaceAll(".par", "");
3203             gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3204             if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
3205                if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3206                   Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
3207                   return kFALSE;
3208                }
3209             } else {
3210                Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
3211                return kFALSE;
3212             }
3213          }
3214       }
3215       // Do we need to load analysis source files ?
3216       // NOTE: don't load on client since this is anyway done by the user to attach his task.
3217       if (fAnalysisSource.Length()) {
3218          TObjArray *list = fAnalysisSource.Tokenize(" ");
3219          TIter next(list);
3220          TObjString *str;
3221          while((str=(TObjString*)next())) {
3222             gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
3223          }
3224          if (list) delete list;
3225       }
3226       if (testMode) {
3227       // Register dataset to proof lite.
3228          if (fFileForTestMode.IsNull()) {
3229             Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
3230             return kFALSE;
3231          }
3232          if (gSystem->AccessPathName(fFileForTestMode)) {
3233             Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
3234             return kFALSE;
3235          }   
3236          TFileCollection *coll = new TFileCollection();
3237          coll->AddFromFile(fFileForTestMode);
3238          gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
3239          gROOT->ProcessLine("gProof->ShowDataSets()");
3240       }
3241       return kTRUE;
3242    }
3243    
3244    // Check if output files have to be taken from the analysis manager
3245    if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
3246       // Add output files and AOD files
3247       fOutputFiles = GetListOfFiles("outaod");
3248       // Add extra files registered to the analysis manager
3249       TString extra = GetListOfFiles("ext");
3250       if (!extra.IsNull()) {
3251          extra.ReplaceAll(".root", "*.root");
3252          if (!fOutputFiles.IsNull()) fOutputFiles += ",";
3253          fOutputFiles += extra;
3254       }
3255       // Compose the output archive.
3256       fOutputArchive = "log_archive.zip:std*@disk=1 ";
3257       fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
3258    }
3259 //   if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
3260    if (TestBit(AliAnalysisGrid::kOffline)) {
3261       Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
3262       \n                         there nor any job run. You can revise the JDL and analysis \
3263       \n                         macro then run the same in \"submit\" mode.");
3264    } else if (TestBit(AliAnalysisGrid::kTest)) {
3265       Info("StartAnalysis","\n##### LOCAL MODE #####   Your analysis will be run locally on a subset of the requested \
3266       \n                         dataset.");
3267    } else if (TestBit(AliAnalysisGrid::kSubmit)) {
3268       Info("StartAnalysis","\n##### SUBMIT MODE #####  Files required by your analysis are copied to your grid working \
3269       \n                         space and job submitted.");
3270    } else if (TestBit(AliAnalysisGrid::kMerge)) {
3271       Info("StartAnalysis","\n##### MERGE MODE #####   The registered outputs of the analysis will be merged");
3272       if (fMergeViaJDL) CheckInputData();
3273       return kTRUE;
3274    } else {
3275       Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");   
3276    }   
3277       
3278    Print();   
3279    if (!Connect()) {
3280       Error("StartAnalysis", "Cannot start grid analysis without grid connection");
3281       return kFALSE;
3282    }
3283    if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
3284    if (!CheckInputData()) {
3285       Error("StartAnalysis", "There was an error in preprocessing your requested input data");
3286       return kFALSE;
3287    }   
3288    if (!CreateDataset(fDataPattern)) {
3289       TString serror;
3290       if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
3291       if (fRunNumbers.Length()) serror = "run numbers";
3292       if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
3293       serror += Form("\n   or data pattern <%s>", fDataPattern.Data());
3294       Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
3295       return kFALSE;
3296    }   
3297    WriteAnalysisFile();
3298    WriteAnalysisMacro();
3299    WriteExecutable();
3300    WriteValidationScript();
3301    if (fMergeViaJDL) {
3302       WriteMergingMacro();
3303       WriteMergeExecutable();
3304       WriteValidationScript(kTRUE);
3305    }   
3306    if (!CreateJDL()) return kFALSE;
3307    if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3308    if (testMode) {
3309       // Locally testing the analysis
3310       Info("StartAnalysis", "\n_______________________________________________________________________ \
3311       \n   Running analysis script in a daughter shell as on a worker node \
3312       \n_______________________________________________________________________");
3313       TObjArray *list = fOutputFiles.Tokenize(",");
3314       TIter next(list);
3315       TObjString *str;
3316       TString outputFile;
3317       while((str=(TObjString*)next())) {
3318          outputFile = str->GetString();
3319          Int_t index = outputFile.Index("@");
3320          if (index > 0) outputFile.Remove(index);         
3321          if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
3322       }
3323       delete list;
3324       gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
3325       gSystem->Exec(Form("bash %s",fValidationScript.Data()));
3326 //      gSystem->Exec("cat stdout");
3327       return kFALSE;
3328    }
3329    // Check if submitting is managed by LPM manager
3330    if (fProductionMode) {
3331       TString prodfile = fJDLName;
3332       prodfile.ReplaceAll(".jdl", ".prod");
3333       WriteProductionFile(prodfile);
3334       Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
3335       return kFALSE;
3336    }   
3337    // Submit AliEn job(s)
3338    gGrid->Cd(fGridOutputDir);
3339    TGridResult *res;
3340    TString jobID = "";
3341    if (!fRunNumbers.Length() && !fRunRange[0]) {
3342       // Submit a given xml or a set of runs
3343       res = gGrid->Command(Form("submit %s", fJDLName.Data()));
3344       printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
3345       if (res) {
3346          const char *cjobId = res->GetKey(0,"jobId");
3347          if (!cjobId) {
3348             gGrid->Stdout();
3349             gGrid->Stderr();
3350             Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
3351             return kFALSE;
3352          } else {
3353             Info("StartAnalysis", "\n_______________________________________________________________________ \
3354             \n#####   Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
3355             \n_______________________________________________________________________",
3356                    fJDLName.Data(), cjobId);
3357             jobID = cjobId;      
3358          }          
3359          delete res;
3360       } else {
3361          Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3362          return kFALSE;      
3363       }   
3364    } else {
3365       // Submit for a range of enumeration of runs.
3366       if (!Submit()) return kFALSE;
3367    }   
3368          
3369    Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
3370    \n You may exit at any time and terminate the job later using the option <terminate> \
3371    \n ##################################################################################", jobID.Data());
3372    gSystem->Exec("aliensh");
3373    return kTRUE;
3374 }
3375
3376 //______________________________________________________________________________
3377 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
3378 {
3379 // Get a comma-separated list of output files of the requested type.
3380 // Type can be (case unsensitive):
3381 //    aod - list of aod files (std, extensions and filters)
3382 //    out - list of output files connected to containers (but not aod's or extras)
3383 //    ext - list of extra files registered to the manager
3384 //    ter - list of files produced in terminate
3385    static TString files;
3386    files = "";
3387    TString stype = type;
3388    stype.ToLower();
3389    TString aodfiles, extra;
3390    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3391    if (!mgr) {
3392       ::Error("GetListOfFiles", "Cannot call this without analysis manager");
3393       return files.Data();
3394    }
3395    if (mgr->GetOutputEventHandler()) {
3396       aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
3397       TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
3398       if (!extraaod.IsNull()) {
3399          aodfiles += ",";
3400          aodfiles += extraaod;
3401       }
3402    }
3403    if (stype.Contains("aod")) {
3404       files = aodfiles;
3405       if (stype == "aod") return files.Data();
3406    }  
3407    // Add output files that are not in the list of AOD files 
3408    TString outputfiles = "";
3409    TIter next(mgr->GetOutputs());
3410    AliAnalysisDataContainer *output;
3411    const char *filename = 0;
3412    while ((output=(AliAnalysisDataContainer*)next())) {
3413       filename = output->GetFileName();
3414       if (!(strcmp(filename, "default"))) continue;
3415       if (outputfiles.Contains(filename)) continue;
3416       if (aodfiles.Contains(filename))    continue;
3417       if (!outputfiles.IsNull()) outputfiles += ",";
3418       outputfiles += filename;
3419    }
3420    if (stype.Contains("out")) {
3421       if (!files.IsNull()) files += ",";
3422       files += outputfiles;
3423       if (stype == "out") return files.Data();
3424    }   
3425    // Add extra files registered to the analysis manager
3426    TString sextra;
3427    extra = mgr->GetExtraFiles();
3428    if (!extra.IsNull()) {
3429       extra.Strip();
3430       extra.ReplaceAll(" ", ",");
3431       TObjArray *fextra = extra.Tokenize(",");
3432       TIter nextx(fextra);
3433       TObject *obj;
3434       while ((obj=nextx())) {
3435          if (aodfiles.Contains(obj->GetName())) continue;
3436          if (outputfiles.Contains(obj->GetName())) continue;
3437          if (sextra.Contains(obj->GetName())) continue;
3438          if (!sextra.IsNull()) sextra += ",";
3439          sextra += obj->GetName();
3440       }
3441       delete fextra;
3442       if (stype.Contains("ext")) {
3443          if (!files.IsNull()) files += ",";
3444          files += sextra;
3445       }
3446    }   
3447    if (stype == "ext") return files.Data();
3448    TString termfiles;
3449    if (!fTerminateFiles.IsNull()) {
3450       fTerminateFiles.Strip();
3451       fTerminateFiles.ReplaceAll(" ",",");
3452       TObjArray *fextra = fTerminateFiles.Tokenize(",");
3453       TIter nextx(fextra);
3454       TObject *obj;
3455       while ((obj=nextx())) {
3456          if (aodfiles.Contains(obj->GetName())) continue;
3457          if (outputfiles.Contains(obj->GetName())) continue;
3458          if (termfiles.Contains(obj->GetName())) continue;
3459          if (sextra.Contains(obj->GetName())) continue;
3460          if (!termfiles.IsNull()) termfiles += ",";
3461          termfiles += obj->GetName();
3462       }
3463       delete fextra;
3464    }   
3465    if (stype.Contains("ter")) {
3466       if (!files.IsNull() && !termfiles.IsNull()) {
3467          files += ",";
3468          files += termfiles;
3469       }   
3470    }   
3471    return files.Data();
3472 }   
3473
3474 //______________________________________________________________________________
3475 Bool_t AliAnalysisAlien::Submit()
3476 {
3477 // Submit all master jobs.
3478    Int_t nmasterjobs = fInputFiles->GetEntries();
3479    Long_t tshoot = gSystem->Now();
3480    if (!fNsubmitted && !SubmitNext()) return kFALSE;
3481    while (fNsubmitted < nmasterjobs) {
3482       Long_t now = gSystem->Now();
3483       if ((now-tshoot)>30000) {
3484          tshoot = now;
3485          if (!SubmitNext()) return kFALSE;
3486       }   
3487    }
3488    return kTRUE;
3489 }
3490
3491 //______________________________________________________________________________
3492 Bool_t AliAnalysisAlien::SubmitMerging()
3493 {
3494 // Submit all merging jobs.
3495    if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3496    gGrid->Cd(fGridOutputDir);
3497    TString mergeJDLName = fExecutable;
3498    mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3499    if (!fInputFiles) {
3500       Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3501       return kFALSE;
3502    }   
3503    Int_t ntosubmit = fInputFiles->GetEntries();
3504    for (Int_t i=0; i<ntosubmit; i++) {
3505       TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3506       runOutDir.ReplaceAll(".xml", "");
3507       if (fOutputToRunNo) {
3508          // The output directory is the run number
3509          printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3510          runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3511       } else {
3512          if (!fRunNumbers.Length() && !fRunRange[0]) {
3513             // The output directory is the grid outdir
3514             printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3515             runOutDir = fGridOutputDir;
3516          } else {
3517             // The output directory is the master number in 3 digits format
3518             printf("### Submitting merging job for master <%03d>\n", i);
3519             runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3520          }   
3521       }
3522       // Check now the number of merging stages.
3523       TObjArray *list = fOutputFiles.Tokenize(",");
3524       TIter next(list);
3525       TObjString *str;
3526       TString outputFile;
3527       while((str=(TObjString*)next())) {
3528          outputFile = str->GetString();
3529          Int_t index = outputFile.Index("@");
3530          if (index > 0) outputFile.Remove(index);
3531          if (!fMergeExcludes.Contains(outputFile) && 
3532              !fRegisterExcludes.Contains(outputFile)) break;
3533       }
3534       delete list;
3535       Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3536       if (!done && (i==ntosubmit-1)) return kFALSE;
3537       if (!fRunNumbers.Length() && !fRunRange[0]) break;
3538    }
3539    if (!ntosubmit) return kTRUE;
3540    Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3541                           \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3542                           \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3543                           \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3544                           \n ################################################################################################################");
3545    gSystem->Exec("aliensh");
3546    return kTRUE;
3547 }
3548
3549 //______________________________________________________________________________
3550 Bool_t AliAnalysisAlien::SubmitNext()
3551 {
3552 // Submit next bunch of master jobs if the queue is free. The first master job is
3553 // submitted right away, while the next will not be unless the previous was split.
3554 // The plugin will not submit new master jobs if there are more that 500 jobs in
3555 // waiting phase.
3556    static Bool_t iscalled = kFALSE;
3557    static Int_t firstmaster = 0;
3558    static Int_t lastmaster = 0;
3559    static Int_t npermaster  = 0;
3560    if (iscalled) return kTRUE;
3561    iscalled = kTRUE;
3562    Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3563    Int_t ntosubmit = 0;
3564    TGridResult *res;
3565    TString jobID = "";
3566    Int_t nmasterjobs = fInputFiles->GetEntries();
3567    if (!fNsubmitted) {
3568       ntosubmit = 1;
3569       if (!IsUseSubmitPolicy()) {
3570          if (nmasterjobs>5)
3571             Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3572                 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3573          ntosubmit = nmasterjobs;
3574       }   
3575    } else {
3576       TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3577       printf("=== master %d: %s\n", lastmaster, status.Data());
3578       // If last master not split, just return
3579       if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3580       // No more than 100 waiting jobs
3581       if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3582       npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;      
3583       if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3584       if (!ntosubmit) ntosubmit = 1;
3585       printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n", 
3586              nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3587    }
3588    for (Int_t i=0; i<ntosubmit; i++) {
3589       // Submit for a range of enumeration of runs.
3590       if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3591       TString query;
3592       TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3593       runOutDir.ReplaceAll(".xml", "");
3594       if (fOutputToRunNo)
3595          query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3596       else
3597          query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3598       printf("********* %s\n",query.Data());
3599       res = gGrid->Command(query);
3600       if (res) {
3601          TString cjobId1 = res->GetKey(0,"jobId");
3602          if (!cjobId1.Length()) {
3603             iscalled = kFALSE;
3604             gGrid->Stdout();
3605             gGrid->Stderr();
3606             Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3607             return kFALSE;
3608          } else {
3609             Info("StartAnalysis", "\n_______________________________________________________________________ \
3610             \n#####   Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3611             \n_______________________________________________________________________",
3612                 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3613             jobID += cjobId1;
3614             jobID += " ";
3615             lastmaster = cjobId1.Atoi();
3616             if (!firstmaster) firstmaster = lastmaster;
3617             fNsubmitted++;
3618          }          
3619          delete res;
3620       } else {
3621          Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3622          return kFALSE;
3623       }   
3624    }
3625    iscalled = kFALSE;
3626    return kTRUE;
3627 }
3628
3629 //______________________________________________________________________________
3630 void AliAnalysisAlien::WriteAnalysisFile()
3631 {
3632 // Write current analysis manager into the file <analysisFile>
3633    TString analysisFile = fExecutable;
3634    analysisFile.ReplaceAll(".sh", ".root");
3635    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
3636       AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3637       if (!mgr || !mgr->IsInitialized()) {
3638          Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3639          return;
3640       }
3641       // Check analysis type
3642       TObject *handler;
3643       if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3644       handler = (TObject*)mgr->GetInputEventHandler();
3645       if (handler) {
3646          if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3647             AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3648             if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3649             if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3650          } else {
3651             if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3652             if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3653          }
3654       }
3655       TDirectory *cdir = gDirectory;
3656       TFile *file = TFile::Open(analysisFile, "RECREATE");
3657       if (file) {
3658          // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3659          if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3660          // Unless merging makes no sense
3661          if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3662          mgr->Write();
3663          delete file;
3664          // Enable termination for local jobs
3665          mgr->SetSkipTerminate(kFALSE);
3666       }
3667       if (cdir) cdir->cd();
3668       Info("WriteAnalysisFile", "\n#####   Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3669    }   
3670    Bool_t copy = kTRUE;
3671    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3672    if (copy) {
3673       CdWork();
3674       TString workdir = gGrid->GetHomeDirectory();
3675       workdir += fGridWorkingDir;
3676       Info("WriteAnalysisFile", "\n#####   Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3677       if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3678       if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(), 
3679           Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3680    }   
3681 }
3682
3683 //______________________________________________________________________________
3684 void AliAnalysisAlien::WriteAnalysisMacro()
3685 {
3686 // Write the analysis macro that will steer the analysis in grid mode.
3687    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
3688       ofstream out;
3689       out.open(fAnalysisMacro.Data(), ios::out);
3690       if (!out.good()) {
3691          Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3692          return;
3693       }
3694       Bool_t hasSTEERBase = kFALSE;
3695       Bool_t hasESD = kFALSE;
3696       Bool_t hasAOD = kFALSE;
3697       Bool_t hasANALYSIS = kFALSE;
3698       Bool_t hasOADB = kFALSE;
3699       Bool_t hasANALYSISalice = kFALSE;
3700       Bool_t hasCORRFW = kFALSE;
3701       TString func = fAnalysisMacro;
3702       TString type = "ESD";
3703       TString comment = "// Analysis using ";
3704       if (IsUseMCchain()) {
3705          type = "MC";
3706          comment += "MC";
3707       } else {   
3708          if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3709          if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3710             type = "AOD";
3711             comment += "AOD";
3712          }   
3713       }
3714       if (type!="AOD" && fFriendChainName!="") {
3715          Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3716          return;
3717       }
3718       if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3719       else comment += " data";
3720       out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3721       func.ReplaceAll(".C", "");
3722       out << "void " << func.Data() << "()" << endl; 
3723       out << "{" << endl;
3724       out << comment.Data() << endl;
3725       out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3726       out << "   TStopwatch timer;" << endl;
3727       out << "   timer.Start();" << endl << endl;
3728       // Change temp directory to current one
3729       out << "// Set temporary merging directory to current one" << endl;
3730       out << "   gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;   
3731       out << "// Set temporary compilation directory to current one" << endl;
3732       out << "   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;   
3733       // Reset existing include path
3734       out << "// Reset existing include path and add current directory first in the search" << endl;
3735       out << "   gSystem->SetIncludePath(\"-I.\");" << endl;
3736       if (!fExecutableCommand.Contains("aliroot")) {
3737          out << "// load base root libraries" << endl;
3738          out << "   gSystem->Load(\"libTree\");" << endl;
3739          out << "   gSystem->Load(\"libGeom\");" << endl;
3740          out << "   gSystem->Load(\"libVMC\");" << endl;
3741          out << "   gSystem->Load(\"libPhysics\");" << endl << endl;
3742          out << "   gSystem->Load(\"libMinuit\");" << endl << endl;
3743       }   
3744       if (fAdditionalRootLibs.Length()) {
3745          // in principle libtree /lib geom libvmc etc. can go into this list, too
3746          out << "// Add aditional libraries" << endl;
3747          TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3748          TIter next(list);
3749          TObjString *str;
3750          while((str=(TObjString*)next())) {
3751             if (str->GetString().Contains(".so"))
3752             out << "   gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3753          }
3754          if (list) delete list;
3755       }
3756       out << "// Load analysis framework libraries" << endl;
3757       TString setupPar = "AliAnalysisAlien::SetupPar";
3758       if (!fPackages) {
3759          if (!fExecutableCommand.Contains("aliroot")) {         
3760             out << "   gSystem->Load(\"libSTEERBase\");" << endl;
3761             out << "   gSystem->Load(\"libESD\");" << endl;
3762             out << "   gSystem->Load(\"libAOD\");" << endl;
3763          }   
3764          out << "   gSystem->Load(\"libANALYSIS\");" << endl;
3765          out << "   gSystem->Load(\"libOADB\");" << endl;
3766          out << "   gSystem->Load(\"libANALYSISalice\");" << endl;
3767          out << "   gSystem->Load(\"libCORRFW\");" << endl << endl;
3768       } else {
3769          TIter next(fPackages);
3770          TObject *obj;
3771          TString pkgname;
3772          while ((obj=next())) {
3773             pkgname = obj->GetName();
3774             if (pkgname == "STEERBase" ||
3775                 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3776             if (pkgname == "ESD" ||
3777                 pkgname == "ESD.par")       hasESD = kTRUE;
3778             if (pkgname == "AOD" ||
3779                 pkgname == "AOD.par")       hasAOD = kTRUE;
3780             if (pkgname == "ANALYSIS" ||
3781                 pkgname == "ANALYSIS.par")  hasANALYSIS = kTRUE;
3782             if (pkgname == "OADB" ||
3783                 pkgname == "OADB.par")      hasOADB = kTRUE;
3784             if (pkgname == "ANALYSISalice" ||
3785                 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3786             if (pkgname == "CORRFW" ||
3787                 pkgname == "CORRFW.par")    hasCORRFW = kTRUE;
3788          }
3789          if (hasANALYSISalice) setupPar = "SetupPar";   
3790          if (!hasSTEERBase) out << "   gSystem->Load(\"libSTEERBase\");" << endl;
3791          else out << "   if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3792          if (!hasESD)       out << "   gSystem->Load(\"libESD\");" << endl;
3793          else out << "   if (!" << setupPar << "(\"ESD\")) return;" << endl;
3794          if (!hasAOD)       out << "   gSystem->Load(\"libAOD\");" << endl;
3795          else out << "   if (!" << setupPar << "(\"AOD\")) return;" << endl;
3796          if (!hasANALYSIS)  out << "   gSystem->Load(\"libANALYSIS\");" << endl;
3797          else out << "   if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3798          if (!hasOADB)  out << "   gSystem->Load(\"libOADB\");" << endl;
3799          else out << "   if (!" << setupPar << "(\"OADB\")) return;" << endl;
3800          if (!hasANALYSISalice)   out << "   gSystem->Load(\"libANALYSISalice\");" << endl;
3801          else out << "   if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3802          if (!hasCORRFW)    out << "   gSystem->Load(\"libCORRFW\");" << endl << endl;
3803          else out << "   if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3804          out << "// Compile other par packages" << endl;
3805          next.Reset();
3806          while ((obj=next())) {
3807             pkgname = obj->GetName();
3808             if (pkgname == "STEERBase" ||
3809                 pkgname == "STEERBase.par" ||
3810                 pkgname == "ESD" ||
3811                 pkgname == "ESD.par" ||
3812                 pkgname == "AOD" ||
3813                 pkgname == "AOD.par" ||
3814                 pkgname == "ANALYSIS" ||
3815                 pkgname == "ANALYSIS.par" ||
3816                 pkgname == "OADB" ||
3817                 pkgname == "OADB.par" ||
3818                 pkgname == "ANALYSISalice" ||
3819                 pkgname == "ANALYSISalice.par" ||
3820                 pkgname == "CORRFW" ||
3821                 pkgname == "CORRFW.par") continue;
3822             out << "   if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3823          }   
3824       }   
3825       out << "// include path" << endl;
3826       // Get the include path from the interpreter and remove entries pointing to AliRoot
3827       out << "   TString intPath = gInterpreter->GetIncludePath();" << endl;
3828       out << "   TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3829       out << "   TIter nextpath(listpaths);" << endl;
3830       out << "   TObjString *pname;" << endl;
3831       out << "   while ((pname=(TObjString*)nextpath())) {" << endl;
3832       out << "      TString current = pname->GetName();" << endl;
3833       out << "      if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3834       out << "      gSystem->AddIncludePath(current);" << endl;
3835       out << "   }" << endl;
3836       out << "   if (listpaths) delete listpaths;" << endl;
3837       if (fIncludePath.Length()) out << "   gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3838       out << "   gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3839       out << "   printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3840       if (fAdditionalLibs.Length()) {
3841          out << "// Add aditional AliRoot libraries" << endl;
3842          TObjArray *list = fAdditionalLibs.Tokenize(" ");
3843          TIter next(list);
3844          TObjString *str;
3845          while((str=(TObjString*)next())) {
3846             if (str->GetString().Contains(".so"))
3847                out << "   gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3848             if (str->GetString().Contains(".par"))
3849                out << "   if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3850          }
3851          if (list) delete list;
3852       }
3853       out << endl;
3854       out << "// analysis source to be compiled at runtime (if any)" << endl;
3855       if (fAnalysisSource.Length()) {
3856          TObjArray *list = fAnalysisSource.Tokenize(" ");
3857          TIter next(list);
3858          TObjString *str;
3859          while((str=(TObjString*)next())) {
3860             out << "   gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3861          }   
3862          if (list) delete list;
3863       }
3864       out << endl;
3865 //      out << "   printf(\"Currently load libraries:\\n\");" << endl;
3866 //      out << "   printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3867       if (fFastReadOption) {
3868          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 !!! \
3869                 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3870          out << "// fast xrootd reading enabled" << endl;
3871          out << "   printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3872          out << "   gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3873          out << "   gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3874          out << "   gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3875          out << "   gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3876          out << "   gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3877       } 
3878       if (!IsLocalTest()) {  
3879          out << "// connect to AliEn and make the chain" << endl;
3880          out << "   if (!TGrid::Connect(\"alien://\")) return;" << endl;
3881       }   
3882       out << "// read the analysis manager from file" << endl;
3883       TString analysisFile = fExecutable;
3884       analysisFile.ReplaceAll(".sh", ".root");
3885       out << "   AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\"" 
3886           << analysisFile << "\");" << endl;
3887       out << "   if (!mgr) return;" << endl;
3888       if (IsLocalTest()) {
3889          out << "   AliAnalysisAlien *plugin = new AliAnalysisAlien();" << endl;
3890          out << "   plugin->SetRunMode(\"test\");" << endl;
3891          if (fFileForTestMode.IsNull())
3892             out << "   plugin->SetFileForTestMode(\"data.txt\");" << endl;
3893          else   
3894             out << "   plugin->SetFileForTestMode(\"" << fFileForTestMode << "\");" << endl;
3895          out << "   plugin->SetNtestFiles(" << fNtestFiles << ");" << endl;
3896          out << "   mgr->SetGridHandler(plugin);" << endl;
3897          if (AliAnalysisManager::GetAnalysisManager()) {
3898             out << "   mgr->SetDebugLevel(" << AliAnalysisManager::GetAnalysisManager()->GetDebugLevel() << ");" << endl;
3899             out << "   mgr->SetNSysInfo(" << AliAnalysisManager::GetAnalysisManager()->GetNsysInfo() << ");" << endl;
3900          } else {
3901             out << "   mgr->SetDebugLevel(10);" << endl;
3902             out << "   mgr->SetNSysInfo(100);" << endl;
3903          }
3904       }
3905       out << "   mgr->PrintStatus();" << endl;
3906       if (AliAnalysisManager::GetAnalysisManager()) {
3907          if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3908             out << "   gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3909          } else {
3910             if (TestBit(AliAnalysisGrid::kTest))            
3911                out << "   AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3912             else
3913                out << "   AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3914          }
3915       }   
3916       if (!IsLocalTest()) {
3917          out << "   TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;   
3918          out << "   mgr->StartAnalysis(\"localfile\", chain);" << endl;
3919       } else {
3920          out << "   mgr->StartAnalysis(\"localfile\");" << endl;
3921       }   
3922       out << "   timer.Stop();" << endl;
3923       out << "   timer.Print();" << endl;
3924       out << "}" << endl << endl;
3925       if (!IsLocalTest()) {
3926          out <<"//________________________________________________________________________________" << endl;
3927          out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3928          out << "{" << endl;
3929          out << "// Create a chain using url's from xml file" << endl;
3930          out << "   TString filename;" << endl;
3931          out << "   Int_t run = 0;" << endl;
3932          if (IsUseMCchain()) {
3933             out << "   TString treename = \"TE\";" << endl;
3934          } else {   
3935             out << "   TString treename = type;" << endl;
3936             out << "   treename.ToLower();" << endl;
3937             out << "   treename += \"Tree\";" << endl;
3938          }   
3939          out << "   printf(\"***************************************\\n\");" << endl;
3940          out << "   printf(\"    Getting chain of trees %s\\n\", treename.Data());" << endl;
3941          out << "   printf(\"***************************************\\n\");" << endl;
3942          out << "   TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3943          out << "   if (!coll) {" << endl;
3944          out << "      ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3945          out << "      return NULL;" << endl;
3946          out << "   }" << endl;
3947          out << "   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3948          out << "   TChain *chain = new TChain(treename);" << endl;
3949          if(fFriendChainName!="") {
3950             out << "   TChain *chainFriend = new TChain(treename);" << endl;
3951          }
3952          out << "   coll->Reset();" << endl;
3953          out << "   while (coll->Next()) {" << endl;
3954          out << "      filename = coll->GetTURL("");" << endl;
3955          out << "      if (mgr) {" << endl;
3956          out << "         Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3957          out << "         if (nrun && nrun != run) {" << endl;
3958          out << "            printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3959          out << "            mgr->SetRunFromPath(nrun);" << endl;
3960          out << "            run = nrun;" << endl;
3961          out << "         }" << endl;
3962          out << "      }" << endl;
3963          out << "      chain->Add(filename);" << endl;
3964          if(fFriendChainName!="") {
3965             out << "      TString fileFriend=coll->GetTURL(\"\");" << endl;
3966             out << "      fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3967             out << "      fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3968             out << "      chainFriend->Add(fileFriend.Data());" << endl;
3969          }
3970          out << "   }" << endl;
3971          out << "   if (!chain->GetNtrees()) {" << endl;
3972          out << "      ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3973          out << "      return NULL;" << endl;
3974          out << "   }" << endl;
3975          if(fFriendChainName!="") {
3976             out << "   chain->AddFriend(chainFriend);" << endl;
3977          }
3978          out << "   return chain;" << endl;
3979          out << "}" << endl << endl;
3980       }   
3981       if (hasANALYSISalice) {
3982          out <<"//________________________________________________________________________________" << endl;
3983          out << "Bool_t SetupPar(const char *package) {" << endl;
3984          out << "// Compile the package and set it up." << endl;
3985          out << "   TString pkgdir = package;" << endl;
3986          out << "   pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3987          out << "   gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3988          out << "   TString cdir = gSystem->WorkingDirectory();" << endl;
3989          out << "   gSystem->ChangeDirectory(pkgdir);" << endl;
3990          out << "   // Check for BUILD.sh and execute" << endl;
3991          out << "   if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3992          out << "      printf(\"*******************************\\n\");" << endl;
3993          out << "      printf(\"*** Building PAR archive    ***\\n\");" << endl;
3994          out << "      printf(\"*******************************\\n\");" << endl;
3995          out << "      if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3996          out << "         ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3997          out << "         gSystem->ChangeDirectory(cdir);" << endl;
3998          out << "         return kFALSE;" << endl;
3999          out << "      }" << endl;
4000          out << "   } else {" << endl;
4001          out << "      ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4002          out << "      gSystem->ChangeDirectory(cdir);" << endl;
4003          out << "      return kFALSE;" << endl;
4004          out << "   }" << endl;
4005          out << "   // Check for SETUP.C and execute" << endl;
4006          out << "   if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4007          out << "      printf(\"*******************************\\n\");" << endl;
4008          out << "      printf(\"***    Setup PAR archive    ***\\n\");" << endl;
4009          out << "      printf(\"*******************************\\n\");" << endl;
4010          out << "      gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4011          out << "   } else {" << endl;
4012          out << "      ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4013          out << "      gSystem->ChangeDirectory(cdir);" << endl;
4014          out << "      return kFALSE;" << endl;
4015          out << "   }" << endl;
4016          out << "   // Restore original workdir" << endl;
4017          out << "   gSystem->ChangeDirectory(cdir);" << endl;
4018          out << "   return kTRUE;" << endl;
4019          out << "}" << endl;
4020       }
4021       Info("WriteAnalysisMacro", "\n#####   Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
4022    }   
4023    Bool_t copy = kTRUE;
4024    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4025    if (copy) {
4026       CdWork();
4027       TString workdir = gGrid->GetHomeDirectory();
4028       workdir += fGridWorkingDir;
4029       if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
4030       Info("WriteAnalysisMacro", "\n#####   Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
4031 //      TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
4032       if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(), 
4033            Form("alien://%s/%s", workdir.Data(), 
4034            fAnalysisMacro.Data()))) Fatal("","Terminating");
4035    }
4036 }
4037
4038 //______________________________________________________________________________
4039 void AliAnalysisAlien::WriteMergingMacro()
4040 {
4041 // Write a macro to merge the outputs per master job.
4042    if (!fMergeViaJDL) return;
4043    if (!fOutputFiles.Length()) {
4044       Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
4045       return;
4046    }   
4047    TString mergingMacro = fExecutable;
4048    mergingMacro.ReplaceAll(".sh","_merge.C");
4049    if (gGrid && !fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
4050    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
4051       ofstream out;
4052       out.open(mergingMacro.Data(), ios::out);
4053       if (!out.good()) {
4054          Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
4055          return;
4056       }
4057       Bool_t hasSTEERBase = kFALSE;
4058       Bool_t hasESD = kFALSE;
4059       Bool_t hasAOD = kFALSE;
4060       Bool_t hasANALYSIS = kFALSE;
4061       Bool_t hasOADB = kFALSE;
4062       Bool_t hasANALYSISalice = kFALSE;
4063       Bool_t hasCORRFW = kFALSE;
4064       TString func = mergingMacro;
4065       TString comment;
4066       func.ReplaceAll(".C", "");
4067       out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
4068       out << "{" << endl;
4069       out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
4070       out << "   TStopwatch timer;" << endl;
4071       out << "   timer.Start();" << endl << endl;
4072       // Reset existing include path
4073       out << "// Reset existing include path and add current directory first in the search" << endl;
4074       out << "   gSystem->SetIncludePath(\"-I.\");" << endl;
4075       if (!fExecutableCommand.Contains("aliroot")) {
4076          out << "// load base root libraries" << endl;
4077          out << "   gSystem->Load(\"libTree\");" << endl;
4078          out << "   gSystem->Load(\"libGeom\");" << endl;
4079          out << "   gSystem->Load(\"libVMC\");" << endl;
4080          out << "   gSystem->Load(\"libPhysics\");" << endl << endl;
4081          out << "   gSystem->Load(\"libMinuit\");" << endl << endl;
4082       }   
4083       if (fAdditionalRootLibs.Length()) {
4084          // in principle libtree /lib geom libvmc etc. can go into this list, too
4085          out << "// Add aditional libraries" << endl;
4086          TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
4087          TIter next(list);
4088          TObjString *str;
4089          while((str=(TObjString*)next())) {
4090             if (str->GetString().Contains(".so"))
4091             out << "   gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4092          }
4093          if (list) delete list;
4094       }
4095       out << "// Load analysis framework libraries" << endl;
4096       if (!fPackages) {
4097          if (!fExecutableCommand.Contains("aliroot")) {
4098             out << "   gSystem->Load(\"libSTEERBase\");" << endl;
4099             out << "   gSystem->Load(\"libESD\");" << endl;
4100             out << "   gSystem->Load(\"libAOD\");" << endl;
4101          }
4102          out << "   gSystem->Load(\"libANALYSIS\");" << endl;
4103          out << "   gSystem->Load(\"libOADB\");" << endl;
4104          out << "   gSystem->Load(\"libANALYSISalice\");" << endl;
4105          out << "   gSystem->Load(\"libCORRFW\");" << endl << endl;
4106       } else {
4107          TIter next(fPackages);
4108          TObject *obj;
4109          TString pkgname;
4110          TString setupPar = "AliAnalysisAlien::SetupPar";
4111          while ((obj=next())) {
4112             pkgname = obj->GetName();
4113             if (pkgname == "STEERBase" ||
4114                 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
4115             if (pkgname == "ESD" ||
4116                 pkgname == "ESD.par")       hasESD = kTRUE;
4117             if (pkgname == "AOD" ||
4118                 pkgname == "AOD.par")       hasAOD = kTRUE;
4119             if (pkgname == "ANALYSIS" ||
4120                 pkgname == "ANALYSIS.par")  hasANALYSIS = kTRUE;
4121             if (pkgname == "OADB" ||
4122                 pkgname == "OADB.par")      hasOADB = kTRUE;
4123             if (pkgname == "ANALYSISalice" ||
4124                 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
4125             if (pkgname == "CORRFW" ||
4126                 pkgname == "CORRFW.par")    hasCORRFW = kTRUE;
4127          }   
4128          if (hasANALYSISalice) setupPar = "SetupPar";   
4129          if (!hasSTEERBase) out << "   gSystem->Load(\"libSTEERBase\");" << endl;
4130          else out << "   if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
4131          if (!hasESD)       out << "   gSystem->Load(\"libESD\");" << endl;
4132          else out << "   if (!" << setupPar << "(\"ESD\")) return;" << endl;
4133          if (!hasAOD)       out << "   gSystem->Load(\"libAOD\");" << endl;
4134          else out << "   if (!" << setupPar << "(\"AOD\")) return;" << endl;
4135          out << "   gSystem->Load(\"libOADB\");" << endl;
4136          if (!hasANALYSIS)  out << "   gSystem->Load(\"libANALYSIS\");" << endl;
4137          else out << "   if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
4138          if (!hasOADB)  out << "   gSystem->Load(\"libOADB\");" << endl;
4139          else out << "   if (!" << setupPar << "(\"OADB\")) return;" << endl;
4140          if (!hasANALYSISalice)   out << "   gSystem->Load(\"libANALYSISalice\");" << endl;
4141          else out << "   if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
4142          if (!hasCORRFW)    out << "   gSystem->Load(\"libCORRFW\");" << endl << endl;
4143          else out << "   if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
4144          out << "// Compile other par packages" << endl;
4145          next.Reset();
4146          while ((obj=next())) {
4147             pkgname = obj->GetName();
4148             if (pkgname == "STEERBase" ||
4149                 pkgname == "STEERBase.par" ||
4150                 pkgname == "ESD" ||
4151                 pkgname == "ESD.par" ||
4152                 pkgname == "AOD" ||
4153                 pkgname == "AOD.par" ||
4154                 pkgname == "ANALYSIS" ||
4155                 pkgname == "ANALYSIS.par" ||
4156                 pkgname == "OADB" ||
4157                 pkgname == "OADB.par" ||
4158                 pkgname == "ANALYSISalice" ||
4159                 pkgname == "ANALYSISalice.par" ||
4160                 pkgname == "CORRFW" ||
4161                 pkgname == "CORRFW.par") continue;
4162             out << "   if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
4163          }   
4164       }   
4165       out << "// include path" << endl;
4166       // Get the include path from the interpreter and remove entries pointing to AliRoot
4167       out << "   TString intPath = gInterpreter->GetIncludePath();" << endl;
4168       out << "   TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
4169       out << "   TIter nextpath(listpaths);" << endl;
4170       out << "   TObjString *pname;" << endl;
4171       out << "   while ((pname=(TObjString*)nextpath())) {" << endl;
4172       out << "      TString current = pname->GetName();" << endl;
4173       out << "      if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
4174       out << "      gSystem->AddIncludePath(current);" << endl;
4175       out << "   }" << endl;
4176       out << "   if (listpaths) delete listpaths;" << endl;
4177       if (fIncludePath.Length()) out << "   gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
4178       out << "   gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
4179       out << "   printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
4180       if (fAdditionalLibs.Length()) {
4181          out << "// Add aditional AliRoot libraries" << endl;
4182          TObjArray *list = fAdditionalLibs.Tokenize(" ");
4183          TIter next(list);
4184          TObjString *str;
4185          while((str=(TObjString*)next())) {
4186             if (str->GetString().Contains(".so"))
4187                out << "   gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
4188          }
4189          if (list) delete list;
4190       }
4191       out << endl;
4192       out << "// Analysis source to be compiled at runtime (if any)" << endl;
4193       if (fAnalysisSource.Length()) {
4194          TObjArray *list = fAnalysisSource.Tokenize(" ");
4195          TIter next(list);
4196          TObjString *str;
4197          while((str=(TObjString*)next())) {
4198             out << "   gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
4199          }   
4200          if (list) delete list;
4201       }
4202       out << endl;      
4203
4204       if (fFastReadOption) {
4205          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 !!!");
4206          out << "// fast xrootd reading enabled" << endl;
4207          out << "   printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
4208          out << "   gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
4209          out << "   gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
4210          out << "   gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
4211          out << "   gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
4212          out << "   gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
4213       }
4214       // Change temp directory to current one
4215       out << "// Set temporary merging directory to current one" << endl;
4216       out << "   gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;   
4217       out << "// Set temporary compilation directory to current one" << endl;
4218       out << "   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;   
4219       out << "// Connect to AliEn" << endl;
4220       out << "   if (!TGrid::Connect(\"alien://\")) return;" << endl;
4221       out << "   TString outputDir = dir;" << endl;  
4222       out << "   TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
4223       out << "   TString mergeExcludes = \"" << fMergeExcludes << " " << fRegisterExcludes << "\";" << endl;
4224       out << "   TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
4225       out << "   TIter *iter = new TIter(list);" << endl;
4226       out << "   TObjString *str;" << endl;
4227       out << "   TString outputFile;" << endl;
4228       out << "   Bool_t merged = kTRUE;" << endl;
4229       out << "   while((str=(TObjString*)iter->Next())) {" << endl;
4230       out << "      outputFile = str->GetString();" << endl;
4231       out << "      if (outputFile.Contains(\"*\")) continue;" << endl;
4232       out << "      Int_t index = outputFile.Index(\"@\");" << endl;
4233       out << "      if (index > 0) outputFile.Remove(index);" << endl;
4234       out << "      // Skip already merged outputs" << endl;
4235       out << "      if (!gSystem->AccessPathName(outputFile)) {" << endl;
4236       out << "         printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
4237       out << "         continue;" << endl;
4238       out << "      }" << endl;
4239       out << "      if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
4240       out << "      merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
4241       out << "      if (!merged) {" << endl;
4242       out << "         printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
4243       out << "         return;" << endl;
4244       out << "      }" << endl;
4245       out << "   }" << endl;
4246       out << "   // all outputs merged, validate" << endl;
4247       out << "   ofstream out;" << endl;
4248       out << "   out.open(\"outputs_valid\", ios::out);" << endl;
4249       out << "   out.close();" << endl;
4250       out << "   // read the analysis manager from file" << endl;
4251       TString analysisFile = fExecutable;
4252       analysisFile.ReplaceAll(".sh", ".root");
4253       out << "   if (!outputDir.Contains(\"Stage\")) return;" << endl;
4254       out << "   AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\"" 
4255           << analysisFile << "\");" << endl;
4256       out << "   if (!mgr) return;" << endl;
4257       out << "   mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
4258       out << "   mgr->SetSkipTerminate(kFALSE);" << endl;
4259       out << "   mgr->PrintStatus();" << endl;
4260       if (AliAnalysisManager::GetAnalysisManager()) {
4261          if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
4262             out << "   gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
4263          } else {
4264             if (TestBit(AliAnalysisGrid::kTest))            
4265                out << "   AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
4266             else
4267                out << "   AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
4268          }
4269       }   
4270       out << "   TTree *tree = NULL;" << endl;
4271       out << "   mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
4272       out << "}" << endl << endl;
4273       if (hasANALYSISalice) {
4274          out <<"//________________________________________________________________________________" << endl;
4275          out << "Bool_t SetupPar(const char *package) {" << endl;
4276          out << "// Compile the package and set it up." << endl;
4277          out << "   TString pkgdir = package;" << endl;
4278          out << "   pkgdir.ReplaceAll(\".par\",\"\");" << endl;
4279          out << "   gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4280          out << "   TString cdir = gSystem->WorkingDirectory();" << endl;
4281          out << "   gSystem->ChangeDirectory(pkgdir);" << endl;
4282          out << "   // Check for BUILD.sh and execute" << endl;
4283          out << "   if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
4284          out << "      printf(\"*******************************\\n\");" << endl;
4285          out << "      printf(\"*** Building PAR archive    ***\\n\");" << endl;
4286          out << "      printf(\"*******************************\\n\");" << endl;
4287          out << "      if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
4288          out << "         ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4289          out << "         gSystem->ChangeDirectory(cdir);" << endl;
4290          out << "         return kFALSE;" << endl;
4291          out << "      }" << endl;
4292          out << "   } else {" << endl;
4293          out << "      ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4294          out << "      gSystem->ChangeDirectory(cdir);" << endl;
4295          out << "      return kFALSE;" << endl;
4296          out << "   }" << endl;
4297          out << "   // Check for SETUP.C and execute" << endl;
4298          out << "   if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
4299          out << "      printf(\"*******************************\\n\");" << endl;
4300          out << "      printf(\"***    Setup PAR archive    ***\\n\");" << endl;
4301          out << "      printf(\"*******************************\\n\");" << endl;
4302          out << "      gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
4303          out << "   } else {" << endl;
4304          out << "      ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4305          out << "      gSystem->ChangeDirectory(cdir);" << endl;
4306          out << "      return kFALSE;" << endl;
4307          out << "   }" << endl;
4308          out << "   // Restore original workdir" << endl;
4309          out << "   gSystem->ChangeDirectory(cdir);" << endl;
4310          out << "   return kTRUE;" << endl;
4311          out << "}" << endl;
4312       }
4313    }   
4314    Bool_t copy = kTRUE;
4315    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4316    if (copy) {
4317       CdWork();
4318       TString workdir = gGrid->GetHomeDirectory();
4319       workdir += fGridWorkingDir;
4320       if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
4321       Info("WriteMergingMacro", "\n#####   Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
4322 //      TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
4323       if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(), 
4324            Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
4325    }
4326 }
4327
4328 //______________________________________________________________________________
4329 Bool_t AliAnalysisAlien::SetupPar(const char *package)
4330 {
4331 // Compile the par file archive pointed by <package>. This must be present in the current directory.
4332 // Note that for loading the compiled library. The current directory should have precedence in
4333 // LD_LIBRARY_PATH
4334    TString pkgdir = package;
4335    pkgdir.ReplaceAll(".par","");
4336    gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
4337    TString cdir = gSystem->WorkingDirectory();
4338    gSystem->ChangeDirectory(pkgdir);
4339    // Check for BUILD.sh and execute
4340    if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
4341       printf("**************************************************\n");
4342       printf("*** Building PAR archive %s\n", package);
4343       printf("**************************************************\n");
4344       if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
4345          ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
4346          gSystem->ChangeDirectory(cdir);
4347          return kFALSE;
4348       }
4349    } else {
4350       ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
4351       gSystem->ChangeDirectory(cdir);
4352       return kFALSE;
4353    }
4354    // Check for SETUP.C and execute
4355    if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
4356       printf("**************************************************\n");
4357       printf("*** Setup PAR archive %s\n", package);
4358       printf("**************************************************\n");
4359       gROOT->Macro("PROOF-INF/SETUP.C");
4360       printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
4361    } else {
4362       ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
4363       gSystem->ChangeDirectory(cdir);
4364       return kFALSE;
4365    }   
4366    // Restore original workdir
4367    gSystem->ChangeDirectory(cdir);
4368    return kTRUE;
4369 }
4370
4371 //______________________________________________________________________________
4372 void AliAnalysisAlien::WriteExecutable()
4373 {
4374 // Generate the alien executable script.
4375    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
4376       ofstream out;
4377       out.open(fExecutable.Data(), ios::out);
4378       if (out.bad()) {
4379          Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
4380          return;
4381       }
4382       out << "#!/bin/bash" << endl;
4383       // Make sure we can properly compile par files
4384       out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4385       out << "echo \"=========================================\"" << endl; 
4386       out << "echo \"############## PATH : ##############\"" << endl;
4387       out << "echo $PATH" << endl;
4388       out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4389       out << "echo $LD_LIBRARY_PATH" << endl;
4390       out << "echo \"############## ROOTSYS : ##############\"" << endl;
4391       out << "echo $ROOTSYS" << endl;
4392       out << "echo \"############## which root : ##############\"" << endl;
4393       out << "which root" << endl;
4394       out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4395       out << "echo $ALICE_ROOT" << endl;
4396       out << "echo \"############## which aliroot : ##############\"" << endl;
4397       out << "which aliroot" << endl;
4398       out << "echo \"############## system limits : ##############\"" << endl;
4399       out << "ulimit -a" << endl;
4400       out << "echo \"############## memory : ##############\"" << endl;
4401       out << "free -m" << endl;
4402       out << "echo \"=========================================\"" << endl << endl;
4403       out << fExecutableCommand << " "; 
4404       out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl;
4405       out << "RET=$?" << endl;
4406       out << "if [ \"$RET\" != \"0\" ];then" << endl;
4407       out << "  echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4408       out << "  if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4409       out << "    let sig=\"$RET - 128\""<<endl;
4410       out << "    sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4411       out << "    KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4412       out << "    CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4413       out << "    XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4414       out << "    sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4415       out << "    echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4416       out << "  fi"<<endl;
4417       out << "  exit $RET"<< endl;
4418       out << "fi" << endl << endl ;
4419       out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $RET ========\"" << endl;
4420       out << "echo \"############## memory after: ##############\"" << endl;
4421       out << "free -m" << endl;
4422    }   
4423    Bool_t copy = kTRUE;
4424    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4425    if (copy) {
4426       CdWork();
4427       TString workdir = gGrid->GetHomeDirectory();
4428       TString bindir = Form("%s/bin", workdir.Data());
4429       if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4430       workdir += fGridWorkingDir;
4431       TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4432       if (FileExists(executable)) gGrid->Rm(executable);
4433       Info("WriteExecutable", "\n#####   Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4434 //      TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4435       if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(), 
4436           executable.Data())) Fatal("","Terminating");
4437    } 
4438 }
4439
4440 //______________________________________________________________________________
4441 void AliAnalysisAlien::WriteMergeExecutable()
4442 {
4443 // Generate the alien executable script for the merging job.
4444    if (!fMergeViaJDL) return;
4445    TString mergeExec = fExecutable;
4446    mergeExec.ReplaceAll(".sh", "_merge.sh");
4447    if (!TestBit(AliAnalysisGrid::kSubmit)) {
4448       ofstream out;
4449       out.open(mergeExec.Data(), ios::out);
4450       if (out.bad()) {
4451          Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4452          return;
4453       }
4454       out << "#!/bin/bash" << endl;
4455       // Make sure we can properly compile par files
4456       out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4457       out << "echo \"=========================================\"" << endl; 
4458       out << "echo \"############## PATH : ##############\"" << endl;
4459       out << "echo $PATH" << endl;
4460       out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4461       out << "echo $LD_LIBRARY_PATH" << endl;
4462       out << "echo \"############## ROOTSYS : ##############\"" << endl;
4463       out << "echo $ROOTSYS" << endl;
4464       out << "echo \"############## which root : ##############\"" << endl;
4465       out << "which root" << endl;
4466       out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4467       out << "echo $ALICE_ROOT" << endl;
4468       out << "echo \"############## which aliroot : ##############\"" << endl;
4469       out << "which aliroot" << endl;
4470       out << "echo \"############## system limits : ##############\"" << endl;
4471       out << "ulimit -a" << endl;
4472       out << "echo \"############## memory : ##############\"" << endl;
4473       out << "free -m" << endl;
4474       out << "echo \"=========================================\"" << endl << endl;
4475       TString mergeMacro = fExecutable;
4476       mergeMacro.ReplaceAll(".sh", "_merge.C");
4477       if (IsOneStageMerging())
4478          out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4479       else
4480          out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4481       out << fExecutableCommand << " " << "$ARG" << endl; 
4482       out << "RET=$?" << endl;
4483       out << "if [ \"$RET\" != \"0\" ];then" << endl;
4484       out << "  echo \"======== ERROR : " << fAnalysisMacro.Data() << " finished with NON zero code: $RET ========\"" << endl;
4485       out << "  if [ \"$RET\" -gt 128 ] && [ \"$RET\" -lt 160 ]; then"<<endl;
4486       out << "    let sig=\"$RET - 128\""<<endl;
4487       out << "    sigs='HUP INT QUIT ILL TRAP ABRT BUS FPE"<<endl;
4488       out << "    KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT"<<endl;
4489       out << "    CHLD CONT STOP TSTP TTIN TTOU URG XCPU"<<endl;
4490       out << "    XFSZ VTALRM PROF WINCH IO PWR SYS'"<<endl;
4491       out << "    sig=SIG`echo $sigs | awk '{ print $'\"$sig\"' }'`"<<endl;
4492       out << "    echo \"======== it appears to have been killed with signal: $sig ========\""<<endl;
4493       out << "  fi"<<endl;
4494       out << "  exit $RET"<< endl;
4495       out << "fi" << endl << endl ;
4496       out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4497       out << "echo \"############## memory after: ##############\"" << endl;
4498       out << "free -m" << endl;
4499    }   
4500    Bool_t copy = kTRUE;
4501    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4502    if (copy) {
4503       CdWork();
4504       TString workdir = gGrid->GetHomeDirectory();
4505       TString bindir = Form("%s/bin", workdir.Data());
4506       if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4507       workdir += fGridWorkingDir;
4508       TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4509       if (FileExists(executable)) gGrid->Rm(executable);
4510       Info("WriteMergeExecutable", "\n#####   Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4511 //      TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4512       if (!copyLocal2Alien("WriteMergeExecutable",
4513           mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4514    } 
4515 }
4516
4517 //______________________________________________________________________________
4518 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4519 {
4520 // Write the production file to be submitted by LPM manager. The format is:
4521 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4522 // Next lines: full_path_to_dataset XXX (XXX is a string)
4523 // To submit, one has to: submit jdl XXX for all lines
4524    ofstream out;
4525    out.open(filename, ios::out);
4526    if (out.bad()) {
4527       Error("WriteProductionFile", "Bad file name: %s", filename);
4528       return;
4529    }
4530    TString workdir;
4531    if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4532       workdir = gGrid->GetHomeDirectory();
4533    workdir += fGridWorkingDir;
4534    Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4535    TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4536    out << locjdl << " " << njobspermaster << endl;
4537    Int_t nmasterjobs = fInputFiles->GetEntries();
4538    for (Int_t i=0; i<nmasterjobs; i++) {
4539       TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4540       runOutDir.ReplaceAll(".xml", "");
4541       if (fOutputToRunNo)
4542          out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4543       else
4544          out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4545    }
4546    if (gGrid) {
4547       Info("WriteProductionFile", "\n#####   Copying production file <%s> to your work directory", filename);
4548       if (FileExists(filename)) gGrid->Rm(filename);
4549 //      TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4550       if (!copyLocal2Alien("WriteProductionFile", filename, 
4551           Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4552    }   
4553 }
4554
4555 //______________________________________________________________________________
4556 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4557 {
4558 // Generate the alien validation script.
4559    // Generate the validation script
4560    TObjString *os;
4561    if (fValidationScript.IsNull()) {
4562       fValidationScript = fExecutable;
4563       fValidationScript.ReplaceAll(".sh", "_validation.sh");
4564    }   
4565    TString validationScript = fValidationScript;
4566    if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4567    if (!Connect()) {
4568       Error("WriteValidationScript", "Alien connection required");
4569       return;
4570    }
4571    if (!fTerminateFiles.IsNull()) {
4572       fTerminateFiles.Strip();
4573       fTerminateFiles.ReplaceAll(" ",",");
4574    }   
4575    TString outStream = "";
4576    if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4577    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
4578       ofstream out;
4579       out.open(validationScript, ios::out);
4580       out << "#!/bin/bash" << endl;
4581       out << "##################################################" << endl;
4582       out << "validateout=`dirname $0`" << endl;
4583       out << "validatetime=`date`" << endl;
4584       out << "validated=\"0\";" << endl;
4585       out << "error=0" << endl;
4586       out << "if [ -z $validateout ]" << endl;
4587       out << "then" << endl;
4588       out << "    validateout=\".\"" << endl;
4589       out << "fi" << endl << endl;
4590       out << "cd $validateout;" << endl;
4591       out << "validateworkdir=`pwd`;" << endl << endl;
4592       out << "echo \"*******************************************************\"" << outStream << endl;
4593       out << "echo \"* Automatically generated validation script           *\""  << outStream << endl;
4594       out << "" << endl;
4595       out << "echo \"* Time:    $validatetime \""  << outStream << endl;
4596       out << "echo \"* Dir:     $validateout\""  << outStream << endl;
4597       out << "echo \"* Workdir: $validateworkdir\""  << outStream << endl;
4598       out << "echo \"* ----------------------------------------------------*\""  << outStream << endl;
4599       out << "ls -la ./"  << outStream << endl;
4600       out << "echo \"* ----------------------------------------------------*\""  << outStream << endl << endl;
4601       out << "##################################################" << endl;
4602       out << "" << endl;
4603
4604       out << "if [ ! -f stderr ] ; then" << endl;
4605       out << "   error=1" << endl;
4606       out << "   echo \"* ########## Job not validated - no stderr  ###\" " << outStream << endl;
4607       out << "   echo \"Error = $error\" " << outStream << endl;
4608       out << "fi" << endl;
4609
4610       out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4611       out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4612       out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4613       out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4614       out << "" << endl;
4615
4616       out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4617       out << "   error=1" << endl;
4618       out << "   echo \"* ########## Job not validated - PAR archive not built  ###\" " << outStream << endl;
4619       out << "   echo \"$parArch\" " << outStream << endl;
4620       out << "   echo \"Error = $error\" " << outStream << endl;
4621       out << "fi" << endl;
4622
4623       out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4624       out << "   error=1" << endl;
4625       out << "   echo \"* ########## Job not validated - Segment. violation  ###\" " << outStream << endl;
4626       out << "   echo \"$segViol\" " << outStream << endl;
4627       out << "   echo \"Error = $error\" " << outStream << endl;
4628       out << "fi" << endl;
4629
4630       out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4631       out << "   error=1" << endl;
4632       out << "   echo \"* ########## Job not validated - Segment. fault  ###\" " << outStream << endl;
4633       out << "   echo \"$segFault\" " << outStream << endl;
4634       out << "   echo \"Error = $error\" " << outStream << endl;
4635       out << "fi" << endl;
4636
4637       out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4638       out << "   error=1" << endl;
4639       out << "   echo \"* ########## Job not validated - *** glibc detected ***  ###\" " << outStream << endl;
4640       out << "   echo \"$glibcErr\" " << outStream << endl;
4641       out << "   echo \"Error = $error\" " << outStream << endl;
4642       out << "fi" << endl;
4643
4644       // Part dedicated to the specific analyses running into the train
4645
4646       TString outputFiles = fOutputFiles;
4647       if (merge && !fTerminateFiles.IsNull()) {
4648          outputFiles += ",";
4649          outputFiles += fTerminateFiles;
4650       }
4651       TObjArray *arr = outputFiles.Tokenize(",");
4652       TIter next1(arr);
4653       TString outputFile;
4654       while (!merge && (os=(TObjString*)next1())) { 
4655          // No need to validate outputs produced by merging since the merging macro does this
4656          outputFile = os->GetString();
4657          Int_t index = outputFile.Index("@");
4658          if (index > 0) outputFile.Remove(index);
4659          if (fTerminateFiles.Contains(outputFile)) continue;
4660          if (outputFile.Contains("*")) continue;
4661          out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4662          out << "   error=1" << endl;
4663          out << "   echo \"Output file " << outputFile << " not found. Job FAILED !\""  << outStream << endl;
4664          out << "   echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4665          out << "fi" << endl;
4666       }   
4667       delete arr;
4668       out << "if ! [ -f outputs_valid ] ; then" << endl;
4669       out << "   error=1" << endl;
4670       out << "   echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4671       out << "   echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4672       out << "fi" << endl;
4673       
4674       out << "if [ $error = 0 ] ; then" << endl;
4675       out << "   echo \"* ----------------   Job Validated  ------------------*\""  << outStream << endl;
4676       if (!IsKeepLogs()) {
4677          out << "   echo \"* === Logs std* will be deleted === \"" << endl;
4678          outStream = "";
4679          out << "   rm -f std*" << endl;
4680       }            
4681       out << "fi" << endl;
4682
4683       out << "echo \"* ----------------------------------------------------*\""  << outStream << endl;
4684       out << "echo \"*******************************************************\""  << outStream << endl;
4685       out << "cd -" << endl;
4686       out << "exit $error" << endl;
4687    }    
4688    Bool_t copy = kTRUE;
4689    if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4690    if (copy) {
4691       CdWork();
4692       TString workdir = gGrid->GetHomeDirectory();
4693       workdir += fGridWorkingDir;
4694       Info("WriteValidationScript", "\n#####   Copying validation script <%s> to your AliEn working space", validationScript.Data());
4695       if (FileExists(validationScript)) gGrid->Rm(validationScript);
4696 //      TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4697       if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(), 
4698           Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");
4699    } 
4700 }