]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisAlien.cxx
AliTPCTransform.h - removing warning visible in
[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 "Riostream.h"
24 #include "TROOT.h"
25 #include "TSystem.h"
26 #include "TFile.h"
27 #include "TObjString.h"
28 #include "TObjArray.h"
29 #include "TGrid.h"
30 #include "TGridResult.h"
31 #include "TGridCollection.h"
32 #include "TGridJDL.h"
33 #include "TFileMerger.h"
34 #include "AliAnalysisManager.h"
35 #include "AliAnalysisAlien.h"
36
37 ClassImp(AliAnalysisAlien)
38
39 //______________________________________________________________________________
40 AliAnalysisAlien::AliAnalysisAlien()
41                  :AliAnalysisGrid(),
42                   fGridJDL(NULL),
43                   fPrice(0),
44                   fTTL(0),
45                   fSplitMaxInputFileNumber(0),
46                   fMaxInitFailed(0),
47                   fMasterResubmitThreshold(0),
48                   fRunNumbers(),
49                   fExecutable(),
50                   fArguments(),
51                   fAnalysisMacro(),
52                   fAnalysisSource(),
53                   fAdditionalLibs(),
54                   fSplitMode(),
55                   fAPIVersion(),
56                   fROOTVersion(),
57                   fAliROOTVersion(),
58                   fUser(),
59                   fGridWorkingDir(),
60                   fGridDataDir(),
61                   fDataPattern(),
62                   fGridOutputDir(),
63                   fOutputArchive(),
64                   fOutputFiles(),
65                   fInputFormat(),
66                   fDatasetName(),
67                   fJDLName(),
68                   fInputFiles(0),
69                   fPackages(0)
70 {
71 // Dummy ctor.
72    SetDefaults();
73 }
74
75 //______________________________________________________________________________
76 AliAnalysisAlien::AliAnalysisAlien(const char *name)
77                  :AliAnalysisGrid(name),
78                   fGridJDL(NULL),
79                   fPrice(0),
80                   fTTL(0),
81                   fSplitMaxInputFileNumber(0),
82                   fMaxInitFailed(0),
83                   fMasterResubmitThreshold(0),
84                   fRunNumbers(),
85                   fExecutable(),
86                   fArguments(),
87                   fAnalysisMacro(),
88                   fAnalysisSource(),
89                   fAdditionalLibs(),
90                   fSplitMode(),
91                   fAPIVersion(),
92                   fROOTVersion(),
93                   fAliROOTVersion(),
94                   fUser(),
95                   fGridWorkingDir(),
96                   fGridDataDir(),
97                   fDataPattern(),
98                   fGridOutputDir(),
99                   fOutputArchive(),
100                   fOutputFiles(),
101                   fInputFormat(),
102                   fDatasetName(),
103                   fJDLName(),
104                   fInputFiles(0),
105                   fPackages(0)
106 {
107 // Default ctor.
108    SetDefaults();
109 }
110
111 //______________________________________________________________________________
112 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
113                  :AliAnalysisGrid(other),
114                   fGridJDL(NULL),
115                   fPrice(other.fPrice),
116                   fTTL(other.fTTL),
117                   fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
118                   fMaxInitFailed(other.fMaxInitFailed),
119                   fMasterResubmitThreshold(other.fMasterResubmitThreshold),
120                   fRunNumbers(other.fRunNumbers),
121                   fExecutable(other.fExecutable),
122                   fArguments(other.fArguments),
123                   fAnalysisMacro(other.fAnalysisMacro),
124                   fAnalysisSource(other.fAnalysisSource),
125                   fAdditionalLibs(other.fAdditionalLibs),
126                   fSplitMode(other.fSplitMode),
127                   fAPIVersion(other.fAPIVersion),
128                   fROOTVersion(other.fROOTVersion),
129                   fAliROOTVersion(other.fAliROOTVersion),
130                   fUser(other.fUser),
131                   fGridWorkingDir(other.fGridWorkingDir),
132                   fGridDataDir(other.fGridDataDir),
133                   fDataPattern(other.fDataPattern),
134                   fGridOutputDir(other.fGridOutputDir),
135                   fOutputArchive(other.fOutputArchive),
136                   fOutputFiles(other.fOutputFiles),
137                   fInputFormat(other.fInputFormat),
138                   fDatasetName(other.fDatasetName),
139                   fJDLName(other.fJDLName),
140                   fInputFiles(0),
141                   fPackages(0)
142 {
143 // Copy ctor.
144    fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
145    if (other.fInputFiles) {
146       fInputFiles = new TObjArray();
147       TIter next(other.fInputFiles);
148       TObject *obj;
149       while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
150       fInputFiles->SetOwner();
151    }   
152    if (other.fPackages) {
153       fPackages = new TObjArray();
154       TIter next(other.fPackages);
155       TObject *obj;
156       while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
157       fPackages->SetOwner();
158    }   
159 }
160
161 //______________________________________________________________________________
162 AliAnalysisAlien::~AliAnalysisAlien()
163 {
164 // Destructor.
165    if (fGridJDL) delete fGridJDL;
166    if (fInputFiles) delete fInputFiles;
167    if (fPackages) delete fPackages;
168 }   
169
170 //______________________________________________________________________________
171 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
172 {
173 // Assignment.
174    if (this != &other) {
175       AliAnalysisGrid::operator=(other);
176       fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
177       fPrice                   = other.fPrice;
178       fTTL                     = other.fTTL;
179       fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
180       fMaxInitFailed           = other.fMaxInitFailed;
181       fMasterResubmitThreshold = other.fMasterResubmitThreshold;
182       fRunNumbers              = other.fRunNumbers;
183       fExecutable              = other.fExecutable;
184       fArguments               = other.fArguments;
185       fAnalysisMacro           = other.fAnalysisMacro;
186       fAnalysisSource          = other.fAnalysisSource;
187       fAdditionalLibs          = other.fAdditionalLibs;
188       fSplitMode               = other.fSplitMode;
189       fAPIVersion              = other.fAPIVersion;
190       fROOTVersion             = other.fROOTVersion;
191       fAliROOTVersion          = other.fAliROOTVersion;
192       fUser                    = other.fUser;
193       fGridWorkingDir          = other.fGridWorkingDir;
194       fGridDataDir             = other.fGridDataDir;
195       fDataPattern             = other.fDataPattern;
196       fGridOutputDir           = other.fGridOutputDir;
197       fOutputArchive           = other.fOutputArchive;
198       fOutputFiles             = other.fOutputFiles;
199       fInputFormat             = other.fInputFormat;
200       fDatasetName             = other.fDatasetName;
201       fJDLName                 = other.fJDLName;
202       if (other.fInputFiles) {
203          fInputFiles = new TObjArray();
204          TIter next(other.fInputFiles);
205          TObject *obj;
206          while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
207          fInputFiles->SetOwner();
208       }   
209       if (other.fPackages) {
210          fPackages = new TObjArray();
211          TIter next(other.fPackages);
212          TObject *obj;
213          while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
214          fPackages->SetOwner();
215       }   
216    }
217    return *this;
218 }
219
220 //______________________________________________________________________________
221 void AliAnalysisAlien::AddRunNumber(Int_t run)
222 {
223 // Add a run number to the list of runs to be processed.
224    if (fRunNumbers.Length()) fRunNumbers += " ";
225    fRunNumbers += Form("%d", run);
226 }   
227
228 //______________________________________________________________________________
229 void AliAnalysisAlien::AddDataFile(const char *lfn)
230 {
231 // Adds a data file to the input to be analysed. The file should be a valid LFN
232 // or point to an existing file in the alien workdir.
233    if (!fInputFiles) fInputFiles = new TObjArray();
234    fInputFiles->Add(new TObjString(lfn));
235 }
236    
237 //______________________________________________________________________________
238 Bool_t AliAnalysisAlien::Connect()
239 {
240 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
241    if (gGrid && gGrid->IsConnected()) return kTRUE;
242    if (!gSystem->Getenv("alien_API_USER")) {
243       Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
244             gSystem->Getenv("UID"));
245       return kFALSE;
246    }         
247    if (!gGrid) {
248       Info("Connect", "Trying to connect to AliEn ...");
249       TGrid::Connect("alien://");
250    }
251    if (!gGrid || !gGrid->IsConnected()) {
252       Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
253       return kFALSE;
254    }  
255    fUser = gGrid->GetUser();
256    Info("Connect", "\n#####   Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
257    return kTRUE;
258 }
259
260 //______________________________________________________________________________
261 void AliAnalysisAlien::CdWork()
262 {
263 // Check validity of alien workspace. Create directory if possible.
264    if (!Connect()) {
265       Error("CdWork", "Alien connection required");
266       return;
267    } 
268    TString homedir = gGrid->GetHomeDirectory();
269    TString workdir = homedir + fGridWorkingDir;
270    if (!gGrid->Cd(workdir)) {
271       gGrid->Cd(homedir);
272       if (gGrid->Mkdir(workdir)) {
273          gGrid->Cd(fGridWorkingDir);
274          Info("CreateJDL", "\n#####   Created alien working directory %s", fGridWorkingDir.Data());
275       } else {
276          Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
277                  workdir.Data(), homedir.Data());
278          fGridWorkingDir = "";
279       }          
280    }      
281 }
282
283 //______________________________________________________________________________
284 Bool_t AliAnalysisAlien::CheckInputData()
285 {
286 // Check validity of input data. If necessary, create xml files.
287    if (!fInputFiles && !fRunNumbers.Length()) {
288        Error("CheckInputData", "You have to specify either a set of run numbers or some existing grid files. Use AddRunNumber()/AddDataFile().");
289       return kFALSE;
290    }
291    // Process declared files
292    Bool_t is_collection = kFALSE;
293    Bool_t is_xml = kFALSE;
294    Bool_t use_tags = kFALSE;
295    Bool_t checked = kFALSE;
296    CdWork();
297    TString file;
298    TString workdir = gGrid->GetHomeDirectory();
299    workdir += fGridWorkingDir;
300    if (fInputFiles) {
301       TObjString *objstr;
302       TIter next(fInputFiles);
303       while ((objstr=(TObjString*)next())) {
304          file = workdir;
305          file += "/";
306          file += objstr->GetString();
307          // Store full lfn path
308          if (FileExists(file)) objstr->SetString(file);
309          else {
310             file = objstr->GetName();
311             if (!FileExists(objstr->GetName())) {
312                Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
313                      objstr->GetName(), workdir.Data());
314                return kFALSE;
315             }         
316          }
317          Bool_t iscoll, isxml, usetags;
318          CheckDataType(file, iscoll, isxml, usetags);
319          if (!checked) {
320             checked = kTRUE;
321             is_collection = iscoll;
322             is_xml = isxml;
323             use_tags = usetags;
324             TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
325          } else {
326             if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
327                Error("CheckInputData", "Some conflict was found in the types of inputs");
328                return kFALSE;
329             } 
330          }
331       }
332    }
333    // Process requested run numbers
334    if (!fRunNumbers.Length()) return kTRUE;
335    // Check validity of alien data directory
336    if (!fGridDataDir.Length()) {
337       Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
338       return kFALSE;
339    }
340    if (!gGrid->Cd(fGridDataDir)) {
341       Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
342       return kFALSE;
343    }
344    if (is_collection) {
345       Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
346       return kFALSE;   
347    }
348    
349    if (checked && !is_xml) {
350       Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
351       return kFALSE;   
352    }
353    // Check validity of run number(s)
354    TObjArray *arr;
355    TObjString *os;
356    TString path;
357    if (!checked) {
358       checked = kTRUE;
359       use_tags = fDataPattern.Contains("tag");
360       TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
361    }   
362    if (use_tags != fDataPattern.Contains("tag")) {
363       Error("CheckInputData", "Cannot mix input files using/not using tags");
364       return kFALSE;
365    }
366    if (fRunNumbers.Length()) {
367       arr = fRunNumbers.Tokenize(" ");
368       TIter next(arr);
369       while ((os=(TObjString*)next())) {
370          path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
371          if (!gGrid->Cd(path)) {
372             Error("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
373             return kFALSE;
374          }
375          path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
376          TString msg = "\n#####   file: ";
377          msg += path;
378          msg += " type: xml_collection;";
379          if (use_tags) msg += " using_tags: Yes";
380          else          msg += " using_tags: No";
381          Info("CheckDataType", msg.Data());
382          AddDataFile(path);
383       }
384       delete arr;   
385    }
386    return kTRUE;      
387 }   
388
389 //______________________________________________________________________________
390 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
391 {
392 // Create dataset for the grid data directory + run number.
393    if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
394    if (!Connect()) {
395       Error("CreateDataset", "Cannot create dataset with no grid connection");
396       return kFALSE;
397    }   
398
399    // Cd workspace
400    CdWork();
401    TString workdir = gGrid->GetHomeDirectory();
402    workdir += fGridWorkingDir;
403
404    // Compose the 'find' command arguments
405    TString command;
406    TString options = "-x collection ";
407    if (TestBit(AliAnalysisGrid::kTest)) options += "-l 100 ";
408    TString conditions = "";
409    
410    TString file;
411    TString path;
412    if (!fRunNumbers.Length()) return kTRUE;   
413    // Several runs
414    TObjArray *arr = fRunNumbers.Tokenize(" ");
415    TObjString *os;
416    TIter next(arr);
417    while ((os=(TObjString*)next())) {
418       path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
419       if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
420       else file = Form("%s.xml", os->GetString().Data());
421       if (FileExists(file) && !TestBit(AliAnalysisGrid::kTest)) {
422          Info("CreateDataset", "\n#####   Removing previous dataset %s", file.Data());
423          gGrid->Rm(file); 
424       }
425       command = "find ";
426       command += options;
427       command += path;
428       command += pattern;
429 //      conditions = Form(" > %s", file.Data());
430       command += conditions;
431       TGridResult *res = gGrid->Command(command);
432       if (res) delete res;
433       // Write standard output to file
434       gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
435       if (TestBit(AliAnalysisGrid::kTest)) break;
436       // Copy xml file to alien space
437       TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
438       if (!FileExists(file)) {
439          Error("CreateDataset", "Command %s did NOT succeed", command.Data());
440          delete arr;
441          return kFALSE;
442       }
443    }   
444    delete arr;
445    return kTRUE;
446 }
447
448 //______________________________________________________________________________
449 Bool_t AliAnalysisAlien::CreateJDL()
450 {
451 // Generate a JDL file according to current settings. The name of the file is 
452 // specified by fJDLName.
453    Bool_t error = kFALSE;
454    TObjArray *arr = 0;
455    Bool_t copy = kTRUE;
456    if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
457    Bool_t generate = kTRUE;
458    if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
459    if (!Connect()) {
460       Error("CreateJDL", "Alien connection required");
461       return kFALSE;
462    }   
463    // Check validity of alien workspace
464    CdWork();
465    TString workdir = gGrid->GetHomeDirectory();
466    workdir += fGridWorkingDir;
467    if (generate) {
468       TObjString *os;
469       if (!fInputFiles) {
470          Error("CreateJDL()", "Define some input files for your analysis.");
471          error = kTRUE;
472       }
473       // Compose list of input files   
474       // Check if output files were defined
475       if (!fOutputFiles.Length()) {
476          Error("CreateJDL", "You must define at least one output file");
477          error = kTRUE;
478       }   
479       // Check if an output directory was defined and valid
480       if (!fGridOutputDir.Length()) {
481          Error("CreateJDL", "You must define AliEn output directory");
482          error = kTRUE;
483       } else {
484          if (!gGrid->Cd(fGridOutputDir)) {
485             if (gGrid->Mkdir(fGridOutputDir)) {
486                Info("CreateJDL", "\n#####   Created alien output directory %s", fGridOutputDir.Data());
487             } else {
488                Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
489                error = kTRUE;
490             }
491          }
492          gGrid->Cd(workdir);
493       }   
494       // Exit if any error up to now
495       if (error) return kFALSE;   
496       // Set JDL fields
497       fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
498       fGridJDL->SetExecutable(fExecutable);
499 //      fGridJDL->SetTTL((UInt_t)fTTL);
500       fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
501       if (fMaxInitFailed > 0) 
502          fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
503       if (fSplitMaxInputFileNumber > 0) 
504          fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
505       if (fSplitMode.Length()) 
506          fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
507 //      fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
508       if (fAliROOTVersion.Length())  
509          fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
510       if (fROOTVersion.Length()) 
511          fGridJDL->AddToPackages("ROOT", fROOTVersion);
512       if (fAPIVersion.Length()) 
513          fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
514       fGridJDL->SetInputDataListFormat(fInputFormat);
515       fGridJDL->SetInputDataList("wn.xml");
516       if (fInputFiles) {
517          TIter next(fInputFiles);
518          while ((os=(TObjString*)next()))
519             fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
520       }      
521       fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
522       fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
523       if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
524          fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
525       if (fAdditionalLibs.Length()) {
526          arr = fAdditionalLibs.Tokenize(" ");
527          TIter next(arr);
528          while ((os=(TObjString*)next())) {
529             if (os->GetString().Contains(".so")) continue;
530             fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
531          }   
532          delete arr;   
533       }
534       if (fPackages) {
535          TIter next(fPackages);
536          TObject *obj;
537          while ((obj=next()))
538             fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
539       }
540       if (fOutputArchive.Length()) {
541          arr = fOutputArchive.Tokenize(" ");
542          TIter next(arr);
543          while ((os=(TObjString*)next()))
544             fGridJDL->AddToOutputArchive(os->GetString().Data());
545          delete arr;
546       }      
547       fGridJDL->SetOutputDirectory(Form("%s/%s/#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data()));
548       arr = fOutputFiles.Tokenize(" ");
549       TIter next(arr);
550       while ((os=(TObjString*)next())) fGridJDL->AddToOutputSandbox(os->GetString());
551       delete arr;
552 //      fGridJDL->SetPrice((UInt_t)fPrice);
553       fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
554       fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
555       if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
556       // Generate the JDL as a string
557       TString sjdl = fGridJDL->Generate();
558       Int_t index;
559       index = sjdl.Index("Executable");
560       if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
561       index = sjdl.Index("Split ");
562       if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
563       index = sjdl.Index("SplitMaxInputFileNumber");
564       if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
565       index = sjdl.Index("InputDataCollection");
566       if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
567       index = sjdl.Index("InputFile");
568       if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
569       index = sjdl.Index("InputDataList ");
570       if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
571       index = sjdl.Index("InputDataListFormat");
572       if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
573       index = sjdl.Index("Price");
574       if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
575       index = sjdl.Index("Requirements");
576       if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
577       index = sjdl.Index("Packages");
578       if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
579       index = sjdl.Index("User");
580       if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
581       index = sjdl.Index("TTL");
582       if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
583       index = sjdl.Index("OutputFile");
584       if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
585       index = sjdl.Index("OutputDir");
586       if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
587       index = sjdl.Index("OutputArchive");
588       if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
589       index = sjdl.Index("MaxInitFailed");
590       if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
591       index = sjdl.Index("MasterResubmitThreshold");
592       if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
593       sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
594       index = sjdl.Index("Validationcommand");
595       if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
596       sjdl.ReplaceAll("\"LF:", "\n   \"LF:");
597       sjdl.ReplaceAll("(member", "\n   (member");
598       sjdl.ReplaceAll("\",\"VO_", "\",\n   \"VO_");
599       sjdl.ReplaceAll("{", "{\n   ");
600       sjdl.ReplaceAll("};", "\n};");
601       sjdl.ReplaceAll("{\n   \n", "{\n");
602       sjdl.ReplaceAll("\n\n", "\n");
603       sjdl.ReplaceAll("OutputDirectory", "OutputDir");
604       sjdl += "JDLVariables = \n{\n   \"Packages\",\n   \"OutputDir\"\n};\n";
605       sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
606       index = sjdl.Index("JDLVariables");
607       if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
608       // Write jdl to file
609       ofstream out;
610       out.open(fJDLName.Data(), ios::out);
611       if (out.bad()) {
612          Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
613          return kFALSE;
614       }
615       out << sjdl << endl;
616    }
617    // Copy jdl to grid workspace   
618    if (!copy) {
619       Info("CreateJDL", "\n#####   You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
620    } else {
621       Info("CreateJDL", "\n#####   Copying JDL file <%s> to your AliEn working space", fJDLName.Data());
622       if (FileExists(fJDLName)) gGrid->Rm(fJDLName);
623       TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s/%s", workdir.Data(), fJDLName.Data()));
624       if (fAdditionalLibs.Length()) {
625          arr = fAdditionalLibs.Tokenize(" ");
626          TObjString *os;
627          TIter next(arr);
628          while ((os=(TObjString*)next())) {
629             if (os->GetString().Contains(".so")) continue;
630             Info("CreateJDL", "\n#####   Copying dependency: <%s> to your alien workspace", os->GetString().Data());
631             if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
632             TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
633          }   
634          delete arr;   
635       }
636       if (fPackages) {
637          TIter next(fPackages);
638          TObject *obj;
639          while ((obj=next())) {
640             Info("CreateJDL", "\n#####   Copying dependency: <%s> to your alien workspace", obj->GetName());
641             TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
642          }   
643       }      
644    } 
645    return kTRUE;
646 }
647
648 //______________________________________________________________________________
649 Bool_t AliAnalysisAlien::FileExists(const char *lfn) const
650 {
651 // Returns true if file exists.
652    if (!gGrid) {
653       Error("FileExists", "No connection to grid");
654       return kFALSE;
655    }
656    TGridResult *res = gGrid->Ls(lfn);
657    if (!res) return kFALSE;
658    TMap *map = dynamic_cast<TMap*>(res->At(0));
659    if (!map) {
660       delete res;
661       return kFALSE;
662    }   
663    TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
664    if (!objs || !objs->GetString().Length()) {
665       delete res;
666       return kFALSE;
667    }
668    delete res;   
669    return kTRUE;
670 }
671
672 //______________________________________________________________________________
673 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
674 {
675 // Check input data type.
676    is_collection = kFALSE;
677    is_xml = kFALSE;
678    use_tags = kFALSE;
679    if (!gGrid) {
680       Error("CheckDataType", "No connection to grid");
681       return;
682    }
683    is_collection = IsCollection(lfn);
684    TString msg = "\n#####   file: ";
685    msg += lfn;
686    if (is_collection) {
687       msg += " type: raw_collection;";
688    // special treatment for collections
689       is_xml = kFALSE;
690       // check for tag files in the collection
691       TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
692       if (!res) {
693          msg += " using_tags: No (unknown)";
694          Info("CheckDataType", msg.Data());
695          return;
696       }   
697       const char* typeStr = res->GetKey(0, "origLFN");
698       if (!typeStr || !strlen(typeStr)) {
699          msg += " using_tags: No (unknown)";
700          Info("CheckDataType", msg.Data());
701          return;
702       }   
703       TString file = typeStr;
704       use_tags = file.Contains(".tag");
705       if (use_tags) msg += " using_tags: Yes";
706       else          msg += " using_tags: No";
707       Info("CheckDataType", msg.Data());
708       return;
709    }
710    TString slfn(lfn);
711    slfn.ToLower();
712    is_xml = slfn.Contains(".xml");
713    if (is_xml) {
714    // Open xml collection and check if there are tag files inside
715       msg += " type: xml_collection;";
716       TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
717       if (!coll) {
718          msg += " using_tags: No (unknown)";
719          Info("CheckDataType", msg.Data());
720          return;
721       }   
722       TMap *map = coll->Next();
723       if (!map) {
724          msg += " using_tags: No (unknown)";
725          Info("CheckDataType", msg.Data());
726          return;
727       }   
728       map = (TMap*)map->GetValue("");
729       TString file;
730       if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
731       use_tags = file.Contains(".tag");
732       delete coll;
733       if (use_tags) msg += " using_tags: Yes";
734       else          msg += " using_tags: No";
735       Info("CheckDataType", msg.Data());
736       return;
737    }
738    use_tags = slfn.Contains(".tag");
739    if (slfn.Contains(".root")) msg += " type: root file;";
740    else                        msg += " type: unhnown file;";
741    if (use_tags) msg += " using_tags: Yes";
742    else          msg += " using_tags: No";
743    Info("CheckDataType", msg.Data());
744 }
745
746 //______________________________________________________________________________
747 void AliAnalysisAlien::EnablePackage(const char *package)
748 {
749 // Enables a par file supposed to exist in the current directory.
750    TString pkg(package);
751    pkg.ReplaceAll(".par", "");
752    pkg += ".par";
753    if (gSystem->AccessPathName(pkg)) {
754       Error("EnablePackage", "Package %s not found", pkg.Data());
755       return;
756    }
757    if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
758       Info("EnablePackage", "AliEn plugin will use .par packages");
759    TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
760    if (!fPackages) {
761       fPackages = new TObjArray();
762       fPackages->SetOwner();
763    }
764    fPackages->Add(new TObjString(pkg));
765 }      
766
767 //______________________________________________________________________________
768 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
769 {
770 // Returns true if file is a collection. Functionality duplicated from
771 // TAlien::Type() because we don't want to directly depend on TAlien.
772    if (!gGrid) {
773       Error("IsCollection", "No connection to grid");
774       return kFALSE;
775    }
776    TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
777    if (!res) return kFALSE;
778    const char* typeStr = res->GetKey(0, "type");
779    if (!typeStr || !strlen(typeStr)) return kFALSE;
780    if (!strcmp(typeStr, "collection")) return kTRUE;
781    delete res;
782    return kFALSE;
783 }   
784
785 //______________________________________________________________________________
786 void AliAnalysisAlien::SetDefaults()
787 {
788 // Set default values for everything. What cannot be filled will be left empty.
789    if (fGridJDL) delete fGridJDL;
790    fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
791    fPrice                      = 1;
792    fTTL                        = 30000;
793    fSplitMaxInputFileNumber    = 100;
794    fMaxInitFailed              = 0;
795    fMasterResubmitThreshold    = 0;
796    fRunNumbers                 = "";
797    fExecutable                 = "analysis.sh";
798    fArguments                  = "";
799    fAnalysisMacro              = "myAnalysis.C";
800    fAnalysisSource             = "";
801    fAdditionalLibs             = "";
802    fSplitMode                  = "se";
803    fAPIVersion                 = "";
804    fROOTVersion                = "";
805    fAliROOTVersion             = "";
806    fUser                       = "";  // Your alien user name
807    fGridWorkingDir             = "";
808    fGridDataDir                = "";  // Can be like: /alice/sim/PDC_08a/LHC08c9/
809    fDataPattern                = "*AliESDs.root";  // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
810    fGridOutputDir              = "output";
811    fOutputArchive              = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
812    fOutputFiles                = "";  // Like "AliAODs.root histos.root"
813    fInputFormat                = "xml-single";
814    fJDLName                    = "analysis.jdl";
815 }   
816
817 //______________________________________________________________________________
818 Bool_t AliAnalysisAlien::MergeOutputs()
819 {
820 // Merge analysis outputs existing in the AliEn space.
821    if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
822    if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
823    if (!Connect()) {
824       Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
825       return kFALSE;
826    }   
827    // Get the output path
828    TString output = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
829    if (!gGrid->Cd(output)) output = Form("/%s/%s", gGrid->GetHomeDirectory(), fGridOutputDir.Data());
830    if (!gGrid->Cd(output)) {
831       Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
832       return kFALSE;
833    }
834    if (!fOutputFiles.Length()) {
835       Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
836       return kFALSE;
837    }   
838    TObjArray *list = fOutputFiles.Tokenize(" ");
839    TIter next(list);
840    TObjString *str;
841    TString command;
842    TString output_file;
843    Bool_t merged = kTRUE;
844    while((str=(TObjString*)next())) {
845       output_file = str->GetString();
846       Int_t index = output_file.Index("@");
847       if (index > 0) output_file.Remove(index);
848       command = Form("find %s/ *%s", output.Data(), output_file.Data());
849       printf("command: %s\n", command.Data());
850       TGridResult *res = gGrid->Command(command);
851       if (!res) continue;
852       TFileMerger *fm = 0;
853       TIter nextmap(res);
854       TMap *map;
855       while ((map=(TMap*)nextmap())) {
856          TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
857          if (!objs || !objs->GetString().Length()) {
858             delete res;
859             continue;
860          }   
861          if (!fm) {
862             fm = new TFileMerger(kFALSE);
863             fm->SetFastMethod(kTRUE);
864             fm->OutputFile(output_file);
865          }
866          fm->AddFile(objs->GetString());   
867       }
868       if (!fm || !fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
869          Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
870          merged = kFALSE;
871          delete res;
872          continue;
873       }
874       if (!fm->Merge()) {
875          Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
876          merged = kFALSE;
877       } else {
878          Info("MergeOutputs", "\n#####   Merged %d output files <%s>", fm->GetMergeList()->GetSize(), output_file.Data());
879       }   
880       delete fm;
881       delete res;
882    } 
883    if (!merged) {
884       Error("MergeOutputs", "Terminate() will  NOT be executed");
885    }  
886    return merged;
887 }   
888
889 //______________________________________________________________________________
890 void AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
891 {
892 // Start remote grid analysis.
893    
894    if (TestBit(AliAnalysisGrid::kOffline)) {
895       Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
896       \n                         there nor any job run. You can revise the JDL and analysis \
897       \n                         macro then run the same in \"submit\" mode.");
898    } else if (TestBit(AliAnalysisGrid::kTest)) {
899       Info("StartAnalysis","\n##### LOCAL MODE #####   Your analysis will be run locally on a subset of the requested \
900       \n                         dataset.");
901    } else if (TestBit(AliAnalysisGrid::kSubmit)) {
902       Info("StartAnalysis","\n##### SUBMIT MODE #####  Files required by your analysis are copied to your grid working \
903       \n                         space and job submitted.");
904    } else if (TestBit(AliAnalysisGrid::kMerge)) {
905       Info("StartAnalysis","\n##### MERGE MODE #####   The registered outputs of the analysis will be merged");
906       return;
907    } else {
908       Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");   
909    }   
910       
911    if (!Connect()) {
912       Error("StartAnalysis", "Cannot start grid analysis without grid connection");
913       return;
914    }   
915    if (!CheckInputData()) {
916       Error("StartAnalysis", "There was an error in preprocessing your requested input data");
917       return;
918    }   
919    CreateDataset(fDataPattern);
920    WriteAnalysisFile();   
921    WriteAnalysisMacro();
922    WriteExecutable();
923    WriteValidationScript();
924    if (!CreateJDL()) return;
925    if (TestBit(AliAnalysisGrid::kOffline)) return;
926    if (TestBit(AliAnalysisGrid::kTest)) {
927       // Locally testing the analysis
928       Info("StartAnalysis", "\n_______________________________________________________________________ \
929       \n   Running analysis script in a daughter shell as on a worker node \
930       \n_______________________________________________________________________");
931       TObjArray *list = fOutputFiles.Tokenize(" ");
932       TIter next(list);
933       TObjString *str;
934       TString output_file;
935       while((str=(TObjString*)next())) {
936          output_file = str->GetString();
937          Int_t index = output_file.Index("@");
938          if (index > 0) output_file.Remove(index);         
939          gSystem->Exec(Form("rm %s", output_file.Data()));
940       }
941       delete list;
942       gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
943       gSystem->Exec("bash validate.sh");
944 //      gSystem->Exec("cat stdout");
945       return;
946    }
947    // Submit AliEn job
948    CdWork();
949    TGridResult *res = gGrid->Command(Form("submit %s", fJDLName.Data()));
950    TString jobID = "";
951    if (res) {
952       const char *cjobId = res->GetKey(0,"jobId");
953       if (!cjobId) {
954          Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
955          return;
956       } else {
957          Info("StartAnalysis", "\n_______________________________________________________________________ \
958          \n#####   Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
959       \n_______________________________________________________________________",
960                 fJDLName.Data(), cjobId);
961          jobID = cjobId;      
962       }          
963       delete res;
964    }   
965    Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
966    \n You may exit at any time and terminate the job later using the option <terminate> \
967    \n ##################################################################################", jobID.Data());
968    gGrid->Shell();
969 }
970
971 //______________________________________________________________________________
972 void AliAnalysisAlien::WriteAnalysisFile()
973 {
974 // Write current analysis manager into the file analysis.root
975    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
976       AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
977       if (!mgr || !mgr->IsInitialized()) {
978          Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
979          return;
980       }
981       // Check analysis type
982       TObject *handler;
983       if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
984       handler = (TObject*)mgr->GetInputEventHandler();
985       if (handler) {
986          if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
987          if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
988       }
989       TDirectory *cdir = gDirectory;
990       TFile *file = TFile::Open("analysis.root", "RECREATE");
991       if (file) {
992          mgr->Write();
993          delete file;
994       }
995       if (cdir) cdir->cd();
996       Info("WriteAnalysisFile", "\n#####   Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
997    }   
998    Bool_t copy = kTRUE;
999    if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1000    if (copy) {
1001       CdWork();
1002       TString workdir = gGrid->GetHomeDirectory();
1003       workdir += fGridWorkingDir;
1004       Info("CreateJDL", "\n#####   Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1005       if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1006       TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1007    }   
1008 }
1009
1010 //______________________________________________________________________________
1011 void AliAnalysisAlien::WriteAnalysisMacro()
1012 {
1013 // Write the analysis macro that will steer the analysis in grid mode.
1014    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
1015       ofstream out;
1016       out.open(fAnalysisMacro.Data(), ios::out);
1017       if (!out.good()) {
1018          Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1019          return;
1020       }
1021       TString func = fAnalysisMacro;
1022       TString type = "ESD";
1023       TString comment = "// Analysis using ";
1024       if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1025       if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1026          type = "AOD";
1027          comment += "AOD";
1028       }   
1029       if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1030       else comment += " data";
1031       out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1032       func.ReplaceAll(".C", "");
1033       out << "void " << func.Data() << "()" << endl; 
1034       out << "{" << endl;
1035       out << comment.Data() << endl;
1036       out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1037       out << "// load base root libraries" << endl;
1038       out << "   gSystem->Load(\"libTree\");" << endl;
1039       out << "   gSystem->Load(\"libGeom\");" << endl;
1040       out << "   gSystem->Load(\"libVMC\");" << endl;
1041       out << "   gSystem->Load(\"libPhysics\");" << endl << endl;
1042       if (!fPackages) {
1043          out << "// Load analysis framework libraries" << endl;
1044          out << "   gSystem->Load(\"libSTEERBase\");" << endl;
1045          out << "   gSystem->Load(\"libESD\");" << endl;
1046          out << "   gSystem->Load(\"libAOD\");" << endl;
1047          out << "   gSystem->Load(\"libANALYSIS\");" << endl;
1048          out << "   gSystem->Load(\"libANALYSISalice\");" << endl << endl;
1049          out << "// include path (remove if using par files)" << endl;
1050          out << "   gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl << endl;
1051       } else {
1052          out << "// Compile all par packages" << endl;
1053          TIter next(fPackages);
1054          TObject *obj;
1055          while ((obj=next())) 
1056             out << "   if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1057       }   
1058       if (fAdditionalLibs.Length()) {
1059          out << "// Add aditional AliRoot libraries" << endl;
1060          TObjArray *list = fAdditionalLibs.Tokenize(" ");
1061          TIter next(list);
1062          TObjString *str;
1063          while((str=(TObjString*)next())) {
1064             if (str->GetString().Contains(".so"))
1065                out << "   gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1066          }
1067          if (list) delete list;
1068       }
1069       out << endl;
1070       out << "// analysis source to be compiled at runtime (if any)" << endl;
1071       if (fAnalysisSource.Length()) {
1072          TObjArray *list = fAnalysisSource.Tokenize(" ");
1073          TIter next(list);
1074          TObjString *str;
1075          while((str=(TObjString*)next())) {
1076             out << "   gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1077          }   
1078          if (list) delete list;
1079       }
1080       out << endl;
1081       out << "// connect to AliEn and make the chain" << endl;
1082       out << "   if (!TGrid::Connect(\"alien://\")) return;" << endl;
1083       if (IsUsingTags()) {
1084          out << "   TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1085       } else {
1086          out << "   TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;      
1087       }   
1088       out << "// read the analysis manager from file" << endl;
1089       out << "   TFile *file = TFile::Open(\"analysis.root\");" << endl;
1090       out << "   if (!file) return;" << endl; 
1091       out << "   TIter nextkey(file->GetListOfKeys());" << endl;
1092       out << "   AliAnalysisManager *mgr = 0;" << endl;
1093       out << "   TKey *key;" << endl;
1094       out << "   while ((key=(TKey*)nextkey())) {" << endl;
1095       out << "      if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1096       out << "         mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1097       out << "   };" << endl;
1098       out << "   if (!mgr) {" << endl;
1099       out << "      ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1100       out << "      return;" << endl;
1101       out << "   }" << endl << endl;
1102       out << "   mgr->PrintStatus();" << endl;
1103       out << "   mgr->StartAnalysis(\"localfile\", chain);" << endl;
1104       out << "}" << endl << endl;
1105       if (IsUsingTags()) {
1106          out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1107          out << "{" << endl;
1108          out << "// Create a chain using tags from the xml file." << endl;
1109          out << "   TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1110          out << "   if (!coll) {" << endl;
1111          out << "      ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1112          out << "      return NULL;" << endl;
1113          out << "   }" << endl;
1114          out << "   TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1115          out << "   AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1116          out << "   tagAna->ChainGridTags(tagResult);" << endl << endl;
1117          out << "   AliRunTagCuts      *runCuts = new AliRunTagCuts();" << endl;
1118          out << "   AliLHCTagCuts      *lhcCuts = new AliLHCTagCuts();" << endl;
1119          out << "   AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1120          out << "   AliEventTagCuts    *evCuts  = new AliEventTagCuts();" << endl;
1121          out << "   // Check if the cuts configuration file was provided" << endl;
1122          out << "   if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1123          out << "      gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1124          out << "      ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1125          out << "   }" << endl;
1126          out << "   TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1127          out << "   if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1128          out << "   chain->ls();" << endl;
1129          out << "   return chain;" << endl;
1130          out << "}" << endl;
1131          if (gSystem->AccessPathName("ConfigureCuts.C")) {
1132             TString msg = "\n#####   You may want to provide a macro ConfigureCuts.C with a method:\n";
1133             msg += "   void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1134             msg += "                      AliLHCTagCuts *lhcCuts,\n";
1135             msg += "                      AliDetectorTagCuts *detCuts,\n";
1136             msg += "                      AliEventTagCuts *evCuts)";
1137             Info("WriteAnalysisMacro", msg.Data());
1138          }
1139       } else {
1140          out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1141          out << "{" << endl;
1142          out << "// Create a chain using url's from xml file" << endl;
1143          out << "   TString treename = type;" << endl;
1144          out << "   treename.ToLower();" << endl;
1145          out << "   treename += \"Tree\";" << endl;
1146          out << "   printf(\"***************************************\");" << endl;
1147          out << "   printf(\"    Getting chain of trees %s\\n\", treename);" << endl;
1148          out << "   printf(\"***************************************\");" << endl;
1149          out << "   TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1150          out << "   if (!coll) {" << endl;
1151          out << "      ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1152          out << "      return NULL;" << endl;
1153          out << "   }" << endl;
1154          out << "   TChain *chain = new TChain(treename);" << endl;
1155          out << "   coll->Reset();" << endl;
1156          out << "   while (coll->Next()) chain->Add(coll->GetTURL(\"\"));" << endl;
1157          out << "   if (!chain->GetNtrees()) {" << endl;
1158          out << "      ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1159          out << "      return NULL;" << endl;
1160          out << "   }" << endl;
1161          out << "   return chain;" << endl;
1162          out << "}" << endl;
1163       }   
1164       if (fPackages) {
1165          out << "Bool_t SetupPar(const char *package) {" << endl;
1166          out << "// Compile the package and set it up." << endl;
1167          out << "   TString pkgdir = package;" << endl;
1168          out << "   pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1169          out << "   gSystem->Exec(Form(\"tar xvzf %s\", package));" << endl;
1170          out << "   TString cdir = gSystem->WorkingDirectory();" << endl;
1171          out << "   gSystem->ChangeDirectory(pkgdir);" << endl;
1172          out << "   // Check for BUILD.sh and execute" << endl;
1173          out << "   if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1174          out << "      printf(\"*******************************\\n\");" << endl;
1175          out << "      printf(\"*** Building PAR archive    ***\\n\");" << endl;
1176          out << "      printf(\"*******************************\\n\");" << endl;
1177          out << "      if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1178          out << "         ::Error(\"SetupPar\", \"Cannot build par archive %s\", package);" << endl;
1179          out << "         gSystem->ChangeDirectory(cdir);" << endl;
1180          out << "         return kFALSE;" << endl;
1181          out << "      }" << endl;
1182          out << "   } else {" << endl;
1183          out << "      ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", package);" << endl;
1184          out << "      gSystem->ChangeDirectory(cdir);" << endl;
1185          out << "      return kFALSE;" << endl;
1186          out << "   }" << endl;
1187          out << "   // Check for SETUP.C and execute" << endl;
1188          out << "   if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1189          out << "      printf(\"*******************************\\n\");" << endl;
1190          out << "      printf(\"***    Setup PAR archive    ***\\n\");" << endl;
1191          out << "      printf(\"*******************************\\n\");" << endl;
1192          out << "      gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1193          out << "   } else {" << endl;
1194          out << "      ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", package);" << endl;
1195          out << "      gSystem->ChangeDirectory(cdir);" << endl;
1196          out << "      return kFALSE;" << endl;
1197          out << "   }" << endl;
1198          out << "   // Restore original workdir" << endl;
1199          out << "   gSystem->ChangeDirectory(cdir);" << endl;
1200          out << "   return kTRUE;" << endl;
1201          out << "}" << endl;
1202       }
1203       Info("WriteAnalysisMacro", "\n#####   Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1204    }   
1205    Bool_t copy = kTRUE;
1206    if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1207    if (copy) {
1208       CdWork();
1209       TString workdir = gGrid->GetHomeDirectory();
1210       workdir += fGridWorkingDir;
1211       if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1212       if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1213          if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1214          Info("WriteAnalysisMacro", "\n#####   Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1215          TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1216       }   
1217       Info("WriteAnalysisMacro", "\n#####   Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1218       TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1219    }
1220 }
1221
1222 //______________________________________________________________________________
1223 void AliAnalysisAlien::WriteExecutable()
1224 {
1225 // Generate the alien executable script.
1226    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
1227       ofstream out;
1228       out.open(fExecutable.Data(), ios::out);
1229       if (out.bad()) {
1230          Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1231          return;
1232       }
1233       out << "#!/bin/bash" << endl;
1234       out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1235       out << "echo \"=========================================\"" << endl; 
1236       out << "echo \"############## PATH : ##############\"" << endl;
1237       out << "echo $PATH" << endl;
1238       out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1239       out << "echo $LD_LIBRARY_PATH" << endl;
1240       out << "echo \"############## ROOTSYS : ##############\"" << endl;
1241       out << "echo $ROOTSYS" << endl;
1242       out << "echo \"############## which root : ##############\"" << endl;
1243       out << "which root" << endl;
1244       out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1245       out << "echo $ALICE_ROOT" << endl;
1246       out << "echo \"############## which aliroot : ##############\"" << endl;
1247       out << "which aliroot" << endl;
1248       out << "echo \"=========================================\"" << endl << endl;
1249 //      if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1250       out << "root -b -q "; 
1251       out << fAnalysisMacro.Data() << endl << endl;
1252       out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1253    }   
1254    Bool_t copy = kTRUE;
1255    if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1256    if (copy) {
1257       CdWork();
1258       TString workdir = gGrid->GetHomeDirectory();
1259       workdir += fGridWorkingDir;
1260       TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1261       if (FileExists(executable)) gGrid->Rm(executable);
1262       Info("CreateJDL", "\n#####   Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1263       TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1264    } 
1265 }
1266
1267 //______________________________________________________________________________
1268 void AliAnalysisAlien::WriteValidationScript()
1269 {
1270 // Generate the alien validation script.
1271    // Generate the validation script
1272    TObjString *os;
1273    if (!Connect()) {
1274       Error("WriteValidationScript", "Alien connection required");
1275       return;
1276    }
1277    TString out_stream = "";
1278    if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1279    if (!TestBit(AliAnalysisGrid::kSubmit)) {  
1280       ofstream out;
1281       out.open("validate.sh", ios::out);
1282       out << "#!/bin/bash" << endl;
1283       out << "##################################################" << endl;
1284       out << "validateout=`dirname $0`" << endl;
1285       out << "validatetime=`date`" << endl;
1286       out << "validated=\"0\";" << endl;
1287       out << "error=0" << endl;
1288       out << "if [ -z $validateout ]" << endl;
1289       out << "then" << endl;
1290       out << "    validateout=\".\"" << endl;
1291       out << "fi" << endl << endl;
1292       out << "cd $validateout;" << endl;
1293       out << "validateworkdir=`pwd`;" << endl << endl;
1294       out << "echo \"*******************************************************\"" << out_stream << endl;
1295       out << "echo \"* Automatically generated validation script           *\""  << out_stream << endl;
1296       out << "" << endl;
1297       out << "echo \"* Time:    $validatetime \""  << out_stream << endl;
1298       out << "echo \"* Dir:     $validateout\""  << out_stream << endl;
1299       out << "echo \"* Workdir: $validateworkdir\""  << out_stream << endl;
1300       out << "echo \"* ----------------------------------------------------*\""  << out_stream << endl;
1301       out << "ls -la ./"  << out_stream << endl;
1302       out << "echo \"* ----------------------------------------------------*\""  << out_stream << endl << endl;
1303       out << "##################################################" << endl;
1304       TObjArray *arr = fOutputFiles.Tokenize(" ");
1305       TIter next1(arr);
1306       TString output_file;
1307       while ((os=(TObjString*)next1())) { 
1308          output_file = os->GetString();
1309          Int_t index = output_file.Index("@");
1310          if (index > 0) output_file.Remove(index);
1311          out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1312          out << "   error=1" << endl;
1313          out << "   echo \"Output file(s) not found. Job FAILED !\""  << out_stream << endl;
1314          out << "   echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
1315          out << "fi" << endl;
1316       }   
1317       delete arr;
1318       out << "if [ $error = 0 ] ; then" << endl;
1319       out << "   echo \"* ----------------   Job Validated  ------------------*\""  << out_stream << endl;
1320       out << "fi" << endl;
1321
1322       out << "echo \"* ----------------------------------------------------*\""  << out_stream << endl;
1323       out << "echo \"*******************************************************\""  << out_stream << endl;
1324       out << "cd -" << endl;
1325       out << "exit $error" << endl;
1326    }    
1327    Bool_t copy = kTRUE;
1328    if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1329    if (copy) {
1330       CdWork();
1331       TString workdir = gGrid->GetHomeDirectory();
1332       workdir += fGridWorkingDir;
1333       Info("CreateJDL", "\n#####   Copying validation script <validate.sh> to your AliEn working space");
1334       if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
1335       TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));
1336    } 
1337 }