a5b6610e06d5c87fb002445001418ece813a70ea
[u/mrichter/AliRoot.git] / PWG / muondep / AliMuonAccEffSubmitter.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 //
17 // AliMuonAccEffSubmitter : a class to help submit Acc x Eff simulations
18 // anchored to real runs for J/psi, upsilon, single muons, etc...
19 //
20 // This class is dealing with 3 different directories :
21 //
22 // - template directory ($ALICE_ROOT/PWG/muondep/AccEffTemplates) containing the
23 //   basic template files to be used for a simuation. A template can contain
24 //   some variables that will be replaced during during the copy from template
25 //   to local dir
26 //
27 // - local directory, where the files from the template directory, are copied
28 //   once the class has been configured properly (i.e. using the various Set, Use,
29 //   etc... methods). Some other files (e.g. JDL ones) are generated from
30 //   scratch and also copied into this directory.
31 //   At this point one could(should) check the files, as they are the ones
32 //   to be copied to the remote directory for the production
33 //
34 // - remote directory, the alien directory where the files will be copied
35 //   (from the local directory) before the actual submission
36 //
37 // ==========================================================
38 //
39 // Basic usage
40 //
41 // AliMuonAccEffSubmitter a;
42 // a.UseOCDBSnapshots(kFALSE);
43 // a.SetRemoteDir("/alice/cern.ch/user/l/laphecet/Analysis/LHC13d/simjpsi/pp503z0");
44 // a.ShouldOverwriteFiles(true);
45 // a.MakeNofEventsPropToTriggerCount("CMUL7-B-NOPF-MUON");
46 // a.SetVar("VAR_GENLIB_PARNAME","\"pp 5.03\"");
47 // a.SetRunList(195682);
48 // a.Print();
49 // a.Run("test"); // will do everything but the submit
50 // a.Submit(false); // actual submission
51 //
52 //
53 // author: Laurent Aphecetche (Subatech
54 //
55
56 #include "AliMuonAccEffSubmitter.h"
57
58 #include "AliAnalysisTriggerScalers.h"
59 #include "AliLog.h"
60 #include "TFile.h"
61 #include "TGrid.h"
62 #include "TGridResult.h"
63 #include "TMap.h"
64 #include "TMath.h"
65 #include "TObjString.h"
66 #include "TROOT.h"
67 #include "TString.h"
68 #include "TSystem.h"
69 #include <vector>
70 #include <fstream>
71 using std::ifstream;
72 namespace
73 {
74   Int_t splitLevel=10;
75 }
76
77 //______________________________________________________________________________
78 AliMuonAccEffSubmitter::AliMuonAccEffSubmitter(const char* generator)
79 : TObject(),
80 fScalers(0x0),
81 fRemoteDir(""),
82 fReferenceTrigger(""),
83 fRatio(1.0),
84 fFixedNofEvents(10000),
85 fMaxEventsPerChunk(5000),
86 fLocalDir(gSystem->pwd()),
87 fOCDBPath("raw://"),
88 fTemplateDir(gSystem->ExpandPathName("$ALICE_ROOT/PWG/muondep/AccEffTemplates")),
89 fPackageAliroot(),
90 fPackageGeant3(),
91 fPackageRoot(),
92 fPackageApi(),
93 fMergedDir(Form("%s/AODs",fRemoteDir.Data())),
94 fSplitMaxInputFileNumber(20),
95 fCompactMode(1),
96 fShouldOverwriteFiles(kFALSE),
97 fVars(0x0),
98 fExternalConfig(""),
99 fUseOCDBSnapshots(kTRUE),
100 fIsValid(kFALSE),
101 fTemplateFileList(0x0),
102 fLocalFileList(0x0),
103 fSnapshotDir(fLocalDir),
104 fUseAODMerging(kFALSE)
105 {
106   // ctor
107   
108   if (!TGrid::Connect("alien://"))
109   {
110     AliError("cannot connect to grid");
111     fIsValid = kFALSE;
112   }
113
114   SetPackages("VO_ALICE@AliRoot::v5-03-Rev-18","VO_ALICE@GEANT3::v1-14-8","VO_ALICE@ROOT::v5-34-05-1");
115   
116   SetVar("VAR_OCDB_PATH","\"raw://\"");
117
118   SetVar("VAR_GENPARAM_GENLIB_TYPE","AliGenMUONlib::kJpsi");
119   SetVar("VAR_GENPARAM_GENLIB_PARNAME","\"pPb 5.03\"");
120
121   SetVar("VAR_GENCORRHF_QUARK","5");
122   SetVar("VAR_GENCORRHF_ENERGY","5");
123
124   // some default values for J/psi
125   SetVar("VAR_GENPARAMCUSTOM_PDGPARTICLECODE","443");
126
127   // default values below are from J/psi p+Pb (from muon_calo pass)
128   SetVar("VAR_GENPARAMCUSTOM_Y_P0","4.08E5");
129   SetVar("VAR_GENPARAMCUSTOM_Y_P1","7.1E4");
130   
131   SetVar("VAR_GENPARAMCUSTOM_PT_P0","1.13E9");
132   SetVar("VAR_GENPARAMCUSTOM_PT_P1","18.05");
133   SetVar("VAR_GENPARAMCUSTOM_PT_P2","2.05");
134   SetVar("VAR_GENPARAMCUSTOM_PT_P3","3.34");
135
136   // some default values for single muons
137   SetVar("VAR_GENPARAMCUSTOMSINGLE_PTMIN","0.35");
138   
139   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P0","4.05962");
140   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P1","1.0");
141   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P2","2.46187");
142   SetVar("VAR_GENPARAMCUSTOMSINGLE_PT_P3","2.08644");
143
144   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P0","0.729545");
145   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P1","0.53837");
146   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P2","0.141776");
147   SetVar("VAR_GENPARAMCUSTOMSINGLE_Y_P3","0.0130173");
148
149   UseOCDBSnapshots(kTRUE);
150   
151   SetGenerator(generator);
152 }
153
154 //______________________________________________________________________________
155 AliMuonAccEffSubmitter::~AliMuonAccEffSubmitter()
156 {
157   // dtor
158   delete fScalers;
159   delete fTemplateFileList;
160   delete fLocalFileList;
161   delete fVars;
162 }
163
164 //______________________________________________________________________________
165 Bool_t AliMuonAccEffSubmitter::CheckCompilation(const char* file) const
166 {
167   /// Check whether file can be compiled or not
168   /// FIXME: use gSystem->TempFileName for tmpfile !
169   
170   Bool_t rv(kTRUE);
171   
172   TString sfile(gSystem->BaseName(file));
173   TString tmpfile(Form("tmpfile_%s",sfile.Data()));
174   
175   gSystem->Exec(Form("cp %s %s",file,tmpfile.Data()));
176   
177   ReplaceVars(tmpfile.Data());
178   
179   gSystem->AddIncludePath("-I$ALICE_ROOT/include");
180   gSystem->AddIncludePath("-I$ALICE_ROOT/EVGEN");
181
182   if (gROOT->LoadMacro(Form("%s++",tmpfile.Data())))
183   {
184     AliError(Form("macro %s can not be compiled. Please check.",file));
185     rv = kFALSE;
186   }
187   
188   gSystem->Exec(Form("rm %s",tmpfile.Data()));
189   
190   return rv;
191 }
192
193
194 //______________________________________________________________________________
195 Bool_t AliMuonAccEffSubmitter::CheckLocal() const
196 {
197   /// Check whether all required local files are there
198   TIter next(LocalFileList());
199   TObjString* file;
200   
201   while ( ( file = static_cast<TObjString*>(next())) )
202   {
203       if ( gSystem->AccessPathName(file->String().Data()) )
204       {
205         return kFALSE;
206       }
207   }
208   
209   return kTRUE;
210 }
211
212 //______________________________________________________________________________
213 Bool_t AliMuonAccEffSubmitter::CheckRemote() const
214 {
215   /// Check whether all required remote files are there
216   AliWarning("implement me");
217   return kFALSE;
218 }
219
220 //______________________________________________________________________________
221 void AliMuonAccEffSubmitter::CleanLocal(Bool_t cleanSnapshots) const
222 {
223   /// Clean (remove) local generated files
224   /// As OCDB snapshot creation is a long process, cleanSnapshots
225   /// is kFALSE by default in order not to delete those.
226   
227   TIter next(LocalFileList());
228   TObjString* file;
229   
230   while ( ( file = static_cast<TObjString*>(next())) )
231   {
232     if ( !cleanSnapshots && file->String().Contains("OCDB_") ) continue;
233     gSystem->Unlink(file->String().Data());
234   }
235 }
236
237 //______________________________________________________________________________
238 void AliMuonAccEffSubmitter::CleanRemote() const
239 {
240   /// Clean (remove) remote files
241   AliWarning("implement me");
242 }
243
244 //______________________________________________________________________________
245 Bool_t AliMuonAccEffSubmitter::CopyFile(const char* localFile)
246 {
247   /// copy a local file to remote destination
248   TString local;
249   
250   if ( gSystem->IsAbsoluteFileName(localFile) )
251   {
252     local = localFile;
253   }
254   else
255   {
256     local = Form("%s/%s",fLocalDir.Data(),gSystem->ExpandPathName(localFile));
257   }
258   
259   if (gSystem->AccessPathName(local.Data()))
260   {
261     AliError(Form("Local file %s does not exist",local.Data()));
262     return kFALSE;
263   }
264   
265   TString remote;
266   
267   remote += fRemoteDir;
268   remote += "/";
269   
270   if ( gSystem->IsAbsoluteFileName(localFile) )
271   {
272     TString tmp(localFile);
273     tmp.ReplaceAll(fSnapshotDir.Data(),"");
274     remote += tmp;
275   }
276   else
277   {
278     remote += localFile;
279   }
280   
281   TString dirName = gSystem->DirName(remote.Data());
282   
283   Bool_t ok(kTRUE);
284   
285   if (!RemoteDirectoryExists(dirName.Data()))
286   {
287     ok = gGrid->Mkdir(dirName.Data(),"-p");
288   }
289   
290   if ( ok )
291   {
292     AliDebug(1,Form("cp %s alien://%s",local.Data(),remote.Data()));
293     return TFile::Cp(local.Data(),Form("alien://%s",remote.Data()));
294   }
295   else
296   {
297     return kFALSE;
298   }
299 }
300
301 //______________________________________________________________________________
302 Bool_t AliMuonAccEffSubmitter::CheckRemoteDir() const
303 {
304   /// Check we have a grid connection and that the remote dir exists
305   
306   if (fRemoteDir.IsNull())
307   {
308     AliError("you must provide the grid location where to copy the files");
309     return kFALSE;
310   }
311   
312   // connect to alien
313   if (!gGrid)
314   {
315     if (!TGrid::Connect("alien://"))
316     {
317       AliError("Cannot connect to grid");
318       return kFALSE;
319     }
320   }
321   
322   if (!RemoteDirectoryExists(fRemoteDir))
323   {
324     AliError(Form("directory %s does not exist", fRemoteDir.Data()));
325     return kFALSE;
326   }
327
328   return kTRUE;
329 }
330
331 //______________________________________________________________________________
332 Bool_t AliMuonAccEffSubmitter::CopyLocalFilesToRemote()
333 {
334   /// copy all files necessary to run the simulation into remote directory
335   
336   if (!IsValid()) return kFALSE;
337   
338   AliDebug(1,"");
339   
340   if ( CheckRemoteDir() )
341   {
342     TString sdir(gSystem->ExpandPathName(LocalDir()));
343   
344     TIter next(LocalFileList());
345     TObjString* ftc;
346   
347     Bool_t allok(kTRUE);
348   
349     while ( ( ftc = static_cast<TObjString*>(next())) )
350     {
351       allok = allok && CopyFile(ftc->String());
352     }
353     return allok;
354   }
355   
356   return kFALSE;
357 }
358
359 //______________________________________________________________________________
360 Bool_t AliMuonAccEffSubmitter::CopyTemplateFilesToLocal()
361 {
362   // copy (or generate) local files from the template ones
363   
364   if (!IsValid()) return kFALSE;
365
366   AliDebug(1,"");
367
368   TIter next(TemplateFileList());
369   TObjString* file;
370   
371   Int_t err(0);
372   Bool_t potentialProblem(kFALSE);
373   
374   while ( ( file = static_cast<TObjString*>(next())) )
375   {
376     if ( file->String().Contains("OCDB") )
377     {
378       /// OCDB snapshots are not in template
379       continue;
380     }
381
382     if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(file->String().Data()) )
383     {
384       AliError(Form("Local file %s already exists. Remove it first if you want to update overwrite it",file->String().Data()));
385       potentialProblem = kTRUE;
386     }
387     else
388     {
389       TString stemplate(Form("%s/%s",fTemplateDir.Data(),file->String().Data()));
390       TString slocal(Form("%s/%s",fLocalDir.Data(),file->String().Data()));
391       
392       Int_t c =  gSystem->CopyFile(stemplate.Data(),slocal.Data(),ShouldOverwriteFiles());
393       if ( c )
394       {
395         Bool_t ok(kFALSE);
396         if ( stemplate.Contains(".jdl",TString::kIgnoreCase) )
397         {
398           if ( stemplate.Contains("merge",TString::kIgnoreCase) )
399           {
400             ok = GenerateMergeJDL(file->String().Data());
401           }
402           else
403           {
404             ok = GenerateRunJDL(file->String().Data());
405           }
406         }
407         if (!ok)
408         {
409           AliError(Form("Error %d copying file %s",c,stemplate.Data()));
410         }
411         else
412         {
413           c=0;
414         }
415       }
416       else
417       {
418         if ( HasVars(slocal.Data()) )
419         {
420           if (!ReplaceVars(slocal.Data()))
421           {
422             AliError("pb in ReplaceVars");
423             c=1;
424           }
425         }
426       }
427       err += c;
428     }
429   }
430   
431   if ( potentialProblem )
432   {
433     AliWarning("At least one local file could not be overwritten. Cross-check that the local files are OK before we try to upload them to the Grid !");
434     return kFALSE;
435   }
436   return (err==0);
437 }
438
439 //______________________________________________________________________________
440 std::ostream* AliMuonAccEffSubmitter::CreateJDLFile(const char* name) const
441 {
442   /// Create a JDL file
443   AliDebug(1,"");
444
445   TString jdl(Form("%s/%s",fLocalDir.Data(),name));
446   
447   if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(jdl.Data()) )
448   {
449     AliError(Form("File %s already exists. Remove it if you want to overwrite it",jdl.Data()));
450     return 0x0;
451   }
452   
453   std::ofstream* os = new std::ofstream(gSystem->ExpandPathName(jdl.Data()));
454   
455   if (os->bad())
456   {
457     AliError(Form("Cannot create file %s",jdl.Data()));
458     delete os;
459     os=0x0;
460   }
461   
462   return os;
463 }
464
465 ///______________________________________________________________________________
466 Bool_t AliMuonAccEffSubmitter::GenerateMergeJDL(const char* name)
467 {
468   /// Create the JDL for merging jobs
469   /// FIXME: not checked !
470   
471   AliDebug(1,"");
472
473   std::ostream* os = CreateJDLFile(name);
474   
475   if (!os)
476   {
477     return kFALSE;
478   }
479   
480   Bool_t final = TString(name).Contains("merge",TString::kIgnoreCase);
481
482   (*os) << "# Generated merging jdl (production mode)" << std::endl
483   << "# $1 = run number" << std::endl
484   << "# $2 = merging stage" << std::endl
485   << "# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip" << std::endl;
486
487   Output(*os,"Packages",fPackageAliroot.Data(),fPackageGeant3.Data(),
488          fPackageRoot.Data(),fPackageApi.Data());
489   
490   Output(*os,"Executable","AOD_merge.sh");
491   
492   Output(*os,"Price","1");
493
494   if ( final )
495   {
496     Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter final merging");
497   }
498   else
499   {
500     Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter merging stage $2");
501   }
502   
503   Output(*os,"Workdirectorysize","5000MB");
504   
505   Output(*os,"Validationcommand",Form("%s/validation_merge.sh",fRemoteDir.Data()));
506   
507   Output(*os,"TTL","7200");
508
509   Output(*os,"OutputArchive",
510     "log_archive.zip:stderr,stdout@disk=1",
511     "root_archive.zip:AliAOD.root,AliAOD.Muons.root,AnalysisResults.root@disk=3"
512          );
513   
514   Output(*os,"Arguments",(final ? "2":"1")); // for AOD_merge.sh, 1 means intermediate merging stage, 2 means final merging
515   
516   if ( !final )
517   {
518     Output(*os,"InputFile",Form("LF:%s/AODtrain.C",fRemoteDir.Data()));
519     Output(*os,"OutputDir",Form("%s/$1/Stage_$2/#alien_counter_03i#",fRemoteDir.Data()));
520     Output(*os,"InputDataCollection",Form("%s/$1/Stage_$2.xml,nodownload",fRemoteDir.Data()));
521     Output(*os,"split","se");
522     Output(*os,"SplitMaxInputFileNumber",GetSplitMaxInputFileNumber());
523     Output(*os,"InputDataListFormat","xml-single");
524     Output(*os,"InputDataList","wn.xml");
525   }
526   else
527   {
528     Output(*os,"InputFile",Form("LF:%s/AODtrain.C",fRemoteDir.Data()),
529            Form("LF:%s/$1/wn.xml",fRemoteDir.Data()));
530     Output(*os,"OutputDir",Form("%s/$1",fRemoteDir.Data()));
531   }
532   
533   return kTRUE;
534 }
535
536 //______________________________________________________________________________
537 Bool_t AliMuonAccEffSubmitter::GenerateRunJDL(const char* name)
538 {
539   /// Generate (locally) the JDL to perform the simulation+reco+aod filtering
540   /// (to be then copied to the grid and finally submitted)
541   
542   AliDebug(1,"");
543
544   std::ostream* os = CreateJDLFile(name);
545   
546   if (!os)
547   {
548     return kFALSE;
549   }
550   
551   Output(*os,"Packages",fPackageAliroot.Data(),fPackageGeant3.Data(),
552          fPackageRoot.Data(),fPackageApi.Data());
553
554   Output(*os,"Jobtag","comment: AliMuonAccEffSubmitter RUN $1");
555
556   Output(*os,"split","production:1-$2");
557
558   Output(*os,"Price","1");
559   
560   Output(*os,"OutputDir",Form("%s/$1/#alien_counter_03i#",fRemoteDir.Data()));
561
562   Output(*os,"Executable","/alice/bin/aliroot_new");
563   
564   TObjArray files;
565   files.SetOwner(kTRUE);
566   TIter next(TemplateFileList());
567   TObjString* file;
568   
569   while ( ( file = static_cast<TObjString*>(next())) )
570   {
571     if ( !file->String().Contains(".jdl",TString::kIgnoreCase) ||
572          !file->String().Contains("OCDB_") )
573     {
574       files.Add(new TObjString(Form("LF:%s/%s",fRemoteDir.Data(),file->String().Data())));      
575     }
576   }
577   
578   if ( fUseOCDBSnapshots )
579   {
580     files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_sim.root",fRemoteDir.Data())));
581     files.Add(new TObjString(Form("LF:%s/OCDB/$1/OCDB_rec.root",fRemoteDir.Data())));
582   }
583   
584   Output(*os,"InputFile",files);
585   
586   if ( CompactMode() == 0 )
587   {
588     // store everything
589     Output(*os,"OutputArchive",  "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,sim.log@disk=1",
590            "root_archive.zip:galice*.root,Kinematics*.root,TrackRefs*.root,AliESDs.root,AliAOD.root,AliAOD.Muons.root,Merged.QA.Data.root,Run*.root@disk=2");
591   }
592   else if ( CompactMode() == 1 )
593   {
594     // keep only muon AODs
595     Output(*os,"OutputArchive",  "log_archive.zip:stderr,stdout,aod.log,checkaod.log,checkesd.log,rec.log,sim.log@disk=1",
596            "root_archive.zip:galice*.root,AliAOD.Muons.root@disk=2");
597   }
598   else
599   {
600     AliError(Form("Unknown CompactMode %d",CompactMode()));
601     delete os;
602     return kFALSE;
603   }
604   
605   Output(*os,"splitarguments","simrun.C --run $1 --chunk #alien_counter# --event $3");
606   
607   Output(*os,"Workdirectorysize","5000MB");
608   
609   Output(*os,"JDLVariables","Packages","OutputDir");
610
611   Output(*os,"Validationcommand",Form("%s/validation.sh",fRemoteDir.Data()));
612
613   Output(*os,"TTL","72000");
614   
615   return kTRUE;
616 }
617
618 //______________________________________________________________________________
619 Bool_t AliMuonAccEffSubmitter::GetLastStage(const char* remoteDir) const
620 {
621   /// Get the last staging phase already performed
622   /// FIXME : not checked !
623   
624   Int_t n = 0, lastStage = 0;
625   gSystem->Exec(Form("alien_ls -F %s | grep Stage_.*/ > __stage__", remoteDir));
626   ifstream f("__stage__");
627   std::string dummy;
628   while (std::getline(f, dummy)) n++;
629   f.close();
630   while (n > 0) if (gSystem->Exec(Form("grep Stage_%d/ __stage__ 2>&1 >/dev/null", ++lastStage)) == 0) n--;
631   gSystem->Exec("rm -f __stage__");
632   return lastStage;
633 }
634
635 //______________________________________________________________________________
636 TObjArray* AliMuonAccEffSubmitter::GetVariables(const char* file) const
637 {
638   /// Find the variables in the file
639   
640   std::ifstream in(file);
641   char line[1024];
642   TObjArray* variables(0x0);
643   
644   while ( in.getline(line,1023,'\n') )
645   {
646     TString sline(line);
647     while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
648     {
649       Int_t i1 = sline.Index("VAR_");
650       Int_t i2(i1);
651       
652       while ( ( i2 < sline.Length() ) && ( isalnum(sline[i2]) || sline[i2]=='_' ) ) ++i2;
653       
654       if (!variables)
655       {
656         variables = new TObjArray;
657         variables->SetOwner(kTRUE);
658       }
659       
660       TString var = sline(i1,i2-i1);
661       if ( !variables->FindObject(var) )
662       {
663         variables->Add(new TObjString(var));
664       }
665       sline.ReplaceAll(var,"");
666     }
667   }
668   
669   in.close();
670   
671   return variables;
672 }
673
674 //______________________________________________________________________________
675 Bool_t AliMuonAccEffSubmitter::HasVars(const char* file) const
676 {
677   /// Whether or not the file contains variables that have to
678   /// be substituted
679   
680   std::ifstream in(file);
681   char line[1024];
682   while ( in.getline(line,1023,'\n') )
683   {
684     TString sline(line);
685     if (sline.Contains("VAR_") && !sline.BeginsWith("//") )
686     {
687       return kTRUE;
688     }
689   }
690   return kFALSE;
691 }
692
693 //______________________________________________________________________________
694 TObjArray* AliMuonAccEffSubmitter::LocalFileList() const
695 {
696   /// Return (after createing and filling it if needed)
697   /// the internal file list with paths from the local directory
698   
699   if (!fLocalFileList)
700   {
701     fLocalFileList = static_cast<TObjArray*>(TemplateFileList()->Clone());
702   }
703   
704   return fLocalFileList;
705 }
706
707 //______________________________________________________________________________
708 Bool_t AliMuonAccEffSubmitter::MakeOCDBSnapshots()
709 {
710   /// Run sim.C and rec.C in a special mode to generate OCDB snapshots
711   /// Can only be done after the templates have been copied locally
712   
713   if (!IsValid()) return kFALSE;
714
715   if (!fUseOCDBSnapshots) return kTRUE;
716   
717   if (!fScalers) return kFALSE;
718   
719   AliDebug(1,"");
720
721   const std::vector<int>& runs = fScalers->GetRunList();
722
723   Bool_t ok(kTRUE);
724   
725   for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
726   {
727     Int_t runNumber = runs[i];
728
729     TString ocdbSim(Form("%s/OCDB/%d/OCDB_sim.root",SnapshotDir().Data(),runNumber));
730     TString ocdbRec(Form("%s/OCDB/%d/OCDB_rec.root",SnapshotDir().Data(),runNumber));
731
732     if ( !gSystem->AccessPathName(ocdbSim.Data()) &&
733          !gSystem->AccessPathName(ocdbRec.Data()) )
734     {
735       AliWarning(Form("Local OCDB snapshots already there for run %d. Will not redo them. If you want to force them, delete them by hand !",runNumber));
736       continue;
737     }
738     else
739     {
740       gSystem->Exec(Form("aliroot -b -q -x simrun.C --run %d --snapshot",runNumber));
741     
742       if ( gSystem->AccessPathName(ocdbSim.Data()) )
743       {
744         AliError(Form("Could not create OCDB snapshot for simulation"));
745         ok = kFALSE;
746       }
747
748       if ( gSystem->AccessPathName(ocdbRec.Data()) )
749       {
750         AliError(Form("Could not create OCDB snapshot for reconstruction"));
751         ok = kFALSE;
752       }
753     }
754     
755     LocalFileList()->Add(new TObjString(ocdbSim));
756     LocalFileList()->Add(new TObjString(ocdbRec));
757   }
758   
759   return ok;
760 }
761
762 //______________________________________________________________________________
763 Bool_t AliMuonAccEffSubmitter::Merge(Int_t stage, Bool_t dryRun)
764 {
765   /// Submit multiple merging jobs with the format "submit AOD_merge(_final).jdl run# (stage#)".
766   /// Also produce the xml collection before sending jobs
767   /// Initial AODs will be taken from fRemoteDir/[RUNNUMBER] while the merged
768   /// ones will be put into fMergedDir/AODs/[RUNNUMBER]
769   ///
770   /// Example:
771   /// - inDir = "/alice/sim/2012/LHC12a10_bis" (where to find the data to merge)
772   ///         = 0x0 --> inDir = homeDir/outDir/resDir
773   /// - outDir = "Sim/LHC11h/embedding/AODs" (where to store merged results)
774   /// - runList.txt must contains the list of run number
775   /// - stage=0 --> final merging / stage>0 --> intermediate merging i
776   ///
777   
778   if (!RemoteDirectoryExists(fMergedDir.Data())) {
779     AliError(Form("directory %s does not exist", fMergedDir.Data()));
780     return kFALSE;
781   }
782   
783   gGrid->Cd(fMergedDir.Data());
784   
785   TString jdl = MergeJDLName(stage==0);
786   
787   if (!RemoteFileExists(jdl.Data()))
788   {
789     AliError(Form("file %s does not exist in %s\n", jdl.Data(), fRemoteDir.Data()));
790     return kFALSE;
791   }
792   
793   const std::vector<int>& runs = fScalers->GetRunList();
794   
795   if (runs.empty())
796   {
797     AliError("No run to work with");
798     return kFALSE;
799   }
800
801   TString currRun;
802   TString reply = "";
803   gSystem->Exec("rm -f __failed__");
804   Bool_t failedRun = kFALSE;
805   
806   for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
807   {
808     Int_t run = runs[i];
809     AliInfo(Form("\n --- processing run %d ---\n", run));
810     
811     TString runDir = Form("%s/%d", fMergedDir.Data(), run);
812     
813     if (!RemoteDirectoryExists(runDir.Data()))
814     {
815       AliInfo(Form(" - creating output directory %s\n", runDir.Data()));
816       gSystem->Exec(Form("alien_mkdir -p %s", runDir.Data()));
817     }
818     
819     if (RemoteFileExists(Form("%s/root_archive.zip", runDir.Data())))
820     {
821       AliWarning(" ! final merging already done");
822       continue;
823     }
824     
825     Int_t lastStage = GetLastStage(runDir.Data());
826     
827     if (stage > 0 && stage != lastStage+1)
828     {
829       AliError(Form(" ! lastest merging stage = %d. Next must be stage %d or final stage\n", lastStage, lastStage+1));
830       continue;
831     }
832     
833     TString wn = (stage > 0) ? Form("Stage_%d.xml", stage) : "wn.xml";
834     TString find = (lastStage == 0) ?
835     Form("alien_find -x %s %s/%d *root_archive.zip", wn.Data(), fRemoteDir.Data(), run) :
836     Form("alien_find -x %s %s/%d/Stage_%d *root_archive.zip", wn.Data(), fRemoteDir.Data(), run, lastStage);
837     gSystem->Exec(Form("%s 1> %s 2>/dev/null", find.Data(), wn.Data()));
838     gSystem->Exec(Form("grep -c /event %s > __nfiles__", wn.Data()));
839     ifstream f2("__nfiles__");
840     TString nFiles;
841     nFiles.ReadLine(f2,kTRUE);
842     f2.close();
843     gSystem->Exec("rm -f __nfiles__");
844     printf(" - number of files to merge = %d\n", nFiles.Atoi());
845     if (nFiles.Atoi() == 0) {
846       printf(" ! collection of files to merge is empty\n");
847       gSystem->Exec(Form("rm -f %s", wn.Data()));
848       continue;
849     } else if (stage > 0 && nFiles.Atoi() <= splitLevel && !reply.BeginsWith("y")) {
850       if (!reply.BeginsWith("n")) {
851         printf(" ! number of files to merge <= split level (%d). Continue? [Y/n] ", splitLevel);
852         fflush(stdout);
853         reply.Gets(stdin,kTRUE);
854         reply.ToLower();
855       }
856       if (reply.BeginsWith("n")) {
857         gSystem->Exec(Form("rm -f %s", wn.Data()));
858         continue;
859       } else reply = "y";
860     }
861     
862     if (!dryRun)
863     {
864       TString dirwn = Form("%s/%s", runDir.Data(), wn.Data());
865       if (RemoteFileExists(dirwn.Data())) gGrid->Rm(dirwn.Data());
866       gSystem->Exec(Form("alien_cp file:%s alien://%s", wn.Data(), dirwn.Data()));
867       gSystem->Exec(Form("rm -f %s", wn.Data()));
868     }
869     
870     TString query;
871     if (stage > 0) query = Form("submit %s %d %d", jdl.Data(), run, stage);
872     else query = Form("submit %s %d", jdl.Data(), run);
873     printf(" - %s ...", query.Data());
874     fflush(stdout);
875     
876     if (dryRun)
877     {
878       AliInfo(" dry run");
879       continue;
880     }
881     
882     Bool_t done = kFALSE;
883     TGridResult *res = gGrid->Command(query);
884     if (res)
885     {
886       TString cjobId1 = res->GetKey(0,"jobId");
887       if (!cjobId1.IsDec())
888       {
889         AliError(" FAILED");
890         gGrid->Stdout();
891         gGrid->Stderr();
892       }
893       else
894       {
895         AliInfo(Form(" DONE\n   --> the job Id is: %s \n", cjobId1.Data()));
896         done = kTRUE;
897       }
898       delete res;
899     }
900     else
901     {
902       AliError(" FAILED");
903     }
904     
905     if (!done)
906     {
907       gSystem->Exec(Form("echo %d >> __failed__", run));
908       failedRun = kTRUE;
909     }
910     
911   }
912   
913   if (failedRun)
914   {
915     AliInfo("\n--------------------\n");
916     AliInfo("list of failed runs:\n");
917     gSystem->Exec("cat __failed__");
918     gSystem->Exec("rm -f __failed__");
919     return kFALSE;
920   }
921   
922   return kTRUE;
923 }
924
925 //______________________________________________________________________________
926 UInt_t AliMuonAccEffSubmitter::NofRuns() const
927 {
928     // number of runs we're dealing with
929   if (!fScalers) return 0;
930   
931   return fScalers->GetRunList().size();
932 }
933
934 //______________________________________________________________________________
935 void AliMuonAccEffSubmitter::Output(std::ostream& out, const char* key,
936                                     const TObjArray& values) const
937 {
938   /// output to ostream of key,{values} pair
939   
940   out << key << " = ";
941   
942   Int_t n = values.GetEntries();
943   
944   if ( n > 1 )
945   {
946     out << "{" << std::endl;
947     TIter next(&values);
948     TObjString* v;
949     
950     while ( ( v = static_cast<TObjString*>(next())) )
951     {
952       --n;
953       out << "\t\"" << v->String().Data() << "\"";
954       if  ( n ) out << ",";
955       out << std::endl;
956     }
957     out << "}";
958   }
959   else
960   {
961     TString& v1 = static_cast<TObjString*>(values.At(0))->String();
962     
963     if ( v1.IsDigit() )
964     {
965       out << v1.Atoi();
966     }
967     else
968     {
969       out << "\"" << v1.Data() << "\"";
970     }
971   }
972   out << ";" << std::endl;
973 }
974
975 //______________________________________________________________________________
976 void AliMuonAccEffSubmitter::Output(std::ostream& out, const char* key, const char* v1,
977                                     const char* v2, const char* v3, const char* v4,
978                                     const char* v5, const char* v6, const char* v7,
979                                     const char* v8, const char* v9) const
980 {
981   /// output to ostream
982   
983   TObjArray values;
984   values.SetOwner(kTRUE);
985   
986   values.Add(new TObjString(v1));
987   if ( strlen(v2) > 0 ) values.Add(new TObjString(v2));
988   if ( strlen(v3) > 0 ) values.Add(new TObjString(v3));
989   if ( strlen(v4) > 0 ) values.Add(new TObjString(v4));
990   if ( strlen(v5) > 0 ) values.Add(new TObjString(v5));
991   if ( strlen(v6) > 0 ) values.Add(new TObjString(v6));
992   if ( strlen(v7) > 0 ) values.Add(new TObjString(v7));
993   if ( strlen(v8) > 0 ) values.Add(new TObjString(v8));
994   if ( strlen(v9) > 0 ) values.Add(new TObjString(v9));
995   
996   Output(out,key,values);
997 }
998
999
1000 //______________________________________________________________________________
1001 void AliMuonAccEffSubmitter::Print(Option_t* /*opt*/) const
1002 {
1003   /// Printout
1004   
1005   if (!IsValid())
1006   {
1007     std::cout << std::string(80,'*') << std::endl;
1008     std::cout << "INVALID OBJECT. CHECK BELOW THE CONFIGURATION." << std::endl;
1009     std::cout << std::string(80,'*') << std::endl;
1010   }
1011     
1012   std::cout << "Template  directory = " << fTemplateDir.Data() << std::endl;
1013   std::cout << "Local     directory = " << fLocalDir.Data() << std::endl;
1014   std::cout << "Remote    directory = " << fRemoteDir.Data() << std::endl;
1015   
1016   if ( fSnapshotDir != fLocalDir )
1017   {
1018     std::cout << "Snapshots directory = " << fSnapshotDir.Data() << std::endl;
1019   }
1020   
1021   std::cout << "OCDB path = " << fOCDBPath.Data() << std::endl;
1022   
1023   if ( fRatio > 0 )
1024   {
1025     std::cout << Form("For each run, will generate %5.2f times the number of real events for trigger %s",
1026                       fRatio,fReferenceTrigger.Data()) << std::endl;
1027   }
1028   else
1029   {
1030     std::cout << Form("For each run, will generate %10d events",fFixedNofEvents) << std::endl;
1031   }
1032   
1033   std::cout << "MaxEventsPerChunk = " << fMaxEventsPerChunk << std::endl;
1034   
1035   if ( NofRuns() )
1036   {
1037     std::cout << NofRuns() << " run";
1038     if ( NofRuns() > 1 ) std::cout << "s";
1039     std::cout << " = ";
1040     fScalers->Print();
1041   }
1042   
1043   if ( fVars )
1044   {
1045     TIter next(fVars);
1046     TObjString* key;
1047     while ( ( key = static_cast<TObjString*>(next())) )
1048     {
1049       TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
1050       std::cout << "Variable " << key->String() << " will be replaced by " << value->String() << std::endl;
1051     }
1052   }
1053   
1054   std::cout << "Files to be uploaded:" << std::endl;
1055   TIter nextFile(LocalFileList());
1056   TObjString* sfile;
1057   while ( ( sfile = static_cast<TObjString*>(nextFile())) )
1058   {
1059     std::cout << sfile->String().Data() << std::endl;
1060   }
1061 }
1062
1063
1064 //______________________________________________________________________________
1065 Bool_t AliMuonAccEffSubmitter::RemoteDirectoryExists(const char *dirname) const
1066 {
1067   // Returns true if directory exists. Can be also a path.
1068   if (!gGrid) return kFALSE;
1069   // Check if dirname is a path
1070   TString dirstripped = dirname;
1071   dirstripped = dirstripped.Strip();
1072   dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1073   TString dir = gSystem->BaseName(dirstripped);
1074   dir += "/";
1075   TString path = gSystem->DirName(dirstripped);
1076   TGridResult *res = gGrid->Ls(path, "-F");
1077   if (!res) return kFALSE;
1078   TIter next(res);
1079   TMap *map;
1080   TObject *obj;
1081   while ((map=dynamic_cast<TMap*>(next()))) {
1082     obj = map->GetValue("name");
1083     if (!obj) break;
1084     if (dir == obj->GetName()) {
1085       delete res;
1086       return kTRUE;
1087     }
1088   }
1089   delete res;
1090   return kFALSE;
1091 }
1092
1093 //______________________________________________________________________________
1094 Bool_t AliMuonAccEffSubmitter::RemoteFileExists(const char *lfn) const
1095 {
1096   // Returns true if file exists.
1097   if (!gGrid) return kFALSE;
1098   TGridResult *res = gGrid->Ls(lfn);
1099   if (!res) return kFALSE;
1100   TMap *map = dynamic_cast<TMap*>(res->At(0));
1101   if (!map) {
1102     delete res;
1103     return kFALSE;
1104   }
1105   TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1106   if (!objs || !objs->GetString().Length()) {
1107     delete res;
1108     return kFALSE;
1109   }
1110   delete res;
1111   return kTRUE;
1112 }
1113
1114 //______________________________________________________________________________
1115 Bool_t AliMuonAccEffSubmitter::ReplaceVars(const char* file) const
1116 {
1117   /// Replace the variables (i.e. things starting by VAR_) found in file
1118   
1119   std::ifstream in(file);
1120   char line[1024];
1121   TObjArray lines;
1122   lines.SetOwner(kTRUE);
1123   Int_t nvars(0);
1124   Int_t nreplaced(0);
1125
1126   TIter next(fVars);
1127
1128   while ( in.getline(line,1023,'\n') )
1129   {
1130     TString sline(line);
1131     while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
1132     {
1133       ++nvars;
1134       TObjString* key;
1135       next.Reset();
1136       while ( ( key = static_cast<TObjString*>(next())) )
1137       {
1138         if ( sline.Contains(key->String()) )
1139         {
1140           ++nreplaced;
1141           TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
1142           sline.ReplaceAll(key->String(),value->String());
1143           break;
1144         }
1145       }
1146     }
1147
1148     lines.Add(new TObjString(sline));
1149   }
1150   
1151   in.close();
1152   
1153   if ( nvars > 0 )
1154   {
1155     if ( nreplaced != nvars )
1156     {
1157       AliError(Form("nvars=%d nreplaced=%d",nvars,nreplaced));
1158       return kFALSE;
1159     }
1160     std::ofstream out(file);
1161     TIter nextLine(&lines);
1162     TObjString* s;
1163     while ( ( s = static_cast<TObjString*>(nextLine()) ) )
1164     {
1165       out << s->String().Data() << std::endl;
1166     }
1167     out.close();
1168   }
1169   
1170   return kTRUE;
1171 }
1172
1173 //______________________________________________________________________________
1174 Bool_t AliMuonAccEffSubmitter::Run(const char* mode)
1175 {
1176   /// mode can be one of (case insensitive)
1177   ///
1178   /// LOCAL : copy the template files from the template directory to the local one
1179   /// UPLOAD : copy the local files to the grid (requires LOCAL)
1180   /// OCDB : make ocdb snapshots (requires LOCAL)
1181   /// SUBMIT : submit the jobs (requires LOCAL + UPLOAD)
1182   /// FULL : all of the above (requires all of the above)
1183   ///
1184   /// TEST : as SUBMIT, but in dry mode (does not actually submit the jobs)
1185   
1186   if (!IsValid()) return kFALSE;
1187   
1188   TString smode(mode);
1189   smode.ToUpper();
1190   
1191   if ( smode == "FULL")
1192   {
1193     return  ( Run("LOCAL") && Run("OCDB") && Run("UPLOAD") && Run("SUBMIT") );
1194   }
1195   
1196   if ( smode == "LOCAL")
1197   {
1198     return CopyTemplateFilesToLocal();
1199   }
1200   
1201   if ( smode == "UPLOAD" )
1202   {
1203     return (CopyLocalFilesToRemote());
1204   }
1205   
1206   if ( smode == "OCDB" )
1207   {
1208     Bool_t ok = Run("LOCAL");
1209     if (ok)
1210     {
1211       ok = MakeOCDBSnapshots();
1212     }
1213     return ok;
1214   }
1215   
1216   if ( smode == "TEST" )
1217   {
1218     Bool_t ok = Run("LOCAL") && Run("OCDB") && Run("UPLOAD");
1219     if ( ok )
1220     {
1221       ok = (Submit(kTRUE)>0);
1222     }
1223     return ok;
1224   }
1225   
1226   if ( smode == "FULL" )
1227   {
1228     Bool_t ok = Run("LOCAL")  && Run("OCDB") && Run("UPLOAD");
1229     if ( ok )
1230     {
1231       ok = (Submit(kFALSE)>0);
1232     }
1233     return ok;
1234   }
1235
1236   if( smode == "SUBMIT" )
1237   {
1238     return (Submit(kFALSE)>0);
1239   }
1240   
1241   return kFALSE;
1242 }
1243
1244 //______________________________________________________________________________
1245 void AliMuonAccEffSubmitter::SetPackages(const char* aliroot,
1246                                          const char* root,
1247                                          const char* geant3,
1248                                          const char* api)
1249 {
1250   /// Set the packages to be used by the jobs
1251   /// Must be a valid combination, see http://alimonitor.cern.ch/packages/
1252   ///
1253   fPackageAliroot = aliroot;
1254   fPackageRoot = root;
1255   fPackageGeant3 = geant3;
1256   fPackageApi = api;
1257 }
1258
1259 //______________________________________________________________________________
1260 TString AliMuonAccEffSubmitter::GetRemoteDir(const char* dir, Bool_t create)
1261 {
1262   /// Set the target remote directory (on the grid)
1263   
1264   if (!RemoteDirectoryExists(dir))
1265   {
1266     if (!create)
1267     {
1268       AliError(Form("Remote directory %s does not exist", dir));
1269       return "";
1270     }
1271     else
1272     {
1273       AliInfo(Form("Remote directory %s does not exist. Trying to create it...",dir));
1274       if ( !gGrid->Mkdir(dir,"-p") )
1275       {
1276         AliError(Form("Could not create remote dir. Sorry."));
1277         return "";
1278       }
1279     }
1280   }
1281   return dir;
1282 }
1283
1284 //______________________________________________________________________________
1285 Bool_t AliMuonAccEffSubmitter::SetGenerator(const char* generator)
1286 {
1287   // set the variable to select the generator macro in Config.C
1288   
1289   gSystem->Load("libEVGEN");
1290     
1291   fIsValid = kFALSE;
1292   
1293   TString generatorFile(Form("%s/%s.C",fTemplateDir.Data(),generator));
1294   
1295   Int_t nofMissingVariables(0);
1296   
1297   // first check we indeed have such a macro
1298   if (!gSystem->AccessPathName(generatorFile.Data()))
1299   {
1300     TObjArray* variables = GetVariables(generatorFile.Data());
1301     
1302     TIter next(variables);
1303     TObjString* var;
1304     
1305     while ( ( var = static_cast<TObjString*>(next())) )
1306     {
1307       if ( !fVars->GetValue(var->String()) )
1308       {
1309         ++nofMissingVariables;
1310         AliError(Form("file %s expect the variable %s to be defined, but we've not defined it !",generatorFile.Data(),var->String().Data()));
1311       }
1312     }
1313     
1314     delete variables;
1315     
1316     if ( !nofMissingVariables )
1317     {
1318       if (CheckCompilation(generatorFile.Data()))
1319       {
1320         fIsValid = kTRUE;
1321         SetVar("VAR_GENERATOR",Form("%s",generator));        
1322         TemplateFileList()->Add(new TObjString(Form("%s.C",generator)));
1323         return kTRUE;
1324       }
1325     }
1326     else
1327     {
1328       return kFALSE;
1329     }
1330   }
1331   else
1332   {
1333     AliError(Form("Can not work with the macro %s",generatorFile.Data()));
1334   }
1335   return kFALSE;
1336 }
1337
1338 //______________________________________________________________________________
1339 Bool_t AliMuonAccEffSubmitter::SetMergedDir(const char* dir, Bool_t create)
1340 {
1341   // Set the merged directory to be used
1342   fMergedDir = GetRemoteDir(dir,create);
1343   return (fMergedDir.Length()>0);
1344 }
1345
1346 //______________________________________________________________________________
1347 Bool_t AliMuonAccEffSubmitter::SetRemoteDir(const char* dir, Bool_t create)
1348 {
1349   // Set the remote directory to be used
1350   fRemoteDir = GetRemoteDir(dir,create);
1351   return (fIsValid = (fRemoteDir.Length()>0));
1352 }
1353
1354
1355 //______________________________________________________________________________
1356 void AliMuonAccEffSubmitter::SetRunList(const char* runList)
1357 {
1358     // set the runlist from a text file
1359   if (!fScalers)
1360   {
1361     fScalers = new AliAnalysisTriggerScalers(runList,fOCDBPath.Data());
1362   }
1363   else
1364   {
1365     fScalers->SetRunList(runList);
1366   }
1367   UpdateLocalFileList(kTRUE);
1368 }
1369
1370 //______________________________________________________________________________
1371 void AliMuonAccEffSubmitter::SetRunList(int runNumber)
1372 {
1373   // set the runlist from a text file
1374   if (!fScalers)
1375   {
1376     fScalers = new AliAnalysisTriggerScalers(runNumber,fOCDBPath.Data());
1377   }
1378   else
1379   {
1380     fScalers->SetRunList(runNumber);      
1381   }
1382   UpdateLocalFileList(kTRUE);
1383 }
1384
1385 //______________________________________________________________________________
1386 void AliMuonAccEffSubmitter::SetOCDBPath(const char* ocdbPath)
1387 {
1388   /// Sets the OCDB path to be used
1389   
1390   fOCDBPath = ocdbPath;
1391   
1392   if (fScalers)
1393   {
1394     // redefine trigger scalers to use the new ocdb path
1395     AliAnalysisTriggerScalers* ts = new AliAnalysisTriggerScalers(fScalers->GetRunList(),
1396                                                                   fOCDBPath.Data());
1397     
1398     delete fScalers;
1399     fScalers = ts;
1400   }
1401 }
1402
1403
1404 //______________________________________________________________________________
1405 void AliMuonAccEffSubmitter::SetOCDBSnapshotDir(const char* dir)
1406 {
1407   // change the directory used for snapshot
1408   
1409   if (gSystem->AccessPathName(Form("%s/OCDB",dir)))
1410   {
1411     AliError(Form("Snapshot top directory (%s) should contain an OCDB subdir with runnumbers in there",dir));
1412   }
1413   else
1414   {
1415     fSnapshotDir = dir;
1416   }
1417 }
1418
1419 //______________________________________________________________________________
1420 Bool_t AliMuonAccEffSubmitter::SetVar(const char* varname, const char* value)
1421 {
1422   /// Set a variable
1423   
1424   TString s(varname);
1425   s.ToUpper();
1426   if (!s.BeginsWith("VAR_"))
1427   {
1428     AliError("Variable name should start with VAR_");
1429     return kFALSE;
1430   }
1431   if (!fVars)
1432   {
1433     fVars = new TMap;
1434     fVars->SetOwnerKeyValue(kTRUE,kTRUE);
1435   }
1436   
1437   TObject* o = new TObjString(s);
1438   fVars->Remove(o);
1439   
1440   fVars->Add(o,new TObjString(value));
1441   
1442   return kTRUE;
1443 }
1444
1445 //______________________________________________________________________________
1446 Int_t AliMuonAccEffSubmitter::Submit(Bool_t dryRun)
1447 {
1448   /// Submit multiple production jobs with the format "submit jdl 000run#.xml 000run#".
1449   ///
1450   /// Return the number of submitted (master) jobs
1451   ///
1452   /// Example:
1453   /// - outputDir = "/alice/cern.ch/user/p/ppillot/Sim/LHC10h/JPsiPbPb276/AlignRawVtxRaw/ESDs"
1454   /// - runList must contains the list of run number
1455   /// - trigger is the (fully qualified) trigger name used to compute the base number of events
1456   /// - mult is the factor to apply to the number of trigger to get the number of events to be generated
1457   ///   (# generated events = # triggers x mult
1458   
1459   if (!IsValid()) return 0;
1460   
1461   AliDebug(1,"");
1462
1463   gGrid->Cd(RemoteDir());
1464   
1465   if (!RemoteFileExists(RunJDLName()))
1466   {
1467     AliError(Form("file %s does not exist in %s", RunJDLName().Data(), RemoteDir().Data()));
1468     return 0;
1469   }
1470   
1471   if ( !fScalers )
1472   {
1473     AliError("No run list set. Use SetRunList");
1474     return 0;
1475   }
1476   const std::vector<int>& runs = fScalers->GetRunList();
1477   
1478   if (runs.empty())
1479   {
1480     AliError("No run to work with");
1481     return 0;
1482   }
1483   
1484   //  cout << "total number of selected MB events = " << totEvt << endl;
1485   //  cout << "required number of generated events = " << nGenEvents << endl;
1486   //  cout << "number of generated events per MB event = " << ratio << endl;
1487   //  cout << endl;
1488   
1489   std::cout << "run\tchunks\tevents" << std::endl;
1490   std::cout << "----------------------" << std::endl;
1491   
1492   Int_t nJobs(0);
1493   Int_t nEvts(0);
1494   
1495   for (std::vector<int>::size_type i=0; i < runs.size(); ++i)
1496   {
1497     Int_t runNumber = runs[i];
1498     
1499     Int_t nEvtRun(fFixedNofEvents);
1500     
1501     if ( fRatio > 0 )
1502     {
1503       AliAnalysisTriggerScalerItem* trigger = fScalers->GetTriggerScaler(runNumber, "L2A", ReferenceTrigger().Data());
1504     
1505       if (!trigger)
1506       {
1507         AliError(Form("Could not get trigger %s for run %09d",ReferenceTrigger().Data(),runNumber));
1508         continue;
1509       }
1510       nEvtRun = TMath::Nint(fRatio * trigger->Value());
1511     }
1512     
1513     Int_t nChunk = 1;
1514     
1515     while (nEvtRun/nChunk+0.5 > MaxEventsPerChunk())
1516     {
1517       ++nChunk;
1518     }
1519     
1520     Int_t nEvtChunk = TMath::Nint(nEvtRun/nChunk + 0.5);
1521     
1522     nJobs += nChunk;
1523     
1524     nEvts += nChunk*nEvtChunk;
1525     
1526     std::cout << runNumber << "\t" << nChunk << "\t" << nEvtChunk << std::endl;
1527     
1528     TString query(Form("submit %s %d %d %d", RunJDLName().Data(), runNumber, nChunk, nEvtChunk));
1529     
1530     std::cout << query.Data() << " ..." << std::flush;
1531     
1532     TGridResult* res = 0x0;
1533     
1534     if (!dryRun)
1535     {
1536       res = gGrid->Command(query);
1537     }
1538     
1539     if (res)
1540     {
1541       TString cjobId1 = res->GetKey(0,"jobId");
1542       
1543       if (!cjobId1.Length())
1544       {
1545         std::cout << " FAILED" << std::endl << std::endl;
1546         gGrid->Stdout();
1547         gGrid->Stderr();
1548       }
1549       else
1550       {
1551         std::cout << "DONE" << std::endl;
1552         std::cout << Form("   --> the job Id is: %s",cjobId1.Data()) << std::endl << std::endl;
1553       }
1554     }
1555     else
1556     {
1557       std::cout << " FAILED" << std::endl << std::endl;
1558     }
1559     
1560     delete res;
1561   }
1562   
1563   std::cout << std::endl
1564   << "total number of jobs = " << nJobs << std::endl
1565   << "total number of generated events = " << nEvts << std::endl
1566   << std::endl;
1567   
1568   return nJobs;
1569 }
1570
1571 //______________________________________________________________________________
1572 TObjArray* AliMuonAccEffSubmitter::TemplateFileList() const
1573 {
1574   /// Return (after createing and filling it if needed)
1575   /// the internal file list with paths from the template directory
1576   
1577   if (!fTemplateFileList)
1578   {
1579     fTemplateFileList = new TObjArray;
1580     fTemplateFileList->SetOwner(kTRUE);
1581     
1582     fTemplateFileList->Add(new TObjString("CheckESD.C"));
1583     fTemplateFileList->Add(new TObjString("CheckAOD.C"));
1584     fTemplateFileList->Add(new TObjString("AODtrain.C"));
1585     fTemplateFileList->Add(new TObjString("validation.sh"));
1586     if ( fExternalConfig.Length() > 0 )
1587     {
1588       fTemplateFileList->Add(new TObjString(fExternalConfig));
1589     }
1590     else
1591     {
1592       fTemplateFileList->Add(new TObjString("Config.C"));
1593     }
1594     fTemplateFileList->Add(new TObjString("rec.C"));
1595     fTemplateFileList->Add(new TObjString("sim.C"));
1596     fTemplateFileList->Add(new TObjString("simrun.C"));
1597     fTemplateFileList->Add(new TObjString(RunJDLName().Data()));
1598     if ( fUseAODMerging )
1599     {
1600       fTemplateFileList->Add(new TObjString(MergeJDLName(kFALSE).Data()));
1601       fTemplateFileList->Add(new TObjString(MergeJDLName(kTRUE).Data()));
1602       fTemplateFileList->Add(new TObjString("AOD_merge.sh"));
1603       fTemplateFileList->Add(new TObjString("validation_merge.sh"));
1604     }
1605   }
1606   
1607   return fTemplateFileList;
1608 }
1609
1610 //______________________________________________________________________________
1611 void AliMuonAccEffSubmitter::UpdateLocalFileList(Bool_t clearSnapshots)
1612 {
1613   /// Update the list of local files
1614   
1615   if (!fScalers) return;
1616   
1617   if ( clearSnapshots )
1618   {
1619     TIter next(LocalFileList());
1620     TObjString* file;
1621     
1622     while ( ( file = static_cast<TObjString*>(next())) )
1623     {
1624       if ( file->String().Contains("OCDB_") )
1625       {
1626         LocalFileList()->Remove(file);
1627       }
1628     }
1629     LocalFileList()->Compress();
1630   }
1631
1632   const std::vector<int>& runs = fScalers->GetRunList();
1633   
1634   const char* type[] = { "sim","rec" };
1635   
1636   for ( std::vector<int>::size_type i = 0; i < runs.size(); ++i )
1637   {
1638     Int_t runNumber = runs[i];
1639     
1640     for ( Int_t t = 0; t < 2; ++t )
1641     {
1642       TString snapshot(Form("%s/OCDB/%d/OCDB_%s.root",SnapshotDir().Data(),runNumber,type[t]));
1643       
1644       if ( !gSystem->AccessPathName(snapshot.Data()) )
1645       {
1646         if ( !LocalFileList()->FindObject(snapshot.Data()) )
1647         {
1648           LocalFileList()->Add(new TObjString(snapshot));
1649         }
1650       }
1651     }
1652   }
1653 }
1654
1655 //______________________________________________________________________________
1656 void AliMuonAccEffSubmitter::UseOCDBSnapshots(Bool_t flag)
1657 {
1658   /// Whether or not to use OCDB snapshots
1659   /// Using OCDB snapshots will speed-up both the sim and reco initialization
1660   /// phases on each worker node, but takes time to produce...
1661   /// So using them is not always a win-win...
1662   
1663   fUseOCDBSnapshots = flag;
1664   if ( flag )
1665   {
1666     SetVar("VAR_OCDB_SNAPSHOT","kTRUE");
1667   }
1668   else
1669   {
1670     SetVar("VAR_OCDB_SNAPSHOT","kFALSE");
1671   }
1672   
1673   UpdateLocalFileList();
1674 }
1675
1676 //______________________________________________________________________________
1677 void AliMuonAccEffSubmitter::UseAODMerging(Bool_t flag)
1678 {
1679   /// whether or not we should generate JDL for merging AODs
1680   
1681   fUseAODMerging = flag;
1682   // FIXME: here should update the TemplateFileList() (and LocalFileList as well ?)
1683 }