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