]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG/muondep/AliMuonGridSubmitter.cxx
move track selection differences from AOD and ESD to corresponding reader
[u/mrichter/AliRoot.git] / PWG / muondep / AliMuonGridSubmitter.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 // AliMuonGridSubmitter : a class to help submit jobs for several runs
18 //
19 // This class is dealing with 3 different directories :
20 //
21 // - template directory ($ALICE_ROOT/PWG/muondep/XXXTemplates) containing the
22 //   basic template files to be used for a particular job type (XXX). A template can contain
23 //   some variables that will be replaced during during the copy from template
24 //   to local dir
25 //
26 // - local directory, where the files from the template directory, are copied
27 //   once the class has been configured properly (i.e. using the various Set, Use,
28 //   etc... methods). Some other files (e.g. JDL ones) are generated from
29 //   scratch and also copied into this directory.
30 //   At this point one could(should) check the files, as they are the ones
31 //   to be copied to the remote directory for the production
32 //
33 // - remote directory, the alien directory where the files will be copied
34 //   (from the local directory) before the actual submission
35 //
36 // author: Laurent Aphecetche (Subatech
37 //
38
39 #include "AliMuonGridSubmitter.h"
40
41 #include "AliLog.h"
42 #include "TFile.h"
43 #include "TGrid.h"
44 #include "TGridResult.h"
45 #include "TMap.h"
46 #include "TMath.h"
47 #include "TObjString.h"
48 #include "TROOT.h"
49 #include "TString.h"
50 #include "TSystem.h"
51 #include <vector>
52 #include "AliAnalysisTriggerScalers.h"
53 #include "Riostream.h"
54
55 //______________________________________________________________________________
56 AliMuonGridSubmitter::AliMuonGridSubmitter(AliMuonGridSubmitter::EJobType jobType, Bool_t localOnly)
57 : TObject(),
58 fInternalMap(0x0),
59 fVars(0x0),
60 fIsValid(kFALSE),
61 fShouldOverwriteFiles(kFALSE),
62 fTemplateFileList(0x0),
63 fLocalFileList(0x0),
64 fRunList()
65 {
66   // ctor
67   
68   if (!gGrid && !localOnly)
69   {
70     TGrid::Connect("alien://");
71     if ( !gGrid )
72     {
73       AliError("cannot connect to grid");
74     }
75   }
76   
77   SetPackages("VO_ALICE@AliRoot::v5-04-Rev-20");
78   
79   TString basedir = gSystem->ExpandPathName("$ALICE_ROOT/PWG/muondep");
80   
81   TString dir;
82   dir.Form("%s/%sTemplates",basedir.Data(),JobTypeName(jobType).Data());
83   
84   if (!SetTemplateDir(dir.Data()))
85   {
86     AliError(Form("Could not find %s directory. Please check.",dir.Data()));
87   }
88   
89   SetLocalDir(gSystem->pwd());
90 }
91
92 //______________________________________________________________________________
93 AliMuonGridSubmitter::~AliMuonGridSubmitter()
94 {
95   // dtor
96   delete fTemplateFileList;
97   delete fLocalFileList;
98   delete fInternalMap;
99   delete fVars;
100 }
101
102 ///______________________________________________________________________________
103 void AliMuonGridSubmitter::AddIncludePath(const char* pathList) const
104 {
105   TObjArray* paths = TString(pathList).Tokenize(" ");
106   TIter next(paths);
107   TObjString* p;
108   TString includePath = gSystem->GetIncludePath();
109   
110   while ( ( p = static_cast<TObjString*>(next()) ) )
111   {
112     if ( !includePath.Contains(p->String()) )
113     {
114       gSystem->AddIncludePath(p->String().Data());
115     }
116   }
117   
118   delete paths;
119 }
120
121
122 //______________________________________________________________________________
123 void AliMuonGridSubmitter::AddToTemplateFileList(const char* filename)
124 {
125   // add a file to the list of templates
126   // and update the local file list if needed
127   
128   TObjArray* a = TemplateFileList();
129   
130   if ( !a->FindObject(filename) )
131   {
132     a->Add(new TObjString(filename));
133     UpdateLocalFileList();
134   }
135 }
136
137 //______________________________________________________________________________
138 void AliMuonGridSubmitter::AddToLocalFileList(const char* filename)
139 {
140   // add a file to the list of local files
141   
142   TObjArray* a = LocalFileList();
143   
144   if ( !a->FindObject(filename) )
145   {
146     a->Add(new TObjString(filename));
147   }
148 }
149
150 //______________________________________________________________________________
151 Bool_t AliMuonGridSubmitter::CheckCompilation(const char* file) const
152 {
153   /// Check whether file can be compiled or not
154   /// FIXME: use gSystem->TempFileName for tmpfile !
155   
156   Bool_t rv(kTRUE);
157   
158   TString sfile(gSystem->BaseName(file));
159   TString tmpfile(Form("tmpfile_%s",sfile.Data()));
160   
161   gSystem->Exec(Form("cp %s %s",file,tmpfile.Data()));
162   
163   ReplaceVars(tmpfile.Data());
164   
165   gSystem->AddIncludePath("-I$ALICE_ROOT/include");
166   gSystem->AddIncludePath("-I$ALICE_ROOT/EVGEN");
167
168   if (gROOT->LoadMacro(Form("%s++",tmpfile.Data())))
169   {
170     AliError(Form("macro %s can not be compiled. Please check.",file));
171     rv = kFALSE;
172   }
173   
174   gSystem->Exec(Form("rm %s",tmpfile.Data()));
175   
176   return rv;
177 }
178
179
180 //______________________________________________________________________________
181 Bool_t AliMuonGridSubmitter::CheckLocal() const
182 {
183   /// Check whether all required local files are there
184   TIter next(LocalFileList());
185   TObjString* file;
186   
187   while ( ( file = static_cast<TObjString*>(next())) )
188   {
189       if ( gSystem->AccessPathName(file->String().Data()) )
190       {
191         return kFALSE;
192       }
193   }
194   
195   return kTRUE;
196 }
197
198 //______________________________________________________________________________
199 Bool_t AliMuonGridSubmitter::CheckRemote() const
200 {
201   /// Check whether all required remote files are there
202   AliWarning("implement me");
203   return kFALSE;
204 }
205
206 //______________________________________________________________________________
207 void AliMuonGridSubmitter::CleanLocal(const char* excludeList) const
208 {
209   /// Clean (remove) local generated files
210   /// exclude contains a list of comma separated pattern of files
211   /// to be avoided
212   
213   TIter next(LocalFileList());
214   TObjString* file;
215   TObjArray* excludeArray = TString(excludeList).Tokenize(",");
216   
217   while ( ( file = static_cast<TObjString*>(next())) )
218   {
219     Bool_t shouldExclude(kFALSE);
220     
221     TIter nextExclude(excludeArray);
222     TObjString* s;
223     
224     while ( ( s = static_cast<TObjString*>(nextExclude()))  && !shouldExclude )
225     {
226       if ( file->String().Contains(s->String()) ) shouldExclude=kTRUE;
227     }
228     
229     if (!shouldExclude)
230     {
231       gSystem->Unlink(file->String().Data());
232     }
233   }
234   
235   delete excludeArray;
236 }
237
238 //______________________________________________________________________________
239 Bool_t AliMuonGridSubmitter::CopyFile(const char* localFile)
240 {
241   /// copy a local file to remote destination
242   TString local;
243   
244   if ( gSystem->IsAbsoluteFileName(localFile) )
245   {
246     local = localFile;
247   }
248   else
249   {
250     local = Form("%s/%s",LocalDir().Data(),gSystem->ExpandPathName(localFile));
251   }
252   
253   if (gSystem->AccessPathName(local.Data()))
254   {
255     AliErrorClass(Form("Local file %s does not exist",local.Data()));
256     return kFALSE;
257   }
258   
259   TString remote;
260   
261   remote += RemoteDir().Data();
262   remote += "/";
263   
264   if ( gSystem->IsAbsoluteFileName(localFile) )
265   {
266     TString tmp(localFile);
267     tmp.ReplaceAll(GetMapValue("Snapshot"),"");
268     tmp.ReplaceAll(GetMapValue("Local"),"");
269     remote += tmp;
270   }
271   else
272   {
273     remote += localFile;
274   }
275   
276   TString dirName = gSystem->DirName(remote.Data());
277   
278   Bool_t ok(kTRUE);
279   
280   if (!RemoteDirectoryExists(dirName.Data()))
281   {
282     ok = gGrid->Mkdir(dirName.Data(),"-p");
283   }
284   
285   if ( ok )
286   {
287     AliDebugClass(1,Form("cp %s alien://%s",local.Data(),remote.Data()));
288     return TFile::Cp(local.Data(),Form("alien://%s",remote.Data()));
289   }
290   else
291   {
292     return kFALSE;
293   }
294 }
295
296 //______________________________________________________________________________
297 Bool_t AliMuonGridSubmitter::CheckRemoteDir() const
298 {
299   /// Check we have a grid connection and that the remote dir exists
300   
301   if (RemoteDir().IsNull())
302   {
303     AliError("you must provide the grid location where to copy the files");
304     return kFALSE;
305   }
306   
307   if (!RemoteDirectoryExists(RemoteDir()))
308   {
309     AliError(Form("directory %s does not exist", RemoteDir().Data()));
310     return kFALSE;
311   }
312
313   return kTRUE;
314 }
315
316 //______________________________________________________________________________
317 Bool_t AliMuonGridSubmitter::CopyLocalFilesToRemote()
318 {
319   /// copy all files necessary to run the simulation into remote directory
320   
321   TIter next(LocalFileList());
322   TObjString* ftc;
323     
324   Bool_t allok(kTRUE);
325     
326   while ( ( ftc = static_cast<TObjString*>(next())) )
327   {
328     allok = allok && CopyFile(ftc->String());
329   }
330   return allok;
331 }
332
333 //______________________________________________________________________________
334 Bool_t AliMuonGridSubmitter::CopyTemplateFilesToLocal()
335 {
336   // copy (or generate) local files from the template ones
337   
338   if (!IsValid()) return kFALSE;
339
340   AliDebug(1,"");
341
342   TIter next(TemplateFileList());
343   TObjString* file;
344   
345   Int_t err(0);
346   Bool_t potentialProblem(kFALSE);
347   
348   while ( ( file = static_cast<TObjString*>(next())) )
349   {
350     if ( file->String().Contains("OCDB") )
351     {
352       /// OCDB snapshots are not in template
353       continue;
354     }
355
356     if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(file->String().Data()) )
357     {
358       AliError(Form("Local file %s already exists. Remove it first if you want to update overwrite it",file->String().Data()));
359       potentialProblem = kTRUE;
360     }
361     else
362     {
363       TString stemplate(Form("%s/%s",TemplateDir().Data(),file->String().Data()));
364       TString slocal(Form("%s/%s",LocalDir().Data(),file->String().Data()));
365       
366       AliDebug(1,Form("Copying %s to %s",stemplate.Data(),slocal.Data()));
367       
368       Int_t c =  gSystem->CopyFile(stemplate.Data(),slocal.Data(),ShouldOverwriteFiles());
369       if ( c )
370       {
371         Bool_t ok(kFALSE);
372         if ( stemplate.Contains(".jdl",TString::kIgnoreCase) )
373         {
374           ok = Generate(file->String().Data());
375         }
376         if (!ok)
377         {
378           AliError(Form("Error %d copying file %s",c,stemplate.Data()));
379         }
380         else
381         {
382           c=0;
383         }
384       }
385       else
386       {
387         if ( HasVars(slocal.Data()) )
388         {
389           if (!ReplaceVars(slocal.Data()))
390           {
391             AliError("pb in ReplaceVars");
392             c=1;
393           }
394         }
395       }
396       err += c;
397     }
398   }
399   
400   if ( potentialProblem )
401   {
402     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 !");
403     return kFALSE;
404   }
405   return (err==0);
406 }
407
408 //______________________________________________________________________________
409 std::ostream* AliMuonGridSubmitter::CreateJDLFile(const char* name) const
410 {
411   /// Create a (local and empty) JDL file
412   
413   AliDebugClass(1,"");
414   
415   TString jdl(Form("%s/%s",LocalDir().Data(),name));
416   
417   if ( !ShouldOverwriteFiles() && !gSystem->AccessPathName(jdl.Data()) )
418   {
419     AliErrorClass(Form("File %s already exists. Remove it if you want to overwrite it",jdl.Data()));
420     return 0x0;
421   }
422   
423   std::ofstream* os = new std::ofstream(gSystem->ExpandPathName(jdl.Data()));
424   
425   if (os->bad())
426   {
427     AliErrorClass(Form("Cannot create file %s",jdl.Data()));
428     delete os;
429     os=0x0;
430   }
431   
432   return os;
433 }
434
435 //______________________________________________________________________________
436 Int_t AliMuonGridSubmitter::GetLastStage(const char* remoteDir)
437 {
438   /// Get the last staging phase already performed
439   
440   TGridResult* r = gGrid->Ls(remoteDir);
441   Int_t i(0);
442   Int_t lastStage(0);
443   Int_t offset = TString("Stage_").Length();
444   
445   while ( r->GetFileName(i) )
446   {
447     TString file(r->GetFileName(i));
448     if  (file.BeginsWith("Stage_") && !file.Contains("xml") )
449     {
450       Int_t n = TString(file(offset,file.Length()-offset)).Atoi();
451       lastStage = TMath::Max(lastStage,n);
452     }
453     ++i;
454   }
455   delete r;
456   return lastStage;
457 }
458
459 //______________________________________________________________________________
460 TString AliMuonGridSubmitter::GetMapValue(const char* key) const
461 {
462   // convenience method to access internal map of TObjStrings
463   if (!fInternalMap) return "";
464   
465   TObject* o = fInternalMap->GetValue(key);
466   
467   if (o)
468   {
469     return static_cast<TObjString*>(o)->String();
470   }
471   
472   return "";
473 }
474
475 //______________________________________________________________________________
476 TObjArray* AliMuonGridSubmitter::GetVariables(const char* file) const
477 {
478   /// Find the variables in the file
479   
480   std::ifstream in(file);
481   char line[1024];
482   TObjArray* variables(0x0);
483   
484   while ( in.getline(line,1023,'\n') )
485   {
486     TString sline(line);
487     while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
488     {
489       Int_t i1 = sline.Index("VAR_");
490       Int_t i2(i1);
491       
492       while ( ( i2 < sline.Length() ) && ( isalnum(sline[i2]) || sline[i2]=='_' ) ) ++i2;
493       
494       if (!variables)
495       {
496         variables = new TObjArray;
497         variables->SetOwner(kTRUE);
498       }
499       
500       TString var = sline(i1,i2-i1);
501       if ( !variables->FindObject(var) )
502       {
503         variables->Add(new TObjString(var));
504       }
505       sline.ReplaceAll(var,"");
506     }
507   }
508   
509   in.close();
510   
511   return variables;
512 }
513
514 //______________________________________________________________________________
515 Bool_t AliMuonGridSubmitter::HasVars(const char* file) const
516 {
517   /// Whether or not the file contains variables that have to
518   /// be substituted
519   
520   std::ifstream in(file);
521   char line[1024];
522   while ( in.getline(line,1023,'\n') )
523   {
524     TString sline(line);
525     if (sline.Contains("VAR_") && !sline.BeginsWith("//") )
526     {
527       return kTRUE;
528     }
529   }
530   return kFALSE;
531 }
532
533 //______________________________________________________________________________
534 TMap* AliMuonGridSubmitter::InternalMap() const
535 {
536   if (!fInternalMap)
537   {
538     fInternalMap = new TMap;
539     fInternalMap->SetOwnerKeyValue(kTRUE,kTRUE);
540   }
541   return fInternalMap;
542 }
543
544 //______________________________________________________________________________
545 TString AliMuonGridSubmitter::JobTypeName(AliMuonGridSubmitter::EJobType jobType) const
546 {
547   if ( jobType == kAccEff )
548   {
549     return "AccEff";
550   }
551   else if ( jobType == kQAMerge)
552   {
553     return "QAMerge";
554   }
555   return "unknown";
556 }
557
558 //______________________________________________________________________________
559 TObjArray* AliMuonGridSubmitter::LocalFileList() const
560 {
561   /// Return (after createing and filling it if needed)
562   /// the internal file list with paths from the local directory
563   
564   if (!fLocalFileList)
565   {
566     fLocalFileList = static_cast<TObjArray*>(TemplateFileList()->Clone());
567   }
568   
569   return fLocalFileList;
570 }
571
572 //______________________________________________________________________________
573 UInt_t AliMuonGridSubmitter::NofRuns() const
574 {
575     // number of runs we're dealing with
576   return fRunList.size();
577 }
578
579 //______________________________________________________________________________
580 TObjArray* AliMuonGridSubmitter::OrderKeys(const TMap& map) const
581 {
582   /// return an array where the map's keys are sorted alphabetically
583   /// the returned array should be deleted by the client
584   
585   TObjArray* keyArray = new TObjArray;
586   keyArray->SetOwner(kTRUE);
587   TObjString* key;
588   
589   TIter next(&map);
590   while ( ( key = static_cast<TObjString*>(next())) )
591   {
592     keyArray->Add(new TObjString(key->String()));
593   }
594   
595   keyArray->Sort();
596   return keyArray;
597 }
598
599
600 //______________________________________________________________________________
601 void AliMuonGridSubmitter::OutputToJDL(std::ostream& out, const char* key,
602                                     const TObjArray& values) const
603 {
604   /// output to ostream of key,{values} pair
605   
606   out << key << " = ";
607   
608   Int_t n = values.GetEntries();
609   
610   if ( n > 1 )
611   {
612     out << "{" << std::endl;
613     TIter next(&values);
614     TObjString* v;
615     
616     while ( ( v = static_cast<TObjString*>(next())) )
617     {
618       if ( v->String().Length() == 0 ) continue;
619       
620       --n;
621       out << "\t\"" << v->String().Data() << "\"";
622       if  ( n ) out << ",";
623       out << std::endl;
624     }
625     out << "}";
626   }
627   else
628   {
629     TString& v1 = static_cast<TObjString*>(values.At(0))->String();
630     
631     if ( v1.IsDigit() && !(TString(key).Contains("SplitMax")) && !(TString(key).Contains("TTL")) )
632     {
633       out << v1.Atoi();
634     }
635     else
636     {
637       out << "\"" << v1.Data() << "\"";
638     }
639   }
640   out << ";" << std::endl;
641 }
642
643 //______________________________________________________________________________
644 void AliMuonGridSubmitter::OutputToJDL(std::ostream& out, const char* key, const char* v1,
645                                     const char* v2, const char* v3, const char* v4,
646                                     const char* v5, const char* v6, const char* v7,
647                                     const char* v8, const char* v9) const
648 {
649   /// output to ostream
650   
651   TObjArray values;
652   values.SetOwner(kTRUE);
653   
654   values.Add(new TObjString(v1));
655   if ( strlen(v2) > 0 ) values.Add(new TObjString(v2));
656   if ( strlen(v3) > 0 ) values.Add(new TObjString(v3));
657   if ( strlen(v4) > 0 ) values.Add(new TObjString(v4));
658   if ( strlen(v5) > 0 ) values.Add(new TObjString(v5));
659   if ( strlen(v6) > 0 ) values.Add(new TObjString(v6));
660   if ( strlen(v7) > 0 ) values.Add(new TObjString(v7));
661   if ( strlen(v8) > 0 ) values.Add(new TObjString(v8));
662   if ( strlen(v9) > 0 ) values.Add(new TObjString(v9));
663   
664   OutputToJDL(out,key,values);
665 }
666
667
668 //______________________________________________________________________________
669 void AliMuonGridSubmitter::Print(Option_t* /*opt*/) const
670 {
671   /// Printout
672   
673   if (!IsValid())
674   {
675     std::cout << std::string(80,'*') << std::endl;
676     std::cout << "INVALID OBJECT. CHECK BELOW THE CONFIGURATION." << std::endl;
677     std::cout << std::string(80,'*') << std::endl;
678   }
679
680   std::cout << "-- Internals : " << std::endl;
681   
682   TObjArray* im = OrderKeys(*fInternalMap);
683   
684   TIter next(im);
685   TObjString* key;
686   
687   while ( ( key = static_cast<TObjString*>(next()) ) )
688   {
689     TString value = static_cast<TObjString*>(fInternalMap->GetValue(key->String()))->String();
690     
691     std::cout << key->String() << " : " << value.Data() << std::endl;
692   }
693   
694   delete im;
695   
696   if ( NofRuns() )
697   {
698     std::cout << NofRuns() << " run";
699     if ( NofRuns() > 1 ) std::cout << "s";
700     std::cout << " = ";
701     for ( std::vector<int>::size_type i = 0; i < fRunList.size(); ++i )
702     {
703       std::cout << fRunList[i] << " ";
704     }
705     std::cout << std::endl;
706   }
707   
708   std::cout << std::endl << "-- Variables : " << std::endl;
709
710   TObjArray* iv = OrderKeys(*fVars);
711   
712   TIter nextVar(iv);
713   while ( ( key = static_cast<TObjString*>(nextVar())) )
714   {
715     TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
716     std::cout << "Variable " << key->String() << " will be replaced by " << value->String() << std::endl;
717   }
718   
719   delete iv;
720   
721   std::cout << std::endl << "-- Files to be uploaded:" << std::endl;
722   TIter nextFile(LocalFileList());
723   TObjString* sfile;
724   while ( ( sfile = static_cast<TObjString*>(nextFile())) )
725   {
726     std::cout << sfile->String().Data() << std::endl;
727   }
728 }
729
730
731 //______________________________________________________________________________
732 Bool_t AliMuonGridSubmitter::RemoteDirectoryExists(const char *dirname) const
733 {
734   // Returns true if directory exists. Can be also a path.
735   if (!gGrid) return kFALSE;
736   // Check if dirname is a path
737   TString dirstripped = dirname;
738   dirstripped = dirstripped.Strip();
739   dirstripped = dirstripped.Strip(TString::kTrailing, '/');
740   TString dir = gSystem->BaseName(dirstripped);
741   dir += "/";
742   TString path = gSystem->DirName(dirstripped);
743   TGridResult *res = gGrid->Ls(path, "-F");
744   if (!res) return kFALSE;
745   TIter next(res);
746   TMap *map;
747   TObject *obj;
748   while ((map=dynamic_cast<TMap*>(next()))) {
749     obj = map->GetValue("name");
750     if (!obj) break;
751     if (dir == obj->GetName()) {
752       delete res;
753       return kTRUE;
754     }
755   }
756   delete res;
757   return kFALSE;
758 }
759
760 //______________________________________________________________________________
761 Bool_t AliMuonGridSubmitter::RemoteFileExists(const char *lfn)
762 {
763   // Returns true if file exists.
764   if (!gGrid) return kFALSE;
765   TGridResult *res = gGrid->Ls(lfn);
766   if (!res) return kFALSE;
767   TMap *map = dynamic_cast<TMap*>(res->At(0));
768   if (!map) {
769     delete res;
770     return kFALSE;
771   }
772   TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
773   if (!objs || !objs->GetString().Length()) {
774     delete res;
775     return kFALSE;
776   }
777   delete res;
778   return kTRUE;
779 }
780
781 //______________________________________________________________________________
782 Bool_t AliMuonGridSubmitter::ReplaceVars(const char* file) const
783 {
784   /// Replace the variables (i.e. things starting by VAR_) found in file
785   
786   AliDebug(1,file);
787   
788   std::ifstream in(file);
789   char line[1024];
790   TObjArray lines;
791   lines.SetOwner(kTRUE);
792   Int_t nvars(0);
793   Int_t nreplaced(0);
794
795   TIter next(fVars);
796
797   while ( in.getline(line,1023,'\n') )
798   {
799     TString sline(line);
800     while (sline.Contains("VAR_") && !sline.BeginsWith("//") )
801     {
802       ++nvars;
803       TObjString* key;
804       next.Reset();
805       
806       int n(0);
807       
808       while ( ( key = static_cast<TObjString*>(next())) )
809       {
810         AliDebug(1,Form("Does %s contains %s ?",sline.Data(),key->String().Data()));
811         
812         if ( sline.Contains(key->String()) )
813         {
814           ++nreplaced;
815           ++n;
816           TObjString* value = static_cast<TObjString*>(fVars->GetValue(key->String()));
817           AliDebug(1,Form("Replacing %s by %s in %s",key->String().Data(),value->String().Data(),sline.Data()));
818           sline.ReplaceAll(key->String(),value->String());
819           AliDebug(1,"Done");
820           break;
821         }
822       }
823       
824       if (n==0)
825       {
826         AliError(Form("Could not find a replacement for variable %s",sline.Data()));
827         break;
828       }
829     }
830
831     lines.Add(new TObjString(sline));
832   }
833   
834   in.close();
835   
836   if ( nvars > 0 )
837   {
838     if ( nreplaced != nvars )
839     {
840       AliError(Form("nvars=%d nreplaced=%d",nvars,nreplaced));
841       return kFALSE;
842     }
843     std::ofstream out(file);
844     TIter nextLine(&lines);
845     TObjString* s;
846     while ( ( s = static_cast<TObjString*>(nextLine()) ) )
847     {
848       out << s->String().Data() << std::endl;
849     }
850     out.close();
851   }
852   
853   AliDebug(1,Form("replaced %d vars",nvars));
854   
855   return kTRUE;
856 }
857
858 //______________________________________________________________________________
859 const std::vector<int>& AliMuonGridSubmitter::RunList() const
860 {
861   /// Return a reference to our runlist
862   return fRunList;
863 }
864
865 //______________________________________________________________________________
866 void AliMuonGridSubmitter::SetPackages(const char* aliroot,
867                                          const char* root,
868                                          const char* geant3,
869                                          const char* api)
870 {
871   /// Set the packages to be used by the jobs
872   /// If root and geant3 are given (default is to let alien get the correct
873   /// values for the requested aliroot version), then they must
874   /// correspond to a valid combination, see http://alimonitor.cern.ch/packages/
875   
876   SetMapKeyValue("AliRoot",aliroot);
877   SetMapKeyValue("Root",root);
878   SetMapKeyValue("Geant3",geant3);
879   SetMapKeyValue("API",api);
880 }
881
882 //______________________________________________________________________________
883 TString AliMuonGridSubmitter::GetRemoteDir(const char* dir, Bool_t create)
884 {
885   /// Set the target remote directory (on the grid)
886   
887   if (!RemoteDirectoryExists(dir))
888   {
889     if (!create)
890     {
891       AliErrorClass(Form("Remote directory %s does not exist", dir));
892       return "";
893     }
894     else
895     {
896       AliInfoClass(Form("Remote directory %s does not exist. Trying to create it...",dir));
897       if (!gGrid)
898       {
899           AliErrorClass("cannot connect to grid");
900           return "";
901       }
902       if ( !gGrid->Mkdir(dir,"-p") )
903       {
904         AliErrorClass(Form("Could not create remote dir. Sorry."));
905         return "";
906       }
907     }
908   }
909   return dir;
910 }
911
912 //______________________________________________________________________________
913 Bool_t AliMuonGridSubmitter::SetLocalDirectory(const char* type, const char* path)
914 {
915   if (gSystem->AccessPathName(path)==kFALSE)
916   {
917     SetMapKeyValue(type,path);
918     return kTRUE;
919   }
920   return kFALSE;
921 }
922
923 //______________________________________________________________________________
924 void AliMuonGridSubmitter::SetMapKeyValue(const char* key, const char* value)
925 {
926   TObjString skey(key);
927   InternalMap()->Remove(&skey);
928   InternalMap()->Add(new TObjString(key),new TObjString(value));
929 }
930
931 //______________________________________________________________________________
932 Bool_t AliMuonGridSubmitter::SetRemoteDirectory(const char* type, const char* path)
933 {
934   // Set the merged directory to be used
935   TString v = GetRemoteDir(path,kTRUE);
936   SetMapKeyValue(type,v);
937   return (v.Length()>0);
938 }
939
940 //______________________________________________________________________________
941 void AliMuonGridSubmitter::SetRunList(const char* runlist)
942 {
943     // set the runlist from a text file
944   AliAnalysisTriggerScalers ts(runlist);
945   fRunList = ts.GetRunList();
946 }
947
948 //______________________________________________________________________________
949 void AliMuonGridSubmitter::SetRunList(int runNumber)
950 {
951   // set the runlist from a text file
952   fRunList.clear();
953   fRunList.push_back(runNumber);
954 }
955
956 //______________________________________________________________________________
957 TString AliMuonGridSubmitter::GetVar(const char* key) const
958 {
959   TObjString* o = static_cast<TObjString*>(Vars()->GetValue(key));
960   if (o)
961   {
962     return o->String();
963   }
964   return "";
965 }
966
967 //______________________________________________________________________________
968 Bool_t AliMuonGridSubmitter::SetVar(const char* varname, const char* value)
969 {
970   /// Set a variable
971   ///
972   /// Pay attention to how string variables should be given here : you have
973   /// to espace the quotation marks :
974   ///
975   /// SetVar("VAR_PYTHIA8_SETUP_STRINGS","\"SoftQCD:doubleDiffractive=off\"");
976   
977   TString s(varname);
978   s.ToUpper();
979   if (!s.BeginsWith("VAR_"))
980   {
981     AliError("Variable name should start with VAR_");
982     return kFALSE;
983   }
984   if (!fVars)
985   {
986     fVars = new TMap;
987     fVars->SetOwnerKeyValue(kTRUE,kTRUE);
988   }
989   
990   TObject* o = new TObjString(s);
991   fVars->Remove(o);
992   
993   fVars->Add(o,new TObjString(value));
994   
995   return kTRUE;
996 }
997
998 //______________________________________________________________________________
999 TObjArray* AliMuonGridSubmitter::TemplateFileList() const
1000 {
1001   /// Return (after createing if needed)
1002   
1003   if (!fTemplateFileList)
1004   {
1005     fTemplateFileList = new TObjArray;
1006     fTemplateFileList->SetOwner(kTRUE);
1007   }
1008   return fTemplateFileList;
1009 }
1010
1011 //______________________________________________________________________________
1012 void AliMuonGridSubmitter::UpdateLocalFileList()
1013 {
1014   // insure that local file list contains at least all of the template files
1015   TIter next(TemplateFileList());
1016   TObjString* s;
1017   
1018   while ( ( s = static_cast<TObjString*>(next())) )
1019   {
1020     AddToLocalFileList(s->String().Data());
1021   }
1022 }
1023
1024 //______________________________________________________________________________
1025 TMap* AliMuonGridSubmitter::Vars() const
1026 {
1027   if (!fVars)
1028   {
1029     fVars = new TMap;
1030     fVars->SetOwnerKeyValue(kTRUE,kTRUE);
1031   }
1032   return fVars;
1033 }
1034