]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGHF/correlationHF/macros/run-single-task.C
support for par files, multiple tasks, and collection of local AODs (Matthias)
[u/mrichter/AliRoot.git] / PWGHF / correlationHF / macros / run-single-task.C
1 //-*- Mode: C++ -*-
2 // $Id$
3
4 /// @file   run-single-task.C
5 /// @author Matthias.Richter@ift.uib.no
6 /// @date   2012-04-06
7 /// @brief  Run a single task
8 ///
9 /// Helper macro to run a single task either locally or on Grid
10 /// Usage:
11 /// aliroot -b -q -l run-single-task.C'("mode", "run", "task", "name", useMC, events, "path", "pattern", "friendPattern", "outputDir", "user")'
12 ///  arguments
13 ///   mode:    local, full, test
14 ///   run:     list of run numbers. Or if using AODs with predefined list/AODs in same folder, specifiy as "AOD"
15 ///   task:    class name of task
16 ///
17 ///  optional arguments
18 ///   name:    analysis name (default 'myanalysis')
19 ///   events:  number of events to be processed (default -1 -> all)
20 ///   path:    data search path for grid analysis (default from configuration file)
21 ///   pattern: data search pattern (default from configuration file)
22 ///
23 /// Examples:
24 /// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "myanalysis_LHC11a")'
25 ///
26 /// aliroot -b -q -l run-single-task.C'("local", "$ALICE_ROOT/test/ppbench/AliESDs.root", "AliAnalysisTaskSample")'
27 ///
28 /// aliroot -b -q -l run-single-task.C'("local", "AOD", "AddTaskSample.C"")'
29 ///
30 /// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "correlation3p_LHC11a", -1, "/alice/data/2011/LHC11a", "*/pass2_without_SDD/AOD*/*/AliAOD.root")'
31 ///
32 /// Data input:
33 /// depending on the format of the search pattern either the ESD or AOD input handler is used.
34 ///
35 /// Source files:
36 /// If the task and classes used by the task are not in an AliRoot library available, e.g.
37 /// for the purpose of development, all header and source files need to be in the local
38 /// directory. The macro searches automatically for dependencies, compiles those and
39 /// copies files to the Grid working directory. In order to make the files accessible in
40 /// the local directory, the files can be just linked.
41 /// <pre>
42 /// for f in <search path>; do ln -s $f; done
43 /// </pre>
44 ///
45 /// Local analysis:
46 /// requires only the path to the input file and the task class name. If the specified file is
47 /// a text file (.txt) each line can contain an input file path, all files are chained.
48 /// Note: AOD mode needs to be implemented
49 ///
50 /// Grid analysis:
51 /// All modes provided by the AliAnalysisAlien plugin can be used, e.g. full, test, offline
52 /// A couple of settings need to be defined in a configuration file 'grid-config.C' which can be
53 /// either in the local directory or home directory.
54 /// <pre>
55 ///   const char* alienAPIVersion="V1.1x";
56 ///   const char* alienROOTVersion="v5-33-02a";
57 ///   const char* alienAliROOTVersion="v5-01-Rev-29";
58 ///   const char* defaultGridDataDir="/alice/data/2011/LHC11a";
59 ///   const char* defaultDataPattern="*/pass2_without_SDD/*/AliESDs.root";
60 ///   {} // note this empty body
61 /// </pre>
62 /// Data path and pattern can also be specified as command line arguments.
63 /// The working directory in the grid home directory of the user is set to
64 /// gridwork/<date>_<time>.
65 ///
66 /// 
67
68 ///////////////////////////////////////////////////////////////////////////////////////////////////
69 //
70 // environment
71 //
72 int macroVerbosity=0;
73 const char* defaultAnalysisName="myanalysis";
74 const char* includePath="-I. -I$ROOTSYS/include -I$ALICE_ROOT/include";
75 const char* libraryDependencies=
76   "libSTEERBase.so "
77   "libESD.so "
78   "libAOD.so "
79   "libANALYSIS.so "
80   "libANALYSISalice.so "
81   ;
82
83 TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass=true);
84 void ErrorConfigurationFile(const char* fileName);
85
86 void run_single_task(const char* mode,
87                      const char* input,
88                      const char* tasknames,
89                      const char* analysisName=defaultAnalysisName,
90                      Bool_t useMC=kFALSE,
91                      int nevents=-1,
92                      const char* gridDataDir=NULL,
93                      const char* dataPattern=NULL,
94                      const char* friendDataPattern=NULL,
95                      TString odir="",
96                      const char* user=NULL
97                      )
98 {
99   ///////////////////////////////////////////////////////////////////////////////////////////////////
100   ///////////////////////////////////////////////////////////////////////////////////////////////////
101   ///////////////////////////////////////////////////////////////////////////////////////////////////
102   //
103   // defaults
104   //
105   if (analysisName==defaultAnalysisName && gDirectory!=NULL) {
106     // NOTE: the direct pointer comparison is on purpose
107     // string comparison not necessary in this special case
108
109     // fetch the analysis name from the setup file
110     const char* confObjectName="analysis_name";
111     TObject* confObject=gDirectory->FindObject(confObjectName);
112     if (confObject) {
113       analysisName=confObject->GetTitle();
114     }
115   }
116
117   bool bRunLocal=strcmp(mode, "local")==0;
118   const char* gridConfigFile="grid-config.C";
119   TString strGridConfigFile=gridConfigFile;
120   if (gSystem->AccessPathName(strGridConfigFile)!=0) {
121     strGridConfigFile.Prepend("/");
122     strGridConfigFile.Prepend(gSystem->Getenv("HOME"));
123     if (gSystem->AccessPathName(strGridConfigFile)!=0) {
124       if (!bRunLocal) {
125         ErrorConfigurationFile(gridConfigFile);
126         return;
127       }
128       strGridConfigFile="";
129     }
130   }
131
132   if (strGridConfigFile.IsNull()==0 && !bRunLocal) {
133     cout << "loading grid configuration from file '" << strGridConfigFile << "':" << endl;
134     gROOT->LoadMacro(strGridConfigFile);
135     cout << " alienAPIVersion          =" << alienAPIVersion     << endl;
136     cout << " alienROOTVersion         =" << alienROOTVersion    << endl;
137     cout << " alienAliROOTVersion      =" << alienAliROOTVersion << endl;
138     cout << " defaultGridDataDir       =" << defaultGridDataDir  << endl;
139     cout << " defaultDataPattern       =" << defaultDataPattern  << endl;
140     cout << " defaultFriendDataPattern =" << defaultFriendDataPattern  << endl;
141
142     if (gridDataDir==NULL) gridDataDir=defaultGridDataDir;
143     if (dataPattern==NULL) dataPattern=defaultDataPattern;
144     if (friendDataPattern==NULL) friendDataPattern=defaultFriendDataPattern;
145   } else if (bRunLocal) {
146     if (dataPattern==NULL) {
147       TString strin=input;
148       if (strin.EndsWith("AOD"))
149         dataPattern="AOD";
150       else if (strin.EndsWith("ESD"))
151         dataPattern="ESD";
152     }
153   }
154
155   if(!bRunLocal) {
156     // Connect to AliEn
157     TGrid::Connect("alien://");
158   }
159   ///////////////////////////////////////////////////////////////////////////////////////////////////
160   ///////////////////////////////////////////////////////////////////////////////////////////////////
161   ///////////////////////////////////////////////////////////////////////////////////////////////////
162   //
163   // make the analysis manager
164   //
165   AliAnalysisManager *pManager  = new AliAnalysisManager("AnalysisManager");
166   if (!pManager) {
167     cerr << "failed to created AnalysisManager" << endl;
168     return;
169   }
170   AliInputEventHandler *pInputHandler = NULL;
171   TString strDataPattern(dataPattern);
172   if (strDataPattern.Contains("AOD")) pInputHandler=new AliAODInputHandler;
173   else if (strDataPattern.Contains("ESD")) pInputHandler=new AliESDInputHandler;
174   else {
175     cerr << "can not determine input type from data pattern '" << dataPattern << "'" << endl;
176     return;
177   }
178   if (!pInputHandler) {
179     cerr << "failed to created input handler" << endl;
180     return;
181   }
182   //pInputHandler->SetReadFriends(kFALSE);
183   pManager->SetInputEventHandler(pInputHandler);  
184   pManager->SetNSysInfo(1000);
185
186   TString ofile=Form("%s.root", analysisName);
187
188   ///////////////////////////////////////////////////////////////////////////////////////////////////
189   ///////////////////////////////////////////////////////////////////////////////////////////////////
190   ///////////////////////////////////////////////////////////////////////////////////////////////////
191   //
192   // load task classes and find and load all dependencies
193   //
194   gSystem->AddIncludePath(includePath);
195   TString libraries=libraryDependencies;
196   if (gDirectory!=NULL) {
197     // fetch the analysis libraries from the setup file
198     const char* confObjectName="analysis_libraries";
199     TObject* confObject=gDirectory->FindObject(confObjectName);
200     if (confObject) {
201       TString analysisLibraries(confObject->GetTitle());
202       TObjArray* pTokens=analysisLibraries.Tokenize(" ");
203       if (pTokens) {
204         for (int i=0; i<pTokens->GetEntriesFast(); i++) {
205           if (libraries.Contains(pTokens->At(i)->GetName())==0) {
206             libraries+=" ";
207             libraries+=pTokens->At(i)->GetName();
208           }
209         }
210         delete pTokens;
211       }
212     }
213   }
214   TObjArray* pTokens=libraries.Tokenize(" ");
215   if (pTokens) {
216     for (int i=0; i<pTokens->GetEntriesFast(); i++) {
217       if (gSystem->Load(pTokens->At(i)->GetName())==0) {
218         cout << "loading " << pTokens->At(i)->GetName() << endl;
219       }
220     }
221     delete pTokens;
222   }
223
224   TString taskNames=tasknames;
225   TString taskClasses="";
226   TString taskSources="";
227   TString taskHeaders="";
228   TString addTaskMacros="";
229   TString parPackages="";
230   TObjArray* pTaskNames=taskNames.Tokenize(" ");
231   if (pTaskNames) {
232     for (int iTaskName=0; iTaskName<pTaskNames->GetEntriesFast(); iTaskName++) {
233       TString taskSource=pTaskNames->At(iTaskName)->GetName();
234       TString taskHeader=pTaskNames->At(iTaskName)->GetName();
235       bool bIsAddTask=false;
236   if (taskSource.EndsWith(".C")) {
237     // suppose that's an 'AddTask' macro
238     taskHeader="";
239     bIsAddTask=true;
240   } else if (taskSource.EndsWith(".par")) {
241     // par file
242     if (gSystem->AccessPathName(taskSource)!=0) {
243       ::Error("run_single_task", Form("par file '%s' not found in current directory, you might want to set a symbolic link", taskSource.Data()));
244       return;
245     }
246     parPackages+=" ";
247     parPackages+=taskSource;
248     continue;
249   } else if (taskSource.EndsWith(".h")) {
250     taskSource.ReplaceAll(".h", "");
251     taskClasses+=" ";
252     taskClasses+=taskSource;
253     taskSource+=".cxx";
254   } else if (taskSource.EndsWith(".cxx")) {
255     taskHeader.ReplaceAll(".cxx", "");
256     taskClasses+=" ";
257     taskClasses+=taskHeader;
258     taskHeader+=".h";
259   } else {
260     taskClasses+=" ";
261     taskClasses+=taskSource;
262     taskSource+=".cxx";
263     taskHeader+=".h";
264   }
265   TString dependencyHeader;
266   TString dependencySource;
267   if (gSystem->AccessPathName(taskHeader)==0) {
268   GetIncludeHeaders(taskHeader, dependencyHeader, libraries);
269   taskHeaders+=" "; taskHeaders+=taskHeader;
270   }
271   if (gSystem->AccessPathName(taskSource)==0) {
272   GetIncludeHeaders(taskSource, dependencyHeader, libraries);
273   if (!bIsAddTask) {taskSources+=" "; taskSources+=taskSource;}
274   else {addTaskMacros+=" "; addTaskMacros+=taskSource;}
275   }
276   TObjArray* pTokens=dependencyHeader.Tokenize(" ");
277   if (pTokens) {
278     for (int i=0; i<pTokens->GetEntriesFast(); i++) {
279       TString sourceFile=pTokens->At(i)->GetName();
280       sourceFile.ReplaceAll(".h", ".cxx");
281       if (gSystem->AccessPathName(sourceFile)!=0) continue;
282       if (!dependencySource.IsNull()) dependencySource+=" ";
283       dependencySource+=sourceFile;
284       if (!libraries.IsNull()) libraries+=" ";
285       libraries+=sourceFile;
286     }
287     delete pTokens;
288   }
289   dependencySource.ReplaceAll(taskSource, "");
290   dependencyHeader.ReplaceAll(taskHeader, "");
291     }
292     delete pTaskNames;
293   }
294   cout << "Tasks: " << taskClasses << endl;
295   cout << "Task files: " << taskSources << addTaskMacros << taskHeaders << endl;
296   cout << "Dependency classes: " << dependencySource << endl;
297   cout << "Dependency headers: " << dependencyHeader << endl;
298   cout << "Dependency libraries: " << libraries << endl;
299   cout << "Packages: " << parPackages << endl;
300
301   ///////////////////////////////////////////////////////////////////////////////////////////////////
302   ///////////////////////////////////////////////////////////////////////////////////////////////////
303   ///////////////////////////////////////////////////////////////////////////////////////////////////
304   //
305   // init for local or GRID analysis
306   //
307   AliAnalysisAlien *alienHandler = NULL; // for grid analysis
308   TChain *chain=NULL; // for local analysis
309   TString strInput=input;
310   if (bRunLocal) {
311     ///////////////////////////////////////////////////////////////////////////////////////////////////
312     //
313     // local analysis
314     //
315     if(strInput.EndsWith("AliESDs.root")){
316       // suppose it's a single ESD file
317       chain = new TChain("esdTree"); 
318       chain->Add(strInput);
319     } else if(strInput.EndsWith(".txt")) {
320       // Constructs chain from filenames in *.txt
321       // in the form $DIR/AliESDs.root  
322       gROOT->LoadMacro("$ALICE_ROOT/PWG0/CreateESDChain.C");
323       // chain can contain up to 200 files, value can be modified to 
324       // include a subset of what the *txt file contains
325       chain = CreateESDChainf(strInput.Data(),200); 
326
327       // check if the files are on grid
328       TIter next(chain->GetListOfFiles());
329       TChainElement *chEl = 0;
330       while(( chEl = (TChainElement*)next() )){
331         TString tmp = chEl->GetTitle();     
332         if(tmp.BeginsWith("alien://")) {
333           TGrid::Connect("alien://");
334           break;
335         }
336       }
337     } else if(strInput.EndsWith("AOD")){
338       // fetch aod tree from the setup macro
339       if (gDirectory!=NULL) {
340         TObject* chainObject=gDirectory->FindObject("aodTree");
341         if (chainObject) {
342           chain=dynamic_cast<TChain*>(chainObject);
343         }
344       }
345       if (!chain) {
346         cout << "failed to fetch aod tree object from setup" << endl;
347         return -1;
348       }
349     } else {
350       cerr << "invalid input" << endl;
351       return -1;
352     }
353   } else {
354     ///////////////////////////////////////////////////////////////////////////////////////////////////
355     //
356     // grid analysis
357     //
358     alienHandler=new AliAnalysisAlien();
359     if (!alienHandler) {
360       cerr << "failed to create alien handler" << endl;
361       return;
362     }
363
364     // do not check for copying to grid (CLOSE_SE)
365     alienHandler->SetCheckCopy(kFALSE);
366
367     // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
368     alienHandler->SetRunMode(mode);
369   
370     // check the versions available on alien with the command 'packages'
371     alienHandler->SetAPIVersion(alienAPIVersion);
372     alienHandler->SetROOTVersion(alienROOTVersion);
373     alienHandler->SetAliROOTVersion(alienAliROOTVersion);
374
375     //Allow non-default outputs
376     //This is required to set non-default output files with the SetOutputFiles
377     //function below
378     alienHandler->SetDefaultOutputs(kFALSE);
379     if (user && user[0]!=0) alienHandler->SetUser(user);
380
381     // data alien directory
382     alienHandler->SetGridDataDir(gridDataDir);
383   
384     // Set data search pattern
385     alienHandler->SetDataPattern(dataPattern);
386     alienHandler->SetFriendChainName(friendDataPattern);
387
388     TObjArray* packageTokens=parPackages.Tokenize(" " );
389     if (packageTokens) {
390       for (int iPackageToken=0; iPackageToken<packageTokens->GetEntriesFast(); iPackageToken++) {
391         alienHandler->EnablePackage(packageTokens->At(iPackageToken)->GetName());
392       }
393       delete packageTokens;
394     }
395
396     if (!useMC)
397       alienHandler->SetRunPrefix("000");   // real data
398
399     alienHandler->AddRunNumber(input);
400
401     // define working and output directories
402     TDatime dt;
403     if(odir.IsNull())
404       odir=(Form("gridwork/%04d-%02d-%02d_%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute()));
405     cout << odir << endl;
406     alienHandler->SetGridWorkingDir(odir); // relative to $HOME
407     alienHandler->SetGridOutputDir("output");   // relative to working dir
408     //alienHandler->SetOverwriteMode();                // overwrites the contents of the working and output directory
409
410     // workaround for a Root feature: GetIncludePath() appends always
411     // the current Root include path including escaped quotes. Those
412     // quotes make it difficult to pass the output directly. Search for the
413     // last appended include path and truncate
414     TString strIncludePath(gSystem->GetIncludePath());
415     Int_t pos=strIncludePath.Index(includePath);
416     if (pos>=0) {
417       Int_t cut=0;
418       do {
419         cut=pos+strlen(includePath);
420       } while ((pos=strIncludePath.Index(includePath, cut))>cut);
421       strIncludePath.Resize(cut);
422     }
423     alienHandler->AddIncludePath(strIncludePath);
424
425     // Note: there is no extra source or header file to be transferred if 'AddTask' macros are used
426     alienHandler->SetAnalysisSource(Form("%s %s %s %s", dependencySource.Data(), dependencyHeader.Data(), taskSources.Data(), taskHeaders.Data()));
427     alienHandler->SetAdditionalLibs(Form("%s %s %s", libraries.Data(), taskHeaders.Data(), dependencyHeader.Data()));
428
429     alienHandler->SetOutputFiles(ofile);
430
431     // Optionally define the files to be archived.
432     //-
433     //alienHandler->SetOutputArchive("log_archive.zip:stdout,stderr");
434   
435     // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
436     TString macroName; macroName.Form("run_%s.C",analysisName); macroName.ReplaceAll("-","_");
437     alienHandler->SetAnalysisMacro(macroName);
438   
439     //alienHandler->SetExecutable("comparison.sh");
440     alienHandler->SetExecutable(Form("run_%s.sh",analysisName));
441
442     alienHandler->SetSplitMaxInputFileNumber(100);
443   
444     // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
445     alienHandler->SetMaxInitFailed(10);
446   
447     // Optionally resubmit threshold.
448     alienHandler->SetMasterResubmitThreshold(90); // in %
449
450     alienHandler->SetTTL(30000);// in sec
451   
452     // Optionally set input format (default xml-single)
453     alienHandler->SetInputFormat("xml-single");
454  
455     // Optionally modify the name of the generated JDL (default analysis.jdl)
456     alienHandler->SetJDLName(Form("run_%s.jdl",analysisName));
457  
458     // Optionally modify job price (default 1)
459     alienHandler->SetPrice(1);
460   
461     // Optionally modify split mode (default 'se')
462     alienHandler->SetSplitMode("se");
463   
464     // comment out the next line when using the "terminate" option, unless
465     // you want separate merged files for each run
466     if (strcmp(mode, "terminate")==0) {
467       alienHandler->SetMergeViaJDL(kFALSE);
468     }
469
470     alienHandler->SetOneStageMerging(kFALSE);
471     alienHandler->SetMaxMergeStages(2);
472   }
473
474   // Connect plugin to the analysis manager
475   if (alienHandler) {
476     pManager->SetGridHandler(alienHandler);
477   }
478
479   ///////////////////////////////////////////////////////////////////////////////////////////////////
480   ///////////////////////////////////////////////////////////////////////////////////////////////////
481   ///////////////////////////////////////////////////////////////////////////////////////////////////
482   //
483   // create task from the name, create output container, connect slots
484   //
485   TObjArray* taskClassTokens=taskClasses.Tokenize(" ");
486   if (taskClassTokens) {
487     for (int iTaskClassToken=0; iTaskClassToken<taskClassTokens->GetEntriesFast(); iTaskClassToken++) {
488     AliAnalysisTaskSE *pTask=NULL;
489     TString taskName=taskClassTokens->At(iTaskClassToken)->GetName();
490     taskName.ReplaceAll(".cxx", "");
491     TClass* pCl=TClass::GetClass(taskName);
492     if (!pCl) {
493       cerr << "can not load class " << taskName << endl;
494       return -1;
495     }
496     TObject* p=pCl->New();
497     if (!p) {
498       cerr << "failed to instantiate class " << taskName << endl;
499       return -1;
500     }
501     pTask=reinterpret_cast<AliAnalysisTaskSE*>(p);
502     pManager->AddTask(pTask);
503     AliAnalysisDataContainer *pContainer=pManager->CreateContainer(analysisName ,TObject::Class(), AliAnalysisManager::kOutputContainer, ofile);       
504     pManager->ConnectInput(pTask,0,pManager->GetCommonInputContainer());
505     pManager->ConnectOutput(pTask,1,pContainer);
506     }
507     delete taskClassTokens;
508   }
509   TObjArray* taskMacroTokens=addTaskMacros.Tokenize(" ");
510   if (taskMacroTokens) {
511     for (int iTaskMacroToken=0; iTaskMacroToken<taskMacroTokens->GetEntriesFast(); iTaskMacroToken++) {
512     taskSource+="+g";
513     TString configuration;
514     configuration.Form("name=%s file=%s %s", analysisName, ofile.Data(), useMC?"mc":"");
515     if (gDirectory) gDirectory->Add(new TNamed("run_single_task_configuration", configuration.Data()));
516     gROOT->Macro(taskMacroTokens->At(iTaskMacroToken)->GetName());
517     }
518     delete taskMacroTokens;
519   }
520
521   ///////////////////////////////////////////////////////////////////////////////////////////////////
522   ///////////////////////////////////////////////////////////////////////////////////////////////////
523   ///////////////////////////////////////////////////////////////////////////////////////////////////
524   //
525   // run
526   //
527   
528   if (!pManager->InitAnalysis()) {
529     cerr << "failed to initialize analysis" << endl;
530     return;
531   }
532   if (nevents<0) nevents=1000000000;
533   pManager->PrintStatus();
534   if (bRunLocal) {
535     pManager->StartAnalysis("local", chain, nevents);
536   } else {
537     pManager->StartAnalysis("grid", nevents);
538   }
539 }
540
541 TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass)
542 {
543   // scan the file and add all include headers found by path
544   // to the parameter headers
545   ifstream input(filename);
546   if (input.bad()) {
547     cerr << "failed to open file " << filename << endl;
548     return headers;
549   }
550   TString line; 
551   while (!line.ReadLine(input).eof()) {
552     if (!line.Contains("#include") || !line.Contains(".h")) continue;
553     line=line(0, line.Index(".h"));line+=".h";
554     line.Replace(0, line.Index("#include"), "");
555     line.ReplaceAll("#include", "");
556     line.ReplaceAll(" ", "");
557     line.ReplaceAll("\"", "");
558     if (!line.BeginsWith("Ali") && !line.BeginsWith("T")) continue;
559     if (gSystem->AccessPathName(line)!=0) {
560       // not an include file in the current directory, check if class
561       // is available or find library
562       line.ReplaceAll(".h","");
563       //cout << "checking class " << line << endl;
564       if (TClass::GetClass(line)==NULL) {
565         TString command;
566         TString resfilename(gSystem->TempDirectory()); resfilename+="/findlib.txt";
567         command.Form("for lib in $ALICE_ROOT/lib/*/lib*.so; do (nm $lib | grep %s | grep ' T ' | grep Class_Name > /dev/null) && echo $lib > %s; done", line.Data(), resfilename.Data());
568         gSystem->Exec(command);
569         ifstream resfile(resfilename.Data());
570         if (resfile.good()) {
571           TString result;
572           if (!result.ReadLine(resfile).eof()) {
573             Ssiz_t haveSlash=-1;
574             while ((haveSlash=result.First('/'))>=0) result.Replace(0, haveSlash+1, "");
575             if (!libs.Contains(result)) {
576               cout << "loading dependency library '" << result << "' for class '" << line << "'" << endl;
577               gSystem->Load(result);
578               if (!libs.IsNull()) libs+=" ";
579               libs+=result;
580             }
581           }
582           command="rm "; command+=resfilename;
583           gSystem->Exec(command);
584         }
585       }
586     } else {
587       if (headers.Contains(line)) {
588         if (!headers.BeginsWith(line)) {
589           headers.ReplaceAll(line, "");
590           if (!headers.IsNull()) headers.Insert(0, " ");
591           if (macroVerbosity>0) cout << "moving " << line << endl;
592           headers.Insert(0, line);
593         }
594         continue;
595       }
596       if (!headers.IsNull()) headers.Insert(0, " ");
597       if (macroVerbosity>0) cout << "inserting " << line << endl;
598       headers.Insert(0, line);
599       TString source=line; source.ReplaceAll(".h", ".cxx");
600       if (gSystem->AccessPathName(source)==0) {
601         GetIncludeHeaders(source, headers, libs);
602       }
603       GetIncludeHeaders(line, headers, libs);
604       if (loadClass && gSystem->AccessPathName(source)==0) {
605         line.ReplaceAll(".h", "");
606         if (TClass::GetClass(line)==NULL) {
607           source+="+g";
608           gROOT->LoadMacro(source);
609         }
610       }
611     }
612   }
613
614   return headers;
615 }
616
617 void ErrorConfigurationFile(const char* fileName) {
618   cout << endl;
619   cout << "/// -------------------------------------------------------------------" << endl;
620   cout << "/// Warning: can not find configuration file '" << fileName << "'" << endl;
621   cout << "/// please create a configuration file in either local or HOME directory, or in" << endl;
622   cout << "/// specified location. Below is an example, fill in your preferred defaults." << endl;
623   cout << "/// -------------------------------------------------------------------" << endl;
624   cout << endl;
625   cout << "const char* alienAPIVersion=\"V1.1x\";" << endl;
626   cout << "const char* alienROOTVersion=\"v5-33-02a\";" << endl;
627   cout << "const char* alienAliROOTVersion=\"v5-01-Rev-29\";" << endl;
628   cout << "const char* defaultGridDataDir=\"/alice/data/2011/LHC11f\";" << endl;
629   cout << "const char* defaultDataPattern=\"*ESDs.root\";" << endl;
630   cout << "const char* defaultFriendDataPattern=\"\";" << endl;
631   cout << "{} // note this empty body";
632   cout << endl;
633 }