]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Register only requested branches to cache
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisManager.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 /* $Id$ */
17 // Author: Andrei Gheata, 31/05/2006
18
19 //==============================================================================
20 //   AliAnalysisManager - Manager analysis class. Allows creation of several
21 // analysis tasks and data containers storing their input/output. Allows
22 // connecting/chaining tasks via shared data containers. Serializes the current
23 // event for all tasks depending only on initial input data.
24 //==============================================================================
25 //
26 //==============================================================================
27
28 #include "AliAnalysisManager.h"
29
30 #include <cerrno>
31 #include <Riostream.h>
32 #include <TError.h>
33 #include <TMap.h>
34 #include <TClass.h>
35 #include <TFile.h>
36 #include <TTreeCache.h>
37 #include <TEnv.h>
38 #include <TMath.h>
39 #include <TH1.h>
40 #include <TMethodCall.h>
41 #include <TChain.h>
42 #include <TSystem.h>
43 #include <TROOT.h>
44 #include <TCanvas.h>
45 #include <TStopwatch.h>
46
47 #include "AliLog.h"
48 #include "AliAnalysisSelector.h"
49 #include "AliAnalysisGrid.h"
50 #include "AliAnalysisTask.h"
51 #include "AliAnalysisDataContainer.h"
52 #include "AliAnalysisDataSlot.h"
53 #include "AliVEventHandler.h"
54 #include "AliVEventPool.h"
55 #include "AliSysInfo.h"
56 #include "AliAnalysisStatistics.h"
57
58 using std::ofstream;
59 using std::ios;
60 using std::cout;
61 using std::endl;
62 ClassImp(AliAnalysisManager)
63
64 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
65 TString AliAnalysisManager::fgCommonFileName = "";
66 TString AliAnalysisManager::fgMacroNames = "";
67 Int_t AliAnalysisManager::fPBUpdateFreq = 1;
68
69 //______________________________________________________________________________
70 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
71                    :TNamed(name,title),
72                     fTree(0),
73                     fInputEventHandler(0),
74                     fOutputEventHandler(0),
75                     fMCtruthEventHandler(0),
76                     fEventPool(0),
77                     fCurrentEntry(-1),
78                     fNSysInfo(0),
79                     fMode(kLocalAnalysis),
80                     fInitOK(kFALSE),
81                     fMustClean(kFALSE),
82                     fIsRemote(kFALSE),
83                     fLocked(kFALSE),
84                     fMCLoop(kFALSE),
85                     fDebug(0),
86                     fSpecialOutputLocation(""), 
87                     fTasks(0),
88                     fTopTasks(0),
89                     fZombies(0),
90                     fContainers(0),
91                     fInputs(0),
92                     fOutputs(0),
93                     fParamCont(0),
94                     fDebugOptions(0),
95                     fFileDescriptors(new TObjArray()),
96                     fCurrentDescriptor(0),
97                     fCommonInput(0),
98                     fCommonOutput(0),
99                     fSelector(0),
100                     fGridHandler(0),
101                     fExtraFiles(),
102                     fFileInfoLog(),
103                     fAutoBranchHandling(kTRUE), 
104                     fAsyncReading(kFALSE), // default prefetching on
105                     fTable(),
106                     fRunFromPath(0),
107                     fNcalls(0),
108                     fMaxEntries(0),
109                     fCacheSize(100000000), // default 100 MB
110                     fStatisticsMsg(),
111                     fRequestedBranches(),
112                     fStatistics(0),
113                     fGlobals(0),
114                     fIOTimer(0),
115                     fCPUTimer(0),
116                     fInitTimer(0),
117                     fIOTime(0),
118                     fCPUTime(0),
119                     fInitTime(0)
120 {
121 // Default constructor.
122    fgAnalysisManager = this;
123    fgCommonFileName  = "AnalysisResults.root";
124    if (TClass::IsCallingNew() != TClass::kDummyNew) {
125      fTasks      = new TObjArray();
126      fTopTasks   = new TObjArray();
127      fZombies    = new TObjArray();
128      fContainers = new TObjArray();
129      fInputs     = new TObjArray();
130      fOutputs    = new TObjArray();
131      fParamCont  = new TObjArray();
132      fGlobals    = new TMap();
133    }
134    fIOTimer = new TStopwatch();
135    fCPUTimer = new TStopwatch();
136    fInitTimer = new TStopwatch();
137    SetEventLoop(kTRUE);
138 }
139
140 //______________________________________________________________________________
141 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
142                    :TNamed(other),
143                     fTree(NULL),
144                     fInputEventHandler(NULL),
145                     fOutputEventHandler(NULL),
146                     fMCtruthEventHandler(NULL),
147                     fEventPool(NULL),
148                     fCurrentEntry(-1),
149                     fNSysInfo(0),
150                     fMode(other.fMode),
151                     fInitOK(other.fInitOK),
152                     fMustClean(other.fMustClean),
153                     fIsRemote(other.fIsRemote),
154                     fLocked(other.fLocked),
155                     fMCLoop(other.fMCLoop),
156                     fDebug(other.fDebug),
157                     fSpecialOutputLocation(""), 
158                     fTasks(NULL),
159                     fTopTasks(NULL),
160                     fZombies(NULL),
161                     fContainers(NULL),
162                     fInputs(NULL),
163                     fOutputs(NULL),
164                     fParamCont(NULL),
165                     fDebugOptions(NULL),
166                     fFileDescriptors(new TObjArray()),
167                     fCurrentDescriptor(0),
168                     fCommonInput(NULL),
169                     fCommonOutput(NULL),
170                     fSelector(NULL),
171                     fGridHandler(NULL),
172                     fExtraFiles(other.fExtraFiles),
173                     fFileInfoLog(other.fFileInfoLog),
174                     fAutoBranchHandling(other.fAutoBranchHandling), 
175                     fAsyncReading(other.fAsyncReading),
176                     fTable(),
177                     fRunFromPath(0),
178                     fNcalls(other.fNcalls),
179                     fMaxEntries(other.fMaxEntries),
180                     fCacheSize(other.fCacheSize),
181                     fStatisticsMsg(other.fStatisticsMsg),
182                     fRequestedBranches(other.fRequestedBranches),
183                     fStatistics(other.fStatistics),
184                     fGlobals(other.fGlobals),
185                     fIOTimer(new TStopwatch()),
186                     fCPUTimer(new TStopwatch()),
187                     fInitTimer(new TStopwatch()),
188                     fIOTime(0),
189                     fCPUTime(0),
190                     fInitTime(0)
191 {
192 // Copy constructor.
193    fTasks      = new TObjArray(*other.fTasks);
194    fTopTasks   = new TObjArray(*other.fTopTasks);
195    fZombies    = new TObjArray(*other.fZombies);
196    fContainers = new TObjArray(*other.fContainers);
197    fInputs     = new TObjArray(*other.fInputs);
198    fOutputs    = new TObjArray(*other.fOutputs);
199    fParamCont  = new TObjArray(*other.fParamCont);
200    fgCommonFileName  = "AnalysisResults.root";
201    fgAnalysisManager = this;
202 }
203    
204 //______________________________________________________________________________
205 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
206 {
207 // Assignment
208    if (&other != this) {
209       TNamed::operator=(other);
210       fInputEventHandler   = other.fInputEventHandler;
211       fOutputEventHandler  = other.fOutputEventHandler;
212       fMCtruthEventHandler = other.fMCtruthEventHandler;
213       fEventPool           = other.fEventPool;
214       fTree       = NULL;
215       fCurrentEntry = -1;
216       fNSysInfo   = other.fNSysInfo;
217       fMode       = other.fMode;
218       fInitOK     = other.fInitOK;
219       fIsRemote   = other.fIsRemote;
220       fLocked     = other.fLocked;
221       fMCLoop     = other.fMCLoop;
222       fDebug      = other.fDebug;
223       fTasks      = new TObjArray(*other.fTasks);
224       fTopTasks   = new TObjArray(*other.fTopTasks);
225       fZombies    = new TObjArray(*other.fZombies);
226       fContainers = new TObjArray(*other.fContainers);
227       fInputs     = new TObjArray(*other.fInputs);
228       fOutputs    = new TObjArray(*other.fOutputs);
229       fParamCont  = new TObjArray(*other.fParamCont);
230       fDebugOptions = NULL;
231       fFileDescriptors = new TObjArray();
232       fCurrentDescriptor = 0;
233       fCommonInput = NULL;
234       fCommonOutput = NULL;
235       fSelector   = NULL;
236       fGridHandler = NULL;
237       fExtraFiles = other.fExtraFiles;
238       fFileInfoLog = other.fFileInfoLog;
239       fgCommonFileName = "AnalysisResults.root";
240       fgAnalysisManager = this;
241       fAutoBranchHandling = other.fAutoBranchHandling;
242       fAsyncReading = other.fAsyncReading;
243       fTable.Clear("nodelete");
244       fRunFromPath = other.fRunFromPath;
245       fNcalls     = other. fNcalls;
246       fMaxEntries = other.fMaxEntries;
247       fCacheSize = other.fCacheSize;
248       fStatisticsMsg = other.fStatisticsMsg;
249       fRequestedBranches = other.fRequestedBranches;
250       fStatistics = other.fStatistics;
251       fGlobals = new TMap();
252       fIOTimer = new TStopwatch();
253       fCPUTimer = new TStopwatch();
254       fInitTimer = new TStopwatch();
255       fIOTime = 0.;
256       fCPUTime = 0.;
257       fInitTime = 0.;
258    }
259    return *this;
260 }
261
262 //______________________________________________________________________________
263 AliAnalysisManager::~AliAnalysisManager()
264 {
265 // Destructor.
266    if (fTasks) {fTasks->Delete(); delete fTasks;}
267    if (fTopTasks) delete fTopTasks;
268    if (fZombies) delete fZombies;
269    if (fContainers) {fContainers->Delete(); delete fContainers;}
270    if (fInputs) delete fInputs;
271    if (fOutputs) delete fOutputs;
272    if (fParamCont) delete fParamCont;
273    if (fDebugOptions) delete fDebugOptions;
274    if (fGridHandler) delete fGridHandler;
275    if (fInputEventHandler) delete fInputEventHandler;
276    if (fOutputEventHandler) delete fOutputEventHandler;
277    if (fMCtruthEventHandler) delete fMCtruthEventHandler;
278    if (fEventPool) delete fEventPool;
279    if (fgAnalysisManager==this) fgAnalysisManager = NULL;
280    if (fGlobals) {fGlobals->DeleteAll(); delete fGlobals;}
281    if (fFileDescriptors) {fFileDescriptors->Delete(); delete fFileDescriptors;}
282    delete fIOTimer;
283    delete fCPUTimer;
284    delete fInitTimer;
285 }
286
287 //______________________________________________________________________________
288 void AliAnalysisManager::CreateReadCache()
289 {
290 // Create cache for reading according fCacheSize and fAsyncReading.
291    if (!fTree || !fTree->GetCurrentFile()) {
292       Error("CreateReadCache","Current tree or tree file not yet defined");
293       return;
294    }   
295    if (!fCacheSize) {
296       if (fDebug) Info("CreateReadCache","=== Read caching disabled ===");
297       return;
298    }
299    gEnv->SetValue("TFile.AsyncPrefetching",(Int_t)fAsyncReading);
300    if (fAsyncReading) gEnv->SetValue("Cache.Directory",Form("file://%s/cache", gSystem->WorkingDirectory()));
301    if (fAsyncReading) gEnv->SetValue("TFile.AsyncReading",1);
302    fTree->SetCacheSize(fCacheSize);
303    TTreeCache::SetLearnEntries(1);  //<<< we can take the decision after 1 entry
304    if (!fAutoBranchHandling && !fRequestedBranches.IsNull()) {
305       TObjArray *arr = fRequestedBranches.Tokenize(",");
306       TIter next(arr);
307       TObject *obj;
308       while ((obj=next()))
309          fTree->AddBranchToCache(obj->GetName(),kTRUE);  //<<< add requested branches to cache
310       delete arr;   
311    } else {
312       fTree->AddBranchToCache("*", kTRUE);  //<<< add all branches to cache
313    }   
314    if (fDebug) {
315       Info("CreateReadCache","Read cache enabled %lld bytes with async reading=%d",fCacheSize, (Int_t)fAsyncReading);
316    }
317    return;
318 }   
319
320 //______________________________________________________________________________
321 Bool_t AliAnalysisManager::EventLoop(Long64_t nevents)
322 {
323 // Initialize an event loop where the data producer is the input handler
324 // The handler must implement MakeTree creating the tree of events (likely
325 // memory resident) and generate the current event in the method BeginEvent.
326 // If the tree is memory resident, the handler should never call TTree::Fill
327 // method.
328    cout << "===== RUNNING IN EVENT LOOP MODE: " << GetName() << endl;
329    if (!fInputEventHandler) {
330      Error("EventLoop", "No input handler: exiting");
331      return kFALSE;
332    }
333    TTree *tree = new TTree("DummyTree", "Dummy tree for AliAnalysisManager::EventLoop");
334    SetExternalLoop(kTRUE);
335    if (!Init(tree)) return kFALSE;
336    SlaveBegin(tree);
337    for (Long64_t iev=0; iev<nevents; iev++)
338       ExecAnalysis();
339    TList dummyList;
340    PackOutput(&dummyList);
341    fIsRemote = kTRUE;
342    Terminate();
343    return kTRUE;
344 }
345       
346 //______________________________________________________________________________
347 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
348 {
349 // Read one entry of the tree or a whole branch.
350    fCurrentEntry = entry;
351    if (!fAutoBranchHandling)
352      return 123456789;
353    if (!fTree || !fTree->GetTree()) return -1;
354    fIOTimer->Start(kTRUE); 
355    Long64_t readbytes = fTree->GetTree()->GetEntry(entry, getall);
356    fIOTimer->Stop();
357    fIOTime += fIOTimer->RealTime();
358    return (Int_t)readbytes;
359 }
360
361 //______________________________________________________________________________
362 Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
363 {
364 // Attempt to extract run number from input data path. Works only for paths to
365 // alice data in alien.
366 //    sim:  /alice/sim/<production>/run_no/...
367 //    data: /alice/data/year/period/000run_no/... (ESD or AOD)
368    TString type = "unknown";
369    TString s(path);
370    if (s.Contains("/alice/data")) type = "real";
371    else if (s.Contains("/alice/sim")) type = "simulated";
372    TString srun;
373    Int_t ind1, ind2;
374    ind1 = s.Index("/00");
375    if (ind1>0) {
376       ind2 = s.Index("/",ind1+1);
377       if (ind2-ind1>8) srun = s(ind1+1, ind2-ind1-1);
378    }   
379    if (srun.IsNull()) {
380       ind1 = s.Index("/LHC");
381       if (ind1>0) {
382          ind1 = s.Index("/",ind1+1);
383          if (ind1>0) {
384             ind2 = s.Index("/",ind1+1);
385             if (ind2>0) srun = s(ind1+1, ind2-ind1-1);
386          }
387       }
388    }         
389    Int_t run = srun.Atoi();
390    if (run>0) printf("=== GetRunFromAlienPath: run %d of %s data ===\n", run, type.Data());
391    return run;
392 }   
393
394 //______________________________________________________________________________
395 Bool_t AliAnalysisManager::Init(TTree *tree)
396 {
397   // The Init() function is called when the selector needs to initialize
398   // a new tree or chain. Typically here the branch addresses of the tree
399   // will be set. It is normaly not necessary to make changes to the
400   // generated code, but the routine can be extended by the user if needed.
401   // Init() will be called many times when running with PROOF.
402    Bool_t init = kFALSE;
403    if (!tree) return kFALSE; // Should not happen - protected in selector caller
404    if (fDebug > 1) {
405       printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
406    }
407    // Call InitTree of EventHandler
408    if (fOutputEventHandler) {
409       if (fMode == kProofAnalysis) {
410          init = fOutputEventHandler->Init(0x0, "proof");
411       } else {
412          init = fOutputEventHandler->Init(0x0, "local");
413       }
414       if (!init) {
415          Error("Init", "Output event handler failed to initialize");
416          return kFALSE;
417       }         
418    }
419    
420    if (fInputEventHandler) {
421       if (fMode == kProofAnalysis) {
422          init = fInputEventHandler->Init(tree, "proof");
423       } else {
424          init = fInputEventHandler->Init(tree, "local");
425       }
426       if (!init) {
427          Error("Init", "Input event handler failed to initialize tree"); 
428          return kFALSE;
429       }         
430    } else {
431       // If no input event handler we need to get the tree once
432       // for the chain
433       if(!tree->GetTree()) {
434          Long64_t readEntry = tree->LoadTree(0);
435          if (readEntry == -2) {
436             Error("Init", "Input tree has no entry. Exiting");
437             return kFALSE;
438          }
439       }   
440    }
441
442    if (fMCtruthEventHandler) {
443       if (fMode == kProofAnalysis) {
444          init = fMCtruthEventHandler->Init(0x0, "proof");
445       } else {
446          init = fMCtruthEventHandler->Init(0x0, "local");
447       }
448       if (!init) {
449          Error("Init", "MC event handler failed to initialize"); 
450          return kFALSE;
451       }         
452    }
453
454    if (!fInitOK) InitAnalysis();
455    if (!fInitOK) return kFALSE;
456    fTree = tree;
457    if (fMode != kProofAnalysis) CreateReadCache();
458    else {
459      // cholm - here we should re-add to the table or branches 
460      fTable.Clear();
461    }
462    AliAnalysisDataContainer *top = fCommonInput;
463    if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
464    if (!top) {
465       Error("Init","No top input container !");
466       return kFALSE;
467    }
468    top->SetData(tree);
469    CheckBranches(kFALSE);
470    fTable.Rehash(100);
471    if (fDebug > 1) {
472       printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
473    }
474    return kTRUE;
475 }
476
477 //______________________________________________________________________________
478 void AliAnalysisManager::SlaveBegin(TTree *tree)
479 {
480   // The SlaveBegin() function is called after the Begin() function.
481   // When running with PROOF SlaveBegin() is called on each slave server.
482   // The tree argument is deprecated (on PROOF 0 is passed).
483    if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
484    // Init timer should be already started
485    // Apply debug options
486    ApplyDebugOptions();
487    if (fCacheSize && 
488        fMCtruthEventHandler &&
489        (fMode != kProofAnalysis)) fMCtruthEventHandler->SetCacheSize(fCacheSize);
490    if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded");
491    static Bool_t isCalled = kFALSE;
492    Bool_t init = kFALSE;
493    Bool_t initOK = kTRUE;
494    TString msg;
495    TDirectory *curdir = gDirectory;
496    // Call SlaveBegin only once in case of mixing
497    if (isCalled && fMode==kMixingAnalysis) return;
498    gROOT->cd();
499    // Call Init of EventHandler
500    if (fOutputEventHandler) {
501       if (fMode == kProofAnalysis) {
502          // Merging AOD's in PROOF via TProofOutputFile
503          if (fDebug > 1) printf("   Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
504          init = fOutputEventHandler->Init("proof");
505          if (!init) msg = "Failed to initialize output handler on worker";
506       } else {
507          init = fOutputEventHandler->Init("local");
508          if (!init) msg = "Failed to initialize output handler";
509       }
510       initOK &= init;
511       if (!fSelector) Error("SlaveBegin", "Selector not set");
512       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
513    }
514    gROOT->cd();
515    if (fInputEventHandler) {
516       fInputEventHandler->SetInputTree(tree);
517       if (fMode == kProofAnalysis) {
518          init = fInputEventHandler->Init("proof");
519          if (!init) msg = "Failed to initialize input handler on worker";
520       } else {
521          init = fInputEventHandler->Init("local");
522          if (!init) msg = "Failed to initialize input handler";
523       }
524       initOK &= init;
525       if (!fSelector) Error("SlaveBegin", "Selector not set");      
526       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
527    }
528    gROOT->cd();
529    if (fMCtruthEventHandler) {
530       if (fMode == kProofAnalysis) {
531          init = fMCtruthEventHandler->Init("proof");
532          if (!init) msg = "Failed to initialize MC handler on worker";
533       } else {
534          init = fMCtruthEventHandler->Init("local");
535          if (!init) msg = "Failed to initialize MC handler";
536       }
537       initOK &= init;
538       if (!fSelector) Error("SlaveBegin", "Selector not set");      
539       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
540    }
541    if (curdir) curdir->cd();
542    isCalled = kTRUE;
543    if (!initOK) return;   
544    TIter next(fTasks);
545    AliAnalysisTask *task;
546    // Call CreateOutputObjects for all tasks
547    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
548    Bool_t dirStatus = TH1::AddDirectoryStatus();
549    Int_t itask = 0;
550    while ((task=(AliAnalysisTask*)next())) {
551       gROOT->cd();
552       // Start with memory as current dir and make sure by default histograms do not get attached to files.
553       TH1::AddDirectory(kFALSE);
554       task->CreateOutputObjects();
555       if (!task->CheckPostData()) {
556          Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
557                 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
558                 ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName());
559       }
560       if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
561       itask++;
562    }
563    TH1::AddDirectory(dirStatus);
564    if (curdir) curdir->cd();
565    fInitTimer->Stop();
566    fInitTime += fInitTimer->RealTime();
567    fInitTimer->Continue();
568    printf("Initialization time: %g [sec]\n", fInitTime);
569    if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
570 }
571
572 //______________________________________________________________________________
573 Bool_t AliAnalysisManager::Notify()
574 {
575    // The Notify() function is called when a new file is opened. This
576    // can be either for a new TTree in a TChain or when when a new TTree
577    // is started when using PROOF. It is normaly not necessary to make changes
578    // to the generated code, but the routine can be extended by the
579    // user if needed. The return value is currently not used.
580    fIOTimer->Start(kTRUE); 
581    if (!fTree) return kFALSE;
582    if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) return kFALSE;
583
584    fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
585    if (fMode == kProofAnalysis) fIsRemote = kTRUE;
586
587    TFile *curfile = fTree->GetCurrentFile();
588    if (!curfile) {
589       Error("Notify","No current file");
590       return kFALSE;
591    }  
592    if (IsCollectThroughput()) {
593       if (fCurrentDescriptor) fCurrentDescriptor->Done();
594       fCurrentDescriptor = new AliAnalysisFileDescriptor(curfile);
595       fFileDescriptors->Add(fCurrentDescriptor);
596    } 
597    
598    if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
599    Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
600    if (run && (run != fRunFromPath)) {
601       fRunFromPath = run;
602       if (fDebug > 1) printf("   ### run found from path: %d\n", run);
603    }
604    TIter next(fTasks);
605    AliAnalysisTask *task;
606         
607    // Call Notify of the event handlers
608    if (fInputEventHandler) {
609        fInputEventHandler->Notify(curfile->GetName());
610    }
611
612    if (fOutputEventHandler) {
613        fOutputEventHandler->Notify(curfile->GetName());
614    }
615
616    if (fMCtruthEventHandler) {
617        fMCtruthEventHandler->Notify(curfile->GetName());
618    }
619
620    // Call Notify for all tasks
621    while ((task=(AliAnalysisTask*)next())) 
622       task->Notify();
623
624    if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
625    fIOTimer->Stop();
626    fIOTime += fIOTimer->RealTime();
627    return kTRUE;
628 }    
629
630 //______________________________________________________________________________
631 Bool_t AliAnalysisManager::Process(Long64_t)
632 {
633   // The Process() function is called for each entry in the tree (or possibly
634   // keyed object in the case of PROOF) to be processed. The entry argument
635   // specifies which entry in the currently loaded tree is to be processed.
636   // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
637   // to read either all or the required parts of the data. When processing
638   // keyed objects with PROOF, the object is already loaded and is available
639   // via the fObject pointer.
640   //
641   // This function should contain the "body" of the analysis. It can contain
642   // simple or elaborate selection criteria, run algorithms on the data
643   // of the event and typically fill histograms.
644
645   // WARNING when a selector is used with a TChain, you must use
646   //  the pointer to the current TTree to call GetEntry(entry).
647   //  The entry is always the local entry number in the current tree.
648   //  Assuming that fChain is the pointer to the TChain being processed,
649   //  use fChain->GetTree()->GetEntry(entry).
650
651    // This method is obsolete. ExecAnalysis is called instead.
652    return kTRUE;
653 }
654
655 //______________________________________________________________________________
656 void AliAnalysisManager::PackOutput(TList *target)
657 {
658   // Pack all output data containers in the output list. Called at SlaveTerminate
659   // stage in PROOF case for each slave.
660    if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
661    fIOTimer->Start(kTRUE);
662    std::ofstream out;
663    if (IsCollectThroughput()) {
664       if (fCurrentDescriptor) fCurrentDescriptor->Done();
665       fFileDescriptors->Print();
666       if (fFileInfoLog.IsNull()) fFileInfoLog = "fileinfo.log";
667       out.open(fFileInfoLog, std::ios::app);
668       if (out.bad()) Error("SavePrimitive", "Bad file name: %s", fFileInfoLog.Data());
669       else {
670          TIter nextflog(fFileDescriptors);
671          TObject *log;
672          while ((log=nextflog())) log->SavePrimitive(out,"");
673       }
674    }   
675    if (!target) {
676       Error("PackOutput", "No target. Exiting.");
677       return;
678    }
679    TDirectory *cdir = gDirectory;
680    gROOT->cd();
681    if (fInputEventHandler)   fInputEventHandler  ->Terminate();
682    if (fOutputEventHandler)  fOutputEventHandler ->Terminate();
683    if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
684    gROOT->cd();
685
686    // Call FinishTaskOutput() for each event loop task (not called for 
687    // post-event loop tasks - use Terminate() fo those)
688    TIter nexttask(fTasks);
689    AliAnalysisTask *task;
690    while ((task=(AliAnalysisTask*)nexttask())) {
691       if (!task->IsPostEventLoop()) {
692          if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
693          task->FinishTaskOutput();
694          gROOT->cd();
695          if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
696       }
697    }
698    // Write statistics message on the workers.
699    if (fStatistics) WriteStatisticsMsg(fNcalls);
700    
701    if (fMode == kProofAnalysis) {
702       TIter next(fOutputs);
703       AliAnalysisDataContainer *output;
704       Bool_t isManagedByHandler = kFALSE;
705       TList filestmp;
706       filestmp.SetOwner();
707       while ((output=(AliAnalysisDataContainer*)next())) {
708          // Do not consider outputs of post event loop tasks
709          isManagedByHandler = kFALSE;
710          if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
711          const char *filename = output->GetFileName();
712          if (!(strcmp(filename, "default")) && fOutputEventHandler) {
713             isManagedByHandler = kTRUE;
714             printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
715             filename = fOutputEventHandler->GetOutputFileName();
716          }
717          // Check if data was posted to this container. If not, issue an error.
718          if (!output->GetData() && !isManagedByHandler) {
719             Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
720             continue;
721          }   
722          if (!output->IsSpecialOutput()) {
723             // Normal outputs
724             if (strlen(filename) && !isManagedByHandler) {
725                // Backup current folder
726                TDirectory *opwd = gDirectory;
727                // File resident outputs. 
728                // Check first if the file exists.
729                TString openoption = "RECREATE";
730                Bool_t firsttime = kTRUE;
731                if (filestmp.FindObject(output->GetFileName())) {
732                   firsttime = kFALSE;
733                } else {   
734                   filestmp.Add(new TNamed(output->GetFileName(),""));
735                }   
736                if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
737 //               TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
738                // Save data to file, then close.
739                if (output->GetData()->InheritsFrom(TCollection::Class())) {
740                   // If data is a collection, we set the name of the collection 
741                   // as the one of the container and we save as a single key.
742                   TCollection *coll = (TCollection*)output->GetData();
743                   coll->SetName(output->GetName());
744 //                  coll->Write(output->GetName(), TObject::kSingleKey);
745                } else {
746                   if (output->GetData()->InheritsFrom(TTree::Class())) {
747                      TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
748                      // Save data to file, then close.
749                      TTree *tree = (TTree*)output->GetData();
750                      // Check if tree is in memory
751                      if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
752                      tree->AutoSave();
753                      file->Close();
754                   } else {
755 //                     output->GetData()->Write();
756                   }   
757                }      
758                if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
759 //               if (fDebug > 2) {
760 //                  printf("   file %s listing content:\n", filename);
761 //                  file->ls();
762 //               }   
763                // Clear file list to release object ownership to user.
764 //               file->Clear();
765 //               file->Close();
766                output->SetFile(NULL);
767                // Restore current directory
768                if (opwd) opwd->cd();
769             } else {
770                // Memory-resident outputs   
771                if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
772             }   
773             AliAnalysisDataWrapper *wrap = 0;
774             if (isManagedByHandler) {
775                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
776                wrap->SetName(output->GetName());
777             }   
778             else                    wrap =output->ExportData();
779             // Output wrappers must NOT delete data after merging - the user owns them
780             wrap->SetDeleteData(kFALSE);
781             target->Add(wrap);
782          } else {
783          // Special outputs. The file must be opened and connected to the container.
784             TDirectory *opwd = gDirectory;
785             TFile *file = output->GetFile();
786             if (!file) {
787                AliAnalysisTask *producer = output->GetProducer();
788                Fatal("PackOutput", 
789                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
790                      output->GetFileName(), output->GetName(), producer->ClassName());
791                continue;
792             }   
793             TString outFilename = file->GetName();
794             if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
795             if (isManagedByHandler) {
796                // Terminate IO for files managed by the output handler
797                // file->Write() moved to AOD handler (A.G. 11.01.10)
798 //               if (file) file->Write();
799                if (file && fDebug > 2) {
800                   printf("   handled file %s listing content:\n", file->GetName());
801                   file->ls();
802                }   
803                fOutputEventHandler->TerminateIO();
804             } else {               
805                file->cd();
806                // Release object ownership to users after writing data to file
807                if (output->GetData()->InheritsFrom(TCollection::Class())) {
808                   // If data is a collection, we set the name of the collection 
809                   // as the one of the container and we save as a single key.
810                   TCollection *coll = (TCollection*)output->GetData();
811                   coll->SetName(output->GetName());
812                   coll->Write(output->GetName(), TObject::kSingleKey);
813                } else {
814                   if (output->GetData()->InheritsFrom(TTree::Class())) {
815                      TTree *tree = (TTree*)output->GetData();
816                      tree->SetDirectory(file);
817                      tree->AutoSave();
818                   } else {
819                      output->GetData()->Write();
820                   }   
821                }      
822                if (fDebug > 2) {
823                   printf("   file %s listing content:\n", output->GetFileName());
824                   file->ls();
825                }
826                // Clear file list to release object ownership to user.
827 //               file->Clear();
828                file->Close();
829                output->SetFile(NULL);
830             }
831             // Restore current directory
832             if (opwd) opwd->cd();
833             // Check if a special output location was provided or the output files have to be merged
834             if (strlen(fSpecialOutputLocation.Data())) {
835                TString remote = fSpecialOutputLocation;
836                remote += "/";
837                Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
838                if (remote.BeginsWith("alien:")) {
839                   gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
840                   remote += outFilename;
841                   remote.ReplaceAll(".root", Form("_%d.root", gid));
842                } else {   
843                   remote += Form("%s_%d_", gSystem->HostName(), gid);
844                   remote += outFilename;
845                }   
846                if (fDebug > 1) 
847                   Info("PackOutput", "Output file for container %s to be copied \n   at: %s. No merging.",
848                        output->GetName(), remote.Data());
849                TFile::Cp ( outFilename.Data(), remote.Data() );
850                // Copy extra outputs
851                if (fExtraFiles.Length() && isManagedByHandler) {
852                   TObjArray *arr = fExtraFiles.Tokenize(" ");
853                   TObjString *os;
854                   TIter nextfilename(arr);
855                   while ((os=(TObjString*)nextfilename())) {
856                      outFilename = os->GetString();
857                      remote = fSpecialOutputLocation;
858                      remote += "/";
859                      if (remote.BeginsWith("alien://")) {
860                         remote += outFilename;
861                         remote.ReplaceAll(".root", Form("_%d.root", gid));
862                      } else {   
863                         remote += Form("%s_%d_", gSystem->HostName(), gid);
864                         remote += outFilename;
865                      }   
866                      if (fDebug > 1) 
867                         Info("PackOutput", "Extra AOD file %s to be copied \n   at: %s. No merging.",
868                              outFilename.Data(), remote.Data());
869                      TFile::Cp ( outFilename.Data(), remote.Data() );
870                   }   
871                   delete arr;
872                }   
873             } else {
874             // No special location specified-> use TProofOutputFile as merging utility
875             // The file at this output slot must be opened in CreateOutputObjects
876                if (fDebug > 1) printf("   File for container %s to be merged via file merger...\n", output->GetName());
877             }
878          }      
879       }
880    } 
881    fIOTime += fIOTimer->RealTime();
882    if ((fDebug || IsCollectThroughput())) {
883       fInitTimer->Stop();
884       fInitTime = fInitTimer->RealTime()-fIOTime-fCPUTime;
885       printf("=Analysis %s= init time:       %g[sec]\
886             \n              I/O & data mng.: %g [sec]\
887             \n              task execution: %g [sec]\
888             \n              total time:     CPU=%g [sec]  REAL=%g[sec]\n",
889             GetName(), fInitTime, fIOTime, fCPUTime, fInitTimer->CpuTime(), fInitTimer->RealTime());
890       if (IsCollectThroughput()) {
891          out << "#summary#########################################################" << endl;
892          out << "train_name   " << GetName() << endl;
893          out << "root_time    " << fInitTimer->RealTime() << endl;
894          out << "root_cpu     " << fInitTimer->CpuTime() << endl;
895          out << "init_time    " << fInitTime << endl;
896          out << "io_mng_time  " << fIOTime << endl;
897          out << "exec_time    " << fCPUTime << endl;
898          TString aliensite = gSystem->Getenv("ALIEN_SITE");
899          out << "alien_site   " << aliensite << endl;
900          out << "host_name    ";
901          TString hostname = gSystem->Getenv("ALIEN_HOSTNAME");
902          if (hostname.IsNull()) {
903             out.close();
904             gSystem->Exec(Form("hostname -f >> %s", fFileInfoLog.Data()));
905          } else {
906             out << hostname << endl;
907          }   
908       }
909    }
910               
911    if (cdir) cdir->cd();
912    if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
913 }
914
915 //______________________________________________________________________________
916 void AliAnalysisManager::ImportWrappers(TList *source)
917 {
918 // Import data in output containers from wrappers coming in source.
919    if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
920    fIOTimer->Start(kTRUE);
921    TIter next(fOutputs);
922    AliAnalysisDataContainer *cont;
923    AliAnalysisDataWrapper   *wrap;
924    Int_t icont = 0;
925    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
926    TDirectory *cdir = gDirectory;
927    while ((cont=(AliAnalysisDataContainer*)next())) {
928       wrap = 0;
929       if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
930       if (cont->IsRegisterDataset()) continue;
931       const char *filename = cont->GetFileName();
932       Bool_t isManagedByHandler = kFALSE;
933       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
934          isManagedByHandler = kTRUE;
935          filename = fOutputEventHandler->GetOutputFileName();
936       }
937       if (cont->IsSpecialOutput() || inGrid) {
938          if (strlen(fSpecialOutputLocation.Data())) continue;
939          // Copy merged file from PROOF scratch space. 
940          // In case of grid the files are already in the current directory.
941          if (!inGrid) {
942             if (isManagedByHandler && fExtraFiles.Length()) {
943                // Copy extra registered dAOD files.
944                TObjArray *arr = fExtraFiles.Tokenize(" ");
945                TObjString *os;
946                TIter nextfilename(arr);
947                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
948                delete arr;
949             }
950             if (!GetFileFromWrapper(filename, source)) continue;
951          }   
952          // Normally we should connect data from the copied file to the
953          // corresponding output container, but it is not obvious how to do this
954          // automatically if several objects in file...
955          TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
956          if (!f) f = TFile::Open(filename, "READ");
957          if (!f) {
958             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
959             continue;
960          }   
961          f->cd();
962          TObject *obj = 0;
963          // Cd to the directory pointed by the container
964          TString folder = cont->GetFolderName();
965          if (!folder.IsNull()) f->cd(folder);
966          // Try to fetch first an object having the container name.
967          obj = gDirectory->Get(cont->GetName());
968          if (!obj) {
969             Warning("ImportWrappers", "Could not import object of type:%s for container %s in file %s:%s.\n Object will not be available in Terminate(). Try if possible to name the output object as the container (%s) or to embed it in a TList", 
970                     cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
971             continue;
972          }  
973          wrap = new AliAnalysisDataWrapper(obj);
974          wrap->SetDeleteData(kFALSE);
975       }   
976       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
977       if (!wrap) {
978          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
979          continue;
980       }
981       icont++;
982       if (fDebug > 1) {
983          printf("   Importing data for container %s\n", cont->GetName());
984          if (strlen(filename)) printf("    -> file %s\n", filename);
985          else printf("\n");
986       }   
987       cont->ImportData(wrap);
988    }
989    if (cdir) cdir->cd();
990    fIOTimer->Stop();
991    fIOTime += fIOTimer->RealTime();
992    if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
993 }
994
995 //______________________________________________________________________________
996 void AliAnalysisManager::UnpackOutput(TList *source)
997 {
998   // Called by AliAnalysisSelector::Terminate only on the client.
999    fIOTimer->Start(kTRUE);
1000    if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
1001    if (!source) {
1002       Error("UnpackOutput", "No target. Exiting.");
1003       return;
1004    }
1005    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
1006
1007    if (fMode == kProofAnalysis) ImportWrappers(source);
1008
1009    TIter next(fOutputs);
1010    AliAnalysisDataContainer *output;
1011    while ((output=(AliAnalysisDataContainer*)next())) {
1012       if (!output->GetData()) continue;
1013       // Check if there are client tasks that run post event loop
1014       if (output->HasConsumers()) {
1015          // Disable event loop semaphore
1016          output->SetPostEventLoop(kTRUE);
1017          TObjArray *list = output->GetConsumers();
1018          Int_t ncons = list->GetEntriesFast();
1019          for (Int_t i=0; i<ncons; i++) {
1020             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
1021             task->CheckNotify(kTRUE);
1022             // If task is active, execute it
1023             if (task->IsPostEventLoop() && task->IsActive()) {
1024                if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
1025                if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
1026                task->ExecuteTask();
1027             }   
1028          }
1029          if (fStatistics) fStatistics->StopTimer();
1030       }   
1031    }
1032    fIOTimer->Stop();
1033    fIOTime += fIOTimer->RealTime();
1034    if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
1035 }
1036
1037 //______________________________________________________________________________
1038 void AliAnalysisManager::Terminate()
1039 {
1040   // The Terminate() function is the last function to be called during
1041   // a query. It always runs on the client, it can be used to present
1042   // the results graphically.
1043    if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
1044    fInitTimer->Start(kTRUE);
1045    TDirectory *cdir = gDirectory;
1046    gROOT->cd();
1047    AliAnalysisTask *task;
1048    AliAnalysisDataContainer *output;
1049    TIter next(fTasks);
1050    TStopwatch timer;
1051    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1052    // Call Terminate() for tasks
1053    Int_t itask = 0;
1054    while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
1055       // Save all the canvases produced by the Terminate
1056       TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
1057       task->Terminate();
1058       gROOT->cd();
1059       if (getsysInfo) 
1060          AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
1061       itask++;   
1062       if (TObject::TestBit(kSaveCanvases)) {
1063          if (!gROOT->IsBatch()) {
1064             if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
1065             timer.Start(kTRUE);
1066             while (timer.RealTime()<5) {
1067                timer.Continue();
1068                gSystem->ProcessEvents();
1069             }
1070          }
1071          Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
1072          if (iend==0) continue;
1073          TCanvas *canvas;
1074          for (Int_t ipict=0; ipict<iend; ipict++) {
1075             canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
1076             if (!canvas) continue;         
1077             canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
1078          } 
1079          gROOT->GetListOfCanvases()->Delete(); 
1080       }
1081    }   
1082    //
1083    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
1084    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
1085    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
1086    gROOT->cd();
1087    TObjArray *allOutputs = new TObjArray();
1088    Int_t icont;
1089    for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
1090    if (!IsSkipTerminate())
1091       for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
1092    TIter next1(allOutputs);
1093    TString handlerFile = "";
1094    TString extraOutputs = "";
1095    if (fOutputEventHandler) {
1096       handlerFile = fOutputEventHandler->GetOutputFileName();
1097       extraOutputs = fOutputEventHandler->GetExtraOutputs();
1098    }
1099    icont = 0;
1100    TList filestmp;
1101    while ((output=(AliAnalysisDataContainer*)next1())) {
1102       // Special outputs or grid files have the files already closed and written.
1103       icont++;
1104       if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
1105       if (fMode == kProofAnalysis) {
1106         if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
1107       }  
1108       const char *filename = output->GetFileName();
1109       TString openoption = "RECREATE";
1110       if (!(strcmp(filename, "default"))) continue;
1111       if (!strlen(filename)) continue;
1112       if (!output->GetData()) continue;
1113       TDirectory *opwd = gDirectory;
1114       TFile *file = output->GetFile();
1115       if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1116       if (!file) {
1117               //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
1118          Bool_t firsttime = kTRUE;
1119          if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
1120             firsttime = kFALSE;
1121          } else {   
1122             filestmp.Add(new TNamed(filename,""));
1123          }   
1124          if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
1125               if (fDebug>1) printf("Opening file: %s  option=%s\n",filename, openoption.Data());
1126          file = new TFile(filename, openoption);
1127       } else {
1128          if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
1129          openoption = file->GetOption();
1130          if (openoption == "READ") {
1131             if (fDebug>1) printf("...reopening in UPDATE mode\n");
1132             file->ReOpen("UPDATE");            
1133          }
1134       }   
1135       if (file->IsZombie()) {
1136          Error("Terminate", "Cannot open output file %s", filename);
1137          continue;
1138       }   
1139       output->SetFile(file);
1140       file->cd();
1141       // Check for a folder request
1142       TString dir = output->GetFolderName();
1143       if (!dir.IsNull()) {
1144          if (!file->GetDirectory(dir)) file->mkdir(dir);
1145          file->cd(dir);
1146       }  
1147       if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1148       if (output->GetData()->InheritsFrom(TCollection::Class())) {
1149       // If data is a collection, we set the name of the collection 
1150       // as the one of the container and we save as a single key.
1151          TCollection *coll = (TCollection*)output->GetData();
1152          coll->SetName(output->GetName());
1153          coll->Write(output->GetName(), TObject::kSingleKey);
1154       } else {
1155          if (output->GetData()->InheritsFrom(TTree::Class())) {
1156             TTree *tree = (TTree*)output->GetData();
1157             tree->SetDirectory(gDirectory);
1158             tree->AutoSave();
1159          } else {
1160             output->GetData()->Write();
1161          }   
1162       }      
1163       if (opwd) opwd->cd();
1164    }
1165    gROOT->cd();
1166    next1.Reset();
1167    TString copiedFiles;
1168    while ((output=(AliAnalysisDataContainer*)next1())) {
1169       // Close all files at output
1170       TDirectory *opwd = gDirectory;
1171       if (output->GetFile()) {
1172          // Clear file list to release object ownership to user.
1173 //         output->GetFile()->Clear();
1174          output->GetFile()->Close();
1175          // Copy merged outputs in alien if requested
1176          if (fSpecialOutputLocation.BeginsWith("alien://")) {
1177             if (copiedFiles.Contains(output->GetFile()->GetName())) {
1178                if (opwd) opwd->cd();
1179                output->SetFile(NULL);
1180                continue;
1181             } 
1182             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
1183             gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
1184             TFile::Cp(output->GetFile()->GetName(), 
1185                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
1186             copiedFiles += output->GetFile()->GetName();
1187          }             
1188          output->SetFile(NULL);
1189       }   
1190       if (opwd) opwd->cd();
1191    }   
1192    delete allOutputs;
1193    //Write statistics information on the client
1194    if (fStatistics) WriteStatisticsMsg(fNcalls);
1195    if (getsysInfo) {
1196       TDirectory *crtdir = gDirectory;
1197       TFile f("syswatch.root", "RECREATE");
1198       TH1 *hist;
1199       TString cut;
1200       if (!f.IsZombie()) {
1201          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
1202          tree->SetName("syswatch");
1203          tree->SetMarkerStyle(kCircle);
1204          tree->SetMarkerColor(kBlue);
1205          tree->SetMarkerSize(0.5);
1206          if (!gROOT->IsBatch()) {
1207             tree->SetAlias("event", "id0");
1208             tree->SetAlias("task",  "id1");
1209             tree->SetAlias("stage", "id2");
1210             // Already defined aliases
1211             // tree->SetAlias("deltaT","stampSec-stampOldSec");
1212             // tree->SetAlias("T","stampSec-first");
1213             // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1214             // tree->SetAlias("VM","pI.fMemVirtual");
1215             TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1216             Int_t npads = 1 /*COO plot for all tasks*/ +
1217                           fTopTasks->GetEntries() /*Exec plot per task*/ +
1218                           1 /*Terminate plot for all tasks*/ +
1219                           1; /*vm plot*/
1220                           
1221             Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1222             if (npads<iopt*(iopt+1))
1223                canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1224             else
1225                canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1226             Int_t ipad = 1;
1227             // draw the plot of deltaVM for Exec for each task
1228             for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1229                task = (AliAnalysisTask*)fTopTasks->At(itask);
1230                canvas->cd(ipad++);
1231                cut = Form("task==%d && stage==1", itask);
1232                tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1233                hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
1234                if (hist) {
1235                   hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1236                   hist->GetYaxis()->SetTitle("deltaVM [MB]");
1237                }   
1238             }
1239             // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1240             canvas->cd(ipad++);
1241             tree->SetMarkerStyle(kFullTriangleUp);
1242             tree->SetMarkerColor(kRed);
1243             tree->SetMarkerSize(0.8);
1244             cut = "task>=0 && task<1000 && stage==0";
1245             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1246             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
1247             if (hist) {
1248                hist->SetTitle("Memory in CreateOutputObjects()");
1249                hist->GetYaxis()->SetTitle("deltaVM [MB]");
1250                hist->GetXaxis()->SetTitle("task");
1251             }   
1252             // draw the plot of deltaVM for Terminate for all tasks
1253             canvas->cd(ipad++);
1254             tree->SetMarkerStyle(kOpenSquare);
1255             tree->SetMarkerColor(kMagenta);
1256             cut = "task>=0 && task<1000 && stage==2";
1257             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1258             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1259             if (hist) {
1260                hist->SetTitle("Memory in Terminate()");
1261                hist->GetYaxis()->SetTitle("deltaVM [MB]");
1262                hist->GetXaxis()->SetTitle("task");
1263             }   
1264             // Full VM profile
1265             canvas->cd(ipad++);
1266             tree->SetMarkerStyle(kFullCircle);
1267             tree->SetMarkerColor(kGreen);
1268             cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);            
1269             tree->Draw("VM:event",cut,"", 1234567890, 0);
1270             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1271             if (hist) {
1272                hist->SetTitle("Virtual memory");
1273                hist->GetYaxis()->SetTitle("VM [MB]");
1274             }
1275             canvas->Modified();   
1276          }   
1277          tree->SetMarkerStyle(kCircle);
1278          tree->SetMarkerColor(kBlue);
1279          tree->SetMarkerSize(0.5);
1280          tree->Write();
1281          f.Close();
1282          delete tree;
1283       }
1284       if (crtdir) crtdir->cd();
1285    }
1286    // Validate the output files
1287    if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1288       ofstream out;
1289       out.open("outputs_valid", ios::out);
1290       out.close();
1291    }
1292    if (cdir) cdir->cd();  
1293    fInitTimer->Stop();
1294    if (fDebug || IsCollectThroughput()) {
1295       printf("=Analysis %s= Terminate time:  %g[sec]\n", GetName(), fInitTimer->RealTime());
1296    }
1297    if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1298 }
1299 //______________________________________________________________________________
1300 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1301 {
1302 // Profiles the task having the itop index in the list of top (first level) tasks.
1303    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1304    if (!task) {
1305       Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1306       return;
1307    }
1308    ProfileTask(task->GetName(), option);
1309 }      
1310
1311 //______________________________________________________________________________
1312 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1313 {
1314 // Profile a managed task after the execution of the analysis in case NSysInfo
1315 // was used.
1316    if (gSystem->AccessPathName("syswatch.root")) {
1317       Error("ProfileTask", "No file syswatch.root found in the current directory");
1318       return;
1319    }
1320    if (gROOT->IsBatch()) return;
1321    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1322    if (!task) {
1323       Error("ProfileTask", "No top task named %s known by the manager.", name);
1324       return;
1325    }
1326    Int_t itop = fTopTasks->IndexOf(task);
1327    Int_t itask = fTasks->IndexOf(task);
1328    // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1329    TDirectory *cdir = gDirectory;
1330    TFile f("syswatch.root");
1331    TTree *tree = (TTree*)f.Get("syswatch");
1332    if (!tree) {
1333       Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1334       return;
1335    }   
1336    if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1337    TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1338    canvas->Divide(2, 2, 0.01, 0.01);
1339    Int_t ipad = 1;
1340    TString cut;
1341    TH1 *hist;
1342    // VM profile for COO and Terminate methods
1343    canvas->cd(ipad++);
1344    cut = Form("task==%d && (stage==0 || stage==2)",itask);
1345    tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1346    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1347    if (hist) {
1348       hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1349       hist->GetYaxis()->SetTitle("deltaVM [MB]");
1350       hist->GetXaxis()->SetTitle("method");
1351    }   
1352    // CPU profile per event
1353    canvas->cd(ipad++);
1354    cut = Form("task==%d && stage==1",itop);
1355    tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1356    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1357    if (hist) {
1358       hist->SetTitle("Execution time per event");
1359       hist->GetYaxis()->SetTitle("CPU/event [s]");
1360    }   
1361    // VM profile for Exec
1362    canvas->cd(ipad++);
1363    cut = Form("task==%d && stage==1",itop);
1364    tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1365    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1366    if (hist) {
1367       hist->SetTitle("Alocated VM[MB] per event");
1368       hist->GetYaxis()->SetTitle("deltaVM [MB]");
1369    }   
1370    canvas->Modified();
1371    delete tree;
1372    f.Close();
1373    if (cdir) cdir->cd();
1374 }     
1375
1376 //______________________________________________________________________________
1377 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1378 {
1379 // Adds a user task to the global list of tasks.
1380    if (fInitOK) {
1381       Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1382       return;
1383    }   
1384       
1385    if (fTasks->FindObject(task)) {
1386       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1387       return;
1388    }   
1389    task->SetActive(kFALSE);
1390    fTasks->Add(task);
1391 }  
1392
1393 //______________________________________________________________________________
1394 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1395 {
1396 // Retreive task by name.
1397    if (!fTasks) return NULL;
1398    return (AliAnalysisTask*)fTasks->FindObject(name);
1399 }
1400
1401 //______________________________________________________________________________
1402 Int_t AliAnalysisManager::GetTaskIndex(const AliAnalysisTask *task) const
1403 {
1404 // Returns task inded in the manager's list, -1 if not registered.
1405    if (!fTasks) return -1;
1406    return fTasks->IndexOf(task);
1407 }  
1408
1409 //______________________________________________________________________________
1410 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
1411                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
1412 {
1413 // Create a data container of a certain type. Types can be:
1414 //   kExchangeContainer  = 0, used to exchange data between tasks
1415 //   kInputContainer   = 1, used to store input data
1416 //   kOutputContainer  = 2, used for writing result to a file
1417 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1418 // the output object to a folder inside the output file
1419    if (fContainers->FindObject(name)) {
1420       Error("CreateContainer","A container named %s already defined !",name);
1421       return NULL;
1422    }   
1423    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1424    fContainers->Add(cont);
1425    switch (type) {
1426       case kInputContainer:
1427          fInputs->Add(cont);
1428          break;
1429       case kOutputContainer:
1430          fOutputs->Add(cont);
1431          if (filename && strlen(filename)) {
1432             cont->SetFileName(filename);
1433             cont->SetDataOwned(kFALSE);  // data owned by the file
1434          }   
1435          break;
1436       case kParamContainer:
1437          fParamCont->Add(cont);
1438          if (filename && strlen(filename)) {
1439             cont->SetFileName(filename);
1440             cont->SetDataOwned(kFALSE);  // data owned by the file
1441          }   
1442          break;
1443       case kExchangeContainer:
1444          break;   
1445    }
1446    return cont;
1447 }
1448          
1449 //______________________________________________________________________________
1450 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1451                                         AliAnalysisDataContainer *cont)
1452 {
1453 // Connect input of an existing task to a data container.
1454    if (!task) {
1455       Error("ConnectInput", "Task pointer is NULL");
1456       return kFALSE;
1457    }   
1458    if (!fTasks->FindObject(task)) {
1459       AddTask(task);
1460       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1461    } 
1462    Bool_t connected = task->ConnectInput(islot, cont);
1463    return connected;
1464 }   
1465
1466 //______________________________________________________________________________
1467 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1468                                         AliAnalysisDataContainer *cont)
1469 {
1470 // Connect output of an existing task to a data container.
1471    if (!task) {
1472       Error("ConnectOutput", "Task pointer is NULL");
1473       return kFALSE;
1474    }   
1475    if (!fTasks->FindObject(task)) {
1476       AddTask(task);
1477       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1478    } 
1479    Bool_t connected = task->ConnectOutput(islot, cont);
1480    return connected;
1481 }   
1482                                
1483 //______________________________________________________________________________
1484 void AliAnalysisManager::CleanContainers()
1485 {
1486 // Clean data from all containers that have already finished all client tasks.
1487    TIter next(fContainers);
1488    AliAnalysisDataContainer *cont;
1489    while ((cont=(AliAnalysisDataContainer *)next())) {
1490       if (cont->IsOwnedData() && 
1491           cont->IsDataReady() && 
1492           cont->ClientsExecuted()) cont->DeleteData();
1493    }
1494 }
1495
1496 //______________________________________________________________________________
1497 Bool_t AliAnalysisManager::InitAnalysis()
1498 {
1499 // Initialization of analysis chain of tasks. Should be called after all tasks
1500 // and data containers are properly connected
1501    // Reset flag and remove valid_outputs file if exists
1502    if (fInitOK) return kTRUE;
1503    if (!gSystem->AccessPathName("outputs_valid"))
1504       gSystem->Unlink("outputs_valid");
1505    // Check for top tasks (depending only on input data containers)
1506    if (!fTasks->First()) {
1507       Error("InitAnalysis", "Analysis has no tasks !");
1508       return kFALSE;
1509    }   
1510    TIter next(fTasks);
1511    AliAnalysisTask *task;
1512    AliAnalysisDataContainer *cont;
1513    Int_t ntop = 0;
1514    Int_t nzombies = 0;
1515    Bool_t iszombie = kFALSE;
1516    Bool_t istop = kTRUE;
1517    Int_t i;
1518    while ((task=(AliAnalysisTask*)next())) {
1519       istop = kTRUE;
1520       iszombie = kFALSE;
1521       Int_t ninputs = task->GetNinputs();
1522       for (i=0; i<ninputs; i++) {
1523          cont = task->GetInputSlot(i)->GetContainer();
1524          if (!cont) {
1525             if (!iszombie) {
1526                task->SetZombie();
1527                fZombies->Add(task);
1528                nzombies++;
1529                iszombie = kTRUE;
1530             }   
1531             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
1532                   i, task->GetName()); 
1533          }
1534          if (iszombie) continue;
1535          // Check if cont is an input container
1536          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1537          // Connect to parent task
1538       }
1539       if (istop) {
1540          ntop++;
1541          fTopTasks->Add(task);
1542       }
1543    }
1544    if (!ntop) {
1545       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1546       return kFALSE;
1547    }                        
1548    // Check now if there are orphan tasks
1549    for (i=0; i<ntop; i++) {
1550       task = (AliAnalysisTask*)fTopTasks->At(i);
1551       task->SetUsed();
1552    }
1553    Int_t norphans = 0;
1554    next.Reset();
1555    while ((task=(AliAnalysisTask*)next())) {
1556       if (!task->IsUsed()) {
1557          norphans++;
1558          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1559       }   
1560    }          
1561    // Check the task hierarchy (no parent task should depend on data provided
1562    // by a daughter task)
1563    for (i=0; i<ntop; i++) {
1564       task = (AliAnalysisTask*)fTopTasks->At(i);
1565       if (task->CheckCircularDeps()) {
1566          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1567          PrintStatus("dep");
1568          return kFALSE;
1569       }   
1570    }
1571    // Check that all containers feeding post-event loop tasks are in the outputs list
1572    TIter nextcont(fContainers); // loop over all containers
1573    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1574       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1575          if (cont->HasConsumers()) {
1576          // Check if one of the consumers is post event loop
1577             TIter nextconsumer(cont->GetConsumers());
1578             while ((task=(AliAnalysisTask*)nextconsumer())) {
1579                if (task->IsPostEventLoop()) {
1580                   fOutputs->Add(cont);
1581                   break;
1582                }
1583             }
1584          }
1585       }
1586    }   
1587    // Check if all special output containers have a file name provided
1588    TIter nextout(fOutputs);
1589    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1590       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1591          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1592          return kFALSE;
1593       }
1594    }
1595    // Initialize requested branch list if needed
1596    if (!fAutoBranchHandling) {
1597       next.Reset();
1598       while ((task=(AliAnalysisTask*)next())) {
1599          if (!task->HasBranches()) {
1600             Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches.\nUse: fBranchNames = \"ESD:br1,br2,...,brN AOD:bra1,bra2,...,braM\"",
1601                   task->GetName(), task->ClassName());
1602             return kFALSE;
1603          }
1604          if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1605             Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1606             return kFALSE;
1607          }
1608          TString taskbranches;
1609          task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1610          if (taskbranches.IsNull()) {
1611             Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1612                   task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1613             return kFALSE;      
1614          }
1615          AddBranches(taskbranches);
1616       }         
1617    }
1618    fInitOK = kTRUE;
1619    return kTRUE;
1620 }   
1621
1622 //______________________________________________________________________________
1623 void AliAnalysisManager::AddBranches(const char *branches)
1624 {
1625 // Add branches to the existing fRequestedBranches.
1626    TString br(branches);
1627    TObjArray *arr = br.Tokenize(",");
1628    TIter next(arr);
1629    TObject *obj;
1630    while ((obj=next())) {
1631       if (!fRequestedBranches.Contains(obj->GetName())) {
1632          if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1633          fRequestedBranches += obj->GetName();
1634       }
1635    }
1636   delete arr;
1637 }   
1638
1639 //______________________________________________________________________________
1640 void AliAnalysisManager::CheckBranches(Bool_t load)
1641 {
1642 // The method checks the input branches to be loaded during the analysis.
1643    if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;   
1644    TObjArray *arr = fRequestedBranches.Tokenize(",");
1645    TIter next(arr);
1646    TObject *obj;
1647    while ((obj=next())) {
1648       TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1649       if (!br) {
1650          br = fTree->GetBranch(obj->GetName());
1651          if (!br) {
1652             Error("CheckBranches", "Could not find branch %s",obj->GetName());
1653             continue;
1654          }
1655          fTable.Add(br);
1656       }   
1657       if (load && br->GetReadEntry()!=GetCurrentEntry()) {
1658          br->GetEntry(GetCurrentEntry());
1659       }      
1660    }
1661   delete arr;
1662 }
1663
1664 //______________________________________________________________________________
1665 Bool_t AliAnalysisManager::CheckTasks() const
1666 {
1667 // Check consistency of tasks.
1668    Int_t ntasks = fTasks->GetEntries();
1669    if (!ntasks) {
1670       Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1671       return kFALSE;
1672    }
1673    // Get the pointer to AliAnalysisTaskSE::Class()
1674    TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1675    // Loop all tasks to check if their corresponding library was loaded
1676    TIter next(fTasks);
1677    TObject *obj;
1678    while ((obj=next())) {
1679       if (obj->IsA() == badptr) {
1680          Error("CheckTasks", "##################\n \
1681          Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1682          return kFALSE;
1683       }
1684    }
1685    return kTRUE;      
1686 }   
1687
1688 //______________________________________________________________________________
1689 void AliAnalysisManager::PrintStatus(Option_t *option) const
1690 {
1691 // Print task hierarchy.
1692    if (!fInitOK) {
1693       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1694       return;
1695    }   
1696    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1697    if (getsysInfo)
1698       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1699    TIter next(fTopTasks);
1700    AliAnalysisTask *task;
1701    while ((task=(AliAnalysisTask*)next()))
1702       task->PrintTask(option);
1703   
1704    if (!fAutoBranchHandling && !fRequestedBranches.IsNull()) 
1705       printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1706   
1707   TString sopt(option);
1708   sopt.ToUpper();
1709   
1710   if (sopt.Contains("ALL"))
1711   {
1712     if ( fOutputEventHandler )
1713     {
1714       cout << TString('_',78) << endl;
1715       cout << "OutputEventHandler:" << endl;
1716       fOutputEventHandler->Print("   ");
1717     }
1718   }
1719 }
1720
1721 //______________________________________________________________________________
1722 void AliAnalysisManager::ResetAnalysis()
1723 {
1724 // Reset all execution flags and clean containers.
1725    CleanContainers();
1726 }
1727
1728 //______________________________________________________________________________
1729 void AliAnalysisManager::RunLocalInit()
1730 {
1731 // Run LocalInit method for all tasks.
1732    TDirectory *cdir = gDirectory;
1733    if (IsTrainInitialized()) return;
1734    TIter nextTask(fTasks);
1735    AliAnalysisTask *task;
1736    while ((task=(AliAnalysisTask*)nextTask())) {
1737       gROOT->cd();
1738       task->LocalInit();
1739    }
1740    if (cdir) cdir->cd();
1741    TObject::SetBit(kTasksInitialized, kTRUE);
1742 }   
1743
1744 //______________________________________________________________________________
1745 void AliAnalysisManager::InputFileFromTree(TTree * const tree, TString &fname)
1746 {
1747 // Retrieves name of the file from tree
1748    fname = "";
1749    if (!tree) return;
1750    TFile *file = tree->GetCurrentFile();
1751    TString basename;
1752    if (!file) {
1753       TChain *chain = dynamic_cast<TChain*>(tree);
1754       if (!chain || !chain->GetNtrees()) return;
1755       basename = gSystem->BaseName(chain->GetListOfFiles()->First()->GetTitle());
1756    } else {   
1757       basename = gSystem->BaseName(file->GetName());
1758    }   
1759    Int_t index = basename.Index("#");
1760    fname = basename(index+1, basename.Length());
1761 }   
1762
1763 //______________________________________________________________________________
1764 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1765 {
1766 // Start analysis having a grid handler.
1767    if (!fGridHandler) {
1768       Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1769       Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1770       return -1;
1771    }
1772    TTree *tree = NULL;
1773    return StartAnalysis(type, tree, nentries, firstentry);
1774 }
1775
1776 //______________________________________________________________________________
1777 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1778 {
1779 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1780 // MIX. Process nentries starting from firstentry
1781    Long64_t retv = 0;
1782    // Backup current directory and make sure gDirectory points to gROOT
1783    TDirectory *cdir = gDirectory;
1784    gROOT->cd();
1785    if (!fInitOK) {
1786       Error("StartAnalysis","Analysis manager was not initialized !");
1787       if (cdir) cdir->cd();
1788       return -1;
1789    }
1790    if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1791    if (fDebug > 1) {
1792       printf("StartAnalysis %s\n",GetName());
1793       AliLog::SetGlobalLogLevel(AliLog::kInfo);
1794    }
1795    fMaxEntries = nentries;
1796    fIsRemote = kFALSE;
1797    TString anaType = type;
1798    anaType.ToLower();
1799    fMode = kLocalAnalysis;
1800    if (anaType.Contains("file"))      fIsRemote = kTRUE;
1801    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1802    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1803    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1804    if (fInputEventHandler) {
1805       TString fname;
1806       InputFileFromTree(tree, fname);
1807       if (fname.Length()) fInputEventHandler->SetInputFileName(fname);
1808    }
1809
1810    if (fMode == kGridAnalysis) {
1811       fIsRemote = kTRUE;
1812       if (!anaType.Contains("terminate")) {
1813          if (!fGridHandler) {
1814             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1815             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1816             if (cdir) cdir->cd();
1817             return -1;
1818          }
1819          // Write analysis manager in the analysis file
1820          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1821          // run local task configuration
1822          RunLocalInit();
1823          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1824             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1825             if (cdir) cdir->cd();
1826             return -1;
1827          }   
1828
1829          // Terminate grid analysis
1830          if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1831          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1832          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1833          if (!fGridHandler->MergeOutputs()) {
1834             // Return if outputs could not be merged or if it alien handler
1835             // was configured for offline mode or local testing.
1836             if (cdir) cdir->cd();
1837             return 0;
1838          }
1839       }   
1840       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1841       if (cdir) cdir->cd();
1842       ImportWrappers(NULL);
1843       Terminate();
1844       if (cdir) cdir->cd();
1845       return 0;
1846    }
1847    TString line;
1848    SetEventLoop(kFALSE);
1849    // Enable event loop mode if a tree was provided
1850    if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1851
1852    TChain *chain = 0;
1853    TString ttype = "TTree";
1854    if (tree && tree->IsA() == TChain::Class()) {
1855       chain = (TChain*)tree;
1856       if (!chain || !chain->GetListOfFiles()->First()) {
1857          Error("StartAnalysis", "Cannot process null or empty chain...");
1858          if (cdir) cdir->cd();
1859          return -1;
1860       }   
1861       ttype = "TChain";
1862    }   
1863
1864    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1865    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1866    // Initialize locally all tasks (happens for all modes)
1867    TIter next(fTasks);
1868    AliAnalysisTask *task;
1869    RunLocalInit();
1870    
1871    switch (fMode) {
1872       case kLocalAnalysis:
1873          if (!tree && !fGridHandler) {
1874             TIter nextT(fTasks);
1875             // Call CreateOutputObjects for all tasks
1876             Int_t itask = 0;
1877             Bool_t dirStatus = TH1::AddDirectoryStatus();
1878             while ((task=(AliAnalysisTask*)nextT())) {
1879                TH1::AddDirectory(kFALSE);
1880                task->CreateOutputObjects();
1881                if (!task->CheckPostData()) {
1882                   Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1883                         Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1884                         ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1885                }
1886                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1887                gROOT->cd();
1888                itask++;
1889             }   
1890             TH1::AddDirectory(dirStatus);
1891             if (IsExternalLoop()) {
1892                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1893                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1894                return 0;
1895             }
1896             ExecAnalysis();
1897             Terminate();
1898             return 0;
1899          } 
1900          fSelector = new AliAnalysisSelector(this);
1901          // Check if a plugin handler is used
1902          if (fGridHandler) {
1903             // Get the chain from the plugin
1904             TString dataType = "esdTree";
1905             if (fInputEventHandler) {
1906                dataType = fInputEventHandler->GetDataType();
1907                dataType.ToLower();
1908                dataType += "Tree";
1909             }   
1910             chain = fGridHandler->GetChainForTestMode(dataType);
1911             if (!chain) {
1912                Error("StartAnalysis", "No chain for test mode. Aborting.");
1913                return -1;
1914             }
1915             cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1916             retv = chain->Process(fSelector, "", nentries, firstentry);
1917             break;
1918          }
1919          // Run tree-based analysis via AliAnalysisSelector  
1920          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1921          retv = tree->Process(fSelector, "", nentries, firstentry);
1922          break;
1923       case kProofAnalysis:
1924          fIsRemote = kTRUE;
1925          // Check if the plugin is used
1926          if (fGridHandler) {
1927             return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1928          }
1929          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1930             Error("StartAnalysis", "No PROOF!!! Exiting.");
1931             if (cdir) cdir->cd();
1932             return -1;
1933          }   
1934          line = Form("gProof->AddInput((TObject*)%p);", this);
1935          gROOT->ProcessLine(line);
1936          if (chain) {
1937             chain->SetProof();
1938             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1939             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1940          } else {
1941             Error("StartAnalysis", "No chain!!! Exiting.");
1942             if (cdir) cdir->cd();
1943             return -1;
1944          }      
1945          break;
1946       case kGridAnalysis:
1947          fIsRemote = kTRUE;
1948          if (!anaType.Contains("terminate")) {
1949             if (!fGridHandler) {
1950                Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1951                Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1952                if (cdir) cdir->cd();
1953                return -1;
1954             }
1955             // Write analysis manager in the analysis file
1956             cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1957             // Start the analysis via the handler
1958             if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1959                Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1960                if (cdir) cdir->cd();
1961                return -1;
1962             }   
1963
1964             // Terminate grid analysis
1965             if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1966             if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1967             cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1968             if (!fGridHandler->MergeOutputs()) {
1969                // Return if outputs could not be merged or if it alien handler
1970                // was configured for offline mode or local testing.
1971                if (cdir) cdir->cd();
1972                return 0;
1973             }
1974          }   
1975          cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1976          ImportWrappers(NULL);
1977          Terminate();
1978          if (cdir) cdir->cd();
1979          return 0;
1980       case kMixingAnalysis:   
1981          // Run event mixing analysis
1982          if (!fEventPool) {
1983             Error("StartAnalysis", "Cannot run event mixing without event pool");
1984             if (cdir) cdir->cd();
1985             return -1;
1986          }
1987          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1988          fSelector = new AliAnalysisSelector(this);
1989          while ((chain=fEventPool->GetNextChain())) {
1990             next.Reset();
1991             // Call NotifyBinChange for all tasks
1992             while ((task=(AliAnalysisTask*)next()))
1993                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1994             retv = chain->Process(fSelector);
1995             if (retv < 0) {
1996                Error("StartAnalysis", "Mixing analysis failed");
1997                if (cdir) cdir->cd();
1998                return retv;
1999             }   
2000          }
2001          PackOutput(fSelector->GetOutputList());
2002          Terminate();
2003    }
2004    if (cdir) cdir->cd();
2005    return retv;
2006 }   
2007
2008 //______________________________________________________________________________
2009 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
2010 {
2011 // Start analysis for this manager on a given dataset. Analysis task can be: 
2012 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
2013    if (!fInitOK) {
2014       Error("StartAnalysis","Analysis manager was not initialized !");
2015       return -1;
2016    }
2017    fIsRemote = kTRUE;
2018    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
2019    TString anaType = type;
2020    anaType.ToLower();
2021    if (!anaType.Contains("proof")) {
2022       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
2023       return -1;
2024    }   
2025    fMode = kProofAnalysis;
2026    TString line;
2027    TString proofProcessOpt;
2028    SetEventLoop(kTRUE);
2029    // Set the dataset flag
2030    TObject::SetBit(kUseDataSet);
2031    fTree = 0;
2032    if (fGridHandler) {
2033       // Start proof analysis using the grid handler
2034       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
2035          Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
2036          return -1;
2037       }
2038       // Check if the plugin is in test mode
2039       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
2040          dataset = "test_collection";
2041       } else {
2042          dataset = fGridHandler->GetProofDataSet();
2043       }
2044
2045       proofProcessOpt = fGridHandler->GetProofProcessOpt();
2046    }   
2047
2048    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
2049       Error("StartAnalysis", "No PROOF!!! Exiting.");
2050       return -1;
2051    }   
2052
2053    // Initialize locally all tasks
2054    RunLocalInit();
2055       
2056    line = Form("gProof->AddInput((TObject*)%p);", this);
2057    gROOT->ProcessLine(line);
2058    Long_t retv;
2059    line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
2060                dataset,proofProcessOpt.Data(), nentries, firstentry);
2061    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
2062    retv = (Long_t)gROOT->ProcessLine(line);
2063    return retv;
2064 }   
2065
2066 //______________________________________________________________________________
2067 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
2068 {
2069 // Opens according the option the file specified by cont->GetFileName() and changes
2070 // current directory to cont->GetFolderName(). If the file was already opened, it
2071 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
2072 // be optionally ignored.
2073   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2074   TString filename = cont->GetFileName();
2075   TFile *f = NULL;
2076   if (filename.IsNull()) {
2077     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2078     return NULL;
2079   }
2080   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2081       && !ignoreProof)
2082     f = mgr->OpenProofFile(cont,option);
2083   else {
2084     // Check first if the file is already opened
2085     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2086     if (f) {
2087       // Check if option "UPDATE" was preserved 
2088       TString opt(option);
2089       opt.ToUpper();
2090       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
2091         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2092     } else {
2093       f = TFile::Open(filename, option);
2094     }    
2095   }   
2096   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2097     cont->SetFile(f);
2098     // Cd to file
2099     f->cd();
2100     // Check for a folder request
2101     TString dir = cont->GetFolderName(); 
2102     if (!dir.IsNull()) {
2103       if (!f->GetDirectory(dir)) f->mkdir(dir);
2104       f->cd(dir);
2105     }
2106     return f;
2107   }
2108   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2109   cont->SetFile(NULL);
2110   return NULL;
2111 }    
2112  
2113 //______________________________________________________________________________
2114 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
2115 {
2116 // Opens a special output file used in PROOF.
2117   TString line;
2118   TString filename = cont->GetFileName();
2119   if (cont == fCommonOutput) {
2120      if (fOutputEventHandler) {
2121         if (strlen(extaod)) filename = extaod;
2122         filename = fOutputEventHandler->GetOutputFileName();
2123      }   
2124      else Fatal("OpenProofFile","No output container. Exiting.");
2125   }   
2126   TFile *f = NULL;
2127   if (fMode!=kProofAnalysis || !fSelector) {
2128     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2129     return NULL;
2130   } 
2131   if (fSpecialOutputLocation.Length()) {
2132     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2133     if (f) {
2134       // Check if option "UPDATE" was preserved 
2135       TString opt(option);
2136       opt.ToUpper();
2137       if ((opt=="UPDATE") && (opt!=f->GetOption()))
2138         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2139     } else {
2140       f = new TFile(filename, option);
2141     }
2142     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2143       cont->SetFile(f);
2144       // Cd to file
2145       f->cd();
2146       // Check for a folder request
2147       TString dir = cont->GetFolderName(); 
2148       if (dir.Length()) {
2149         if (!f->GetDirectory(dir)) f->mkdir(dir);
2150         f->cd(dir);
2151       }      
2152       return f;
2153     }
2154     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2155     cont->SetFile(NULL);
2156     return NULL;       
2157   }
2158   // Check if there is already a proof output file in the output list
2159   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2160   if (pof) {
2161     // Get the actual file
2162     line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
2163     filename = (const char*)gROOT->ProcessLine(line);
2164     if (fDebug>1) {
2165       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2166     }  
2167     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2168     if (!f) {
2169        Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2170        return NULL;
2171     }   
2172     // Check if option "UPDATE" was preserved 
2173     TString opt(option);
2174     opt.ToUpper();
2175     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
2176       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2177   } else {
2178     if (cont->IsRegisterDataset()) {
2179       TString dsetName = filename;
2180       dsetName.ReplaceAll(".root", cont->GetTitle());
2181       dsetName.ReplaceAll(":","_");
2182       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2183       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
2184     } else {
2185       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2186       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2187     }
2188     if (fDebug > 1) printf("=== %s\n", line.Data());
2189     gROOT->ProcessLine(line);
2190     line = Form("pf->OpenFile(\"%s\");", option);
2191     gROOT->ProcessLine(line);
2192     f = gFile;
2193     if (fDebug > 1) {
2194       gROOT->ProcessLine("pf->Print()");
2195       printf(" == proof file name: %s", f->GetName());
2196     }   
2197     // Add to proof output list
2198     line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
2199     if (fDebug > 1) printf("=== %s\n", line.Data());
2200     gROOT->ProcessLine(line);
2201   }
2202   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2203     cont->SetFile(f);
2204     // Cd to file
2205     f->cd();
2206     // Check for a folder request
2207     TString dir = cont->GetFolderName(); 
2208     if (!dir.IsNull()) {
2209       if (!f->GetDirectory(dir)) f->mkdir(dir);
2210       f->cd(dir);
2211     }
2212     return f;
2213   }
2214   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2215   cont->SetFile(NULL);  
2216   return NULL;
2217 }   
2218
2219 //______________________________________________________________________________
2220 void AliAnalysisManager::ExecAnalysis(Option_t *option)
2221 {
2222 // Execute analysis.
2223    static Long64_t nentries = 0;
2224    static TTree *lastTree = 0;
2225    static TStopwatch *timer = new TStopwatch();
2226    // Only the first call to Process will trigger a true Notify. Other Notify
2227    // coming before is ignored.
2228    if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2229       TObject::SetBit(AliAnalysisManager::kTrueNotify);
2230       Notify();
2231    }   
2232    if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2233    else {
2234       if (fTree && (fTree != lastTree)) {
2235          nentries += fTree->GetEntries();
2236          lastTree = fTree;
2237       }   
2238       if (!fNcalls) timer->Start();
2239       if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2240    }
2241    fIOTimer->Start(kTRUE);
2242    gROOT->cd();
2243    TDirectory *cdir = gDirectory;
2244    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2245    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2246    if (!fInitOK) {
2247       Error("ExecAnalysis", "Analysis manager was not initialized !");
2248       if (cdir) cdir->cd();
2249       return;
2250    }
2251    fNcalls++;
2252    AliAnalysisTask *task;
2253    // Check if the top tree is active.
2254    if (fTree) {
2255       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2256          AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2257       TIter next(fTasks);
2258    // De-activate all tasks
2259       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2260       AliAnalysisDataContainer *cont = fCommonInput;
2261       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2262       if (!cont) {
2263               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2264          if (cdir) cdir->cd();
2265          return;
2266       }   
2267       cont->SetData(fTree); // This will notify all consumers
2268       Long64_t entry = fTree->GetTree()->GetReadEntry();      
2269 //
2270 //    Call BeginEvent() for optional input/output and MC services 
2271       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
2272       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
2273       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2274       gROOT->cd();
2275       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2276          AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2277 //
2278 //    Execute the tasks
2279 //      TIter next1(cont->GetConsumers());
2280       fIOTimer->Stop();
2281       fIOTime += fIOTimer->RealTime();
2282       fCPUTimer->Start(kTRUE);
2283       TIter next1(fTopTasks);
2284       Int_t itask = 0;
2285       while ((task=(AliAnalysisTask*)next1())) {
2286          if (fDebug >1) {
2287             cout << "    Executing task " << task->GetName() << endl;
2288          }
2289          if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2290          task->ExecuteTask(option);
2291          if (fStatistics) fStatistics->StopTimer();
2292          gROOT->cd();
2293          if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2294             AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2295          itask++;   
2296       }
2297       fCPUTimer->Stop();
2298       fCPUTime += fCPUTimer->RealTime();
2299       fIOTimer->Start(kTRUE);
2300 //
2301 //    Call FinishEvent() for optional output and MC services 
2302       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2303       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2304       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2305       // Gather system information if requested
2306       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2307          AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2308       if (cdir) cdir->cd();   
2309       fIOTimer->Stop();
2310       fIOTime += fIOTimer->RealTime();
2311       return;
2312    }   
2313    // The event loop is not controlled by TSelector   
2314 //
2315 //  Call BeginEvent() for optional input/output and MC services 
2316    fIOTimer->Start(kTRUE);
2317    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
2318    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
2319    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2320    fIOTimer->Stop();
2321    fIOTime += fIOTimer->RealTime();
2322    gROOT->cd();
2323    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2324       AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2325    fCPUTimer->Start(kTRUE);
2326    TIter next2(fTopTasks);
2327    while ((task=(AliAnalysisTask*)next2())) {
2328       task->SetActive(kTRUE);
2329       if (fDebug > 1) {
2330          cout << "    Executing task " << task->GetName() << endl;
2331       }   
2332       if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2333       task->ExecuteTask(option);
2334       if (fStatistics) fStatistics->StopTimer();
2335       gROOT->cd();
2336    }   
2337    fCPUTimer->Stop();
2338    fCPUTime += fCPUTimer->RealTime();
2339 //
2340 // Call FinishEvent() for optional output and MC services 
2341    fIOTimer->Start(kTRUE);
2342    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2343    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2344    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2345    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2346       AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2347    if (cdir) cdir->cd();   
2348    fIOTimer->Stop();
2349    fIOTime += fIOTimer->RealTime();
2350 }
2351
2352 //______________________________________________________________________________
2353 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2354 {
2355 // Check if the stdout is connected to a pipe (C.Holm)
2356   Bool_t ispipe = kFALSE;
2357   out.seekp(0, std::ios_base::cur);
2358   if (out.fail()) {
2359     out.clear();
2360     if (errno == ESPIPE) ispipe = kTRUE;
2361   }
2362   return ispipe;
2363 }
2364    
2365 //______________________________________________________________________________
2366 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2367 {
2368 // Set the input event handler and create a container for it.
2369    Changed();
2370    fInputEventHandler   = handler;
2371    if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2372 }
2373
2374 //______________________________________________________________________________
2375 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2376 {
2377 // Set the input event handler and create a container for it.
2378    Changed();
2379    fOutputEventHandler   = handler;
2380    if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2381    fCommonOutput->SetSpecialOutput();
2382 }
2383
2384 //______________________________________________________________________________
2385 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2386 {
2387 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2388    if (TObject::TestBit(kUseProgressBar)) {
2389       Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2390       return;
2391    }
2392    fDebug = level;
2393 }
2394    
2395 //______________________________________________________________________________
2396 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2397 {
2398 // Enable a text mode progress bar. Resets debug level to 0.
2399    Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n  ### NOTE: Debug level reset to 0 ###", freq);
2400    TObject::SetBit(kUseProgressBar,flag);
2401    fPBUpdateFreq = freq;
2402    fDebug = 0;
2403 }   
2404
2405 //______________________________________________________________________________
2406 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2407 {
2408 // This method is used externally to register output files which are not
2409 // connected to any output container, so that the manager can properly register,
2410 // retrieve or merge them when running in distributed mode. The file names are
2411 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2412    if (fExtraFiles.Contains(fname)) return;
2413    if (fExtraFiles.Length()) fExtraFiles += " ";
2414    fExtraFiles += fname;
2415 }
2416
2417 //______________________________________________________________________________
2418 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2419 {
2420 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2421    char fullPath[512];
2422    char chUrl[512];
2423    char tmp[1024];
2424    TObject *pof =  source->FindObject(filename);
2425    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2426       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2427       return kFALSE;
2428    }
2429    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2430    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2431    TString clientUrl(chUrl);
2432    TString fullPath_str(fullPath);
2433    if (clientUrl.Contains("localhost")){
2434       TObjArray* array = fullPath_str.Tokenize ( "//" );
2435       TObjString *strobj = ( TObjString *)array->At(1);
2436       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2437       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2438       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2439       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2440       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2441       delete arrayPort;
2442       delete array;
2443    }
2444    else if (clientUrl.Contains("__lite__")) { 
2445      // Special case for ProofLite environement - get file info and copy. 
2446      gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2447      fullPath_str = Form("%s/%s", tmp, fullPath);
2448    }
2449    if (fDebug > 1) 
2450      Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2451    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
2452    if (!gotit)
2453       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2454    return gotit;
2455 }
2456
2457 //______________________________________________________________________________
2458 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2459 {
2460 // Fill analysis type in the provided string.
2461    switch (fMode) {
2462       case kLocalAnalysis:
2463          type = "local";
2464          return;
2465       case kProofAnalysis:
2466          type = "proof";
2467          return;
2468       case kGridAnalysis:
2469          type = "grid";
2470          return;
2471       case kMixingAnalysis:
2472          type = "mix";
2473    }
2474 }
2475
2476 //______________________________________________________________________________
2477 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2478 {
2479 // Validate all output files.
2480    TIter next(fOutputs);
2481    AliAnalysisDataContainer *output;
2482    TDirectory *cdir = gDirectory;
2483    TString openedFiles;
2484    while ((output=(AliAnalysisDataContainer*)next())) {
2485       if (output->IsRegisterDataset()) continue;
2486       TString filename = output->GetFileName();
2487       if (filename == "default") {
2488          if (!fOutputEventHandler) continue;
2489          filename = fOutputEventHandler->GetOutputFileName();
2490          // Main AOD may not be there
2491          if (gSystem->AccessPathName(filename)) continue;
2492       }
2493       // Check if the file is closed
2494       if (openedFiles.Contains(filename)) continue;;
2495       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2496       if (file) {
2497          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2498          // Clear file list to release object ownership to user.
2499 //         file->Clear();
2500          file->Close();
2501       }
2502       file = TFile::Open(filename);
2503       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2504          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2505          if (cdir) cdir->cd();
2506          return kFALSE;
2507       }
2508       file->Close();
2509       openedFiles += filename;
2510       openedFiles += " ";
2511    }
2512    if (cdir) cdir->cd();
2513    return kTRUE;
2514 }   
2515
2516 //______________________________________________________________________________
2517 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2518 {
2519 // Implements a nice text mode progress bar.
2520    static Long64_t icount = 0;
2521    static TString oname;
2522    static TString nname;
2523    static Long64_t ocurrent = 0;
2524    static Long64_t osize = 0;
2525    static Int_t oseconds = 0;
2526    static TStopwatch *owatch = 0;
2527    static Bool_t oneoftwo = kFALSE;
2528    static Int_t nrefresh = 0;
2529    static Int_t nchecks = 0;
2530    static char lastChar = 0;
2531    const char symbol[4] = {'-','\\','|','/'}; 
2532    
2533    if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2534    if (!refresh) {
2535       nrefresh = 0;
2536       if (!size) return;
2537       owatch = watch;
2538       oname = opname;
2539       ocurrent = TMath::Abs(current);
2540       osize = TMath::Abs(size);
2541       if (ocurrent > osize) ocurrent=osize;
2542    } else {
2543       nrefresh++;
2544       if (!osize) return;
2545    }     
2546    if ((current % fPBUpdateFreq) != 0) return;
2547    icount++;
2548    char progress[11] = "          ";
2549    Int_t ichar = icount%4;
2550    Double_t time = 0.;
2551    Int_t hours = 0;
2552    Int_t minutes = 0;
2553    Int_t seconds = 0;
2554    if (owatch && !last) {
2555       owatch->Stop();
2556       time = owatch->RealTime();
2557       seconds   = int(time) % 60;
2558       minutes   = (int(time) / 60) % 60;
2559       hours     = (int(time) / 60 / 60);
2560       if (refresh)  {
2561          if (oseconds==seconds) {
2562             owatch->Continue();
2563             return;
2564          }
2565          oneoftwo = !oneoftwo;   
2566       }
2567       oseconds = seconds;   
2568    }
2569    if (refresh && oneoftwo) {
2570       nname = oname;
2571       if (nchecks <= 0) nchecks = nrefresh+1;
2572       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2573       oname = Form("     == %d%% ==", pctdone);
2574    }         
2575    Double_t percent = 100.0*ocurrent/osize;
2576    Int_t nchar = Int_t(percent/10);
2577    if (nchar>10) nchar=10;
2578    Int_t i;
2579    for (i=0; i<nchar; i++)  progress[i] = '=';
2580    progress[nchar] = symbol[ichar];
2581    for (i=nchar+1; i<10; i++) progress[i] = ' ';
2582    progress[10] = '\0';
2583    oname += "                    ";
2584    oname.Remove(20);
2585    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2586    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2587    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2588    if (time>0.) {
2589      Int_t full   = Int_t(ocurrent > 0 ? 
2590                           time * (float(osize)/ocurrent) + .5 : 
2591                           99*3600+59*60+59); 
2592      Int_t remain = Int_t(full - time);
2593      Int_t rsec   = remain % 60;
2594      Int_t rmin   = (remain / 60) % 60;
2595      Int_t rhour  = (remain / 60 / 60);
2596      fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d  ETA %.2d:%.2d:%.2d%c",
2597              percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2598    }
2599    else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2600    if (refresh && oneoftwo) oname = nname;
2601    if (owatch) owatch->Continue();
2602    if (last) {
2603       icount = 0;
2604       owatch = 0;
2605       ocurrent = 0;
2606       osize = 0;
2607       oseconds = 0;
2608       oneoftwo = kFALSE;
2609       nrefresh = 0;
2610       fprintf(stderr, "\n");
2611    }   
2612 }
2613
2614 //______________________________________________________________________________
2615 void AliAnalysisManager::DoLoadBranch(const char *name) 
2616 {
2617   // Get tree and load branch if needed.
2618   static Long64_t crtEntry = -100;
2619
2620   if (fAutoBranchHandling || !fTree)
2621     return;
2622
2623   TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2624   if (!br) {
2625     br = fTree->GetBranch(name);
2626     if (!br) {
2627       Error("DoLoadBranch", "Could not find branch %s",name);
2628       return;
2629     }
2630     fTable.Add(br);
2631   }
2632   if (br->GetReadEntry()==fCurrentEntry) return;
2633   Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2634   if (readbytes<0) {
2635     Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2636     if (crtEntry != fCurrentEntry) {
2637       CountEvent(1,0,1,0);
2638       crtEntry = fCurrentEntry;
2639     }  
2640   } else {
2641     if (crtEntry != fCurrentEntry) {
2642       CountEvent(1,1,0,0);
2643       crtEntry = fCurrentEntry;
2644     }
2645   }
2646 }
2647
2648 //______________________________________________________________________________
2649 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2650 {
2651 // Add the statistics task to the manager.
2652   if (fStatistics) {
2653      Info("AddStatisticsTask", "Already added");
2654      return;
2655   }
2656   TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2657   gROOT->ProcessLine(line);
2658 }  
2659
2660 //______________________________________________________________________________
2661 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2662 {
2663 // Bookkeep current event;
2664    if (!fStatistics) return;
2665    fStatistics->AddInput(ninput);
2666    fStatistics->AddProcessed(nprocessed);
2667    fStatistics->AddFailed(nfailed);
2668    fStatistics->AddAccepted(naccepted);
2669 }   
2670
2671 //______________________________________________________________________________
2672 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2673 {
2674 // Add a line in the statistics message. If available, the statistics message is written
2675 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2676 // on the client.
2677    if (!strlen(line)) return;
2678    if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2679    fStatisticsMsg += line;
2680 }
2681
2682 //______________________________________________________________________________
2683 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2684 {
2685 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2686    static Bool_t done = kFALSE;
2687    if (done) return;
2688    done = kTRUE;
2689    if (!fStatistics) return;
2690    ofstream out;
2691    AddStatisticsMsg(Form("Number of input events:        %lld",fStatistics->GetNinput()));
2692    AddStatisticsMsg(Form("Number of processed events:    %lld",fStatistics->GetNprocessed()));      
2693    AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2694    AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2695    out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2696                  fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2697                  fStatistics->GetNaccepted()), ios::out);      
2698    out << fStatisticsMsg << endl;
2699    out.close();
2700 }
2701
2702 //______________________________________________________________________________
2703 const char* AliAnalysisManager::GetOADBPath()
2704 {
2705 // returns the path of the OADB
2706 // this static function just depends on environment variables
2707
2708    static TString oadbPath;
2709
2710    if (gSystem->Getenv("OADB_PATH"))
2711       oadbPath = gSystem->Getenv("OADB_PATH");
2712    else if (gSystem->Getenv("ALICE_ROOT"))
2713       oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2714    else
2715       ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2716       
2717    return oadbPath;
2718 }
2719
2720 //______________________________________________________________________________
2721 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2722 {
2723 // Define a custom string variable mapped to a global unique name. The variable
2724 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2725    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2726    if (!mgr) {
2727       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2728       return;
2729    }   
2730    Bool_t valid = kFALSE;
2731    TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2732    if (valid) {
2733       ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2734       return;
2735    }
2736    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2737 }
2738
2739 //______________________________________________________________________________
2740 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2741 {
2742 // Static method to retrieve a global variable defined via SetGlobalStr.
2743    valid = kFALSE;
2744    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2745    if (!mgr) return 0;
2746    TObject *value = mgr->GetGlobals()->GetValue(key);
2747    if (!value) return 0;
2748    valid = kTRUE;
2749    return value->GetName();
2750 }
2751
2752 //______________________________________________________________________________
2753 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2754 {
2755 // Define a custom integer variable mapped to a global unique name. The variable
2756 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2757    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2758    if (!mgr) {
2759       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2760       return;
2761    }   
2762    Bool_t valid = kFALSE;
2763    Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2764    if (valid) {
2765       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2766       return;
2767    }
2768    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2769 }
2770
2771 //______________________________________________________________________________
2772 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2773 {
2774 // Static method to retrieve a global variable defined via SetGlobalInt.
2775    valid = kFALSE;
2776    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2777    if (!mgr) return 0;
2778    TObject *value = mgr->GetGlobals()->GetValue(key);
2779    if (!value) return 0;
2780    valid = kTRUE;
2781    TString s = value->GetName();
2782    return s.Atoi();
2783 }
2784
2785 //______________________________________________________________________________
2786 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2787 {
2788 // Define a custom double precision variable mapped to a global unique name. The variable
2789 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2790    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2791    if (!mgr) {
2792       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2793       return;
2794    }   
2795    Bool_t valid = kFALSE;
2796    Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2797    if (valid) {
2798       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2799       return;
2800    }
2801    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2802 }
2803
2804 //______________________________________________________________________________
2805 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2806 {
2807 // Static method to retrieve a global variable defined via SetGlobalDbl.
2808    valid = kFALSE;
2809    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2810    if (!mgr) return 0;
2811    TObject *value = mgr->GetGlobals()->GetValue(key);
2812    if (!value) return 0;
2813    valid = kTRUE;
2814    TString s = value->GetName();
2815    return s.Atof();
2816 }
2817
2818 //______________________________________________________________________________
2819 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2820 {
2821 // Sets Class debug level
2822
2823    if (!fDebugOptions) {
2824       fDebugOptions = new TObjArray();
2825       fDebugOptions->SetOwner(kTRUE);
2826    }
2827
2828    TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2829    if (!debugOpt) {
2830      AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel,className).Data());
2831      fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2832    } else {
2833       TString oldDebugStr = debugOpt->GetTitle();
2834       Int_t oldDebug = oldDebugStr.Atoi();
2835       if (debugLevel > oldDebug) {
2836          AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel,className,oldDebug).Data());
2837          debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2838       } else {
2839          AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel,className,oldDebug).Data());
2840       }
2841    }
2842 }
2843
2844 //______________________________________________________________________________
2845 void AliAnalysisManager::ApplyDebugOptions()
2846 {
2847 // Apply debug options
2848
2849    if (!fDebugOptions) return;
2850    
2851    TIter next(fDebugOptions);
2852    TNamed *debug;
2853    TString debugLevel;
2854    while ((debug=dynamic_cast<TNamed*>(next()))) {
2855       debugLevel = debug->GetTitle();
2856       AliInfo(TString::Format("Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()).Data());
2857       AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2858    }
2859 }
2860
2861 //______________________________________________________________________________
2862 Bool_t AliAnalysisManager::IsMacroLoaded(const char * filename)
2863 {
2864 // Check if a macro was loaded.
2865    return fgMacroNames.Contains(filename);
2866 }
2867    
2868 //______________________________________________________________________________
2869 Int_t AliAnalysisManager::LoadMacro(const char *filename, Int_t *error, Bool_t check)
2870 {
2871 // Redirection of gROOT->LoadMacro which makes sure the same macro is not loaded 
2872 // twice
2873    TString macroName = gSystem->BaseName(filename);
2874    // Strip appended +, ++, +g, +O
2875    Int_t index = macroName.Index("+");
2876    if (index>0) macroName.Remove(index);
2877    if (fgMacroNames.Contains(macroName)) {
2878       // Macro with the same name loaded already in this root session, do 
2879       // nothing
2880       error = 0;
2881       return 0;
2882    }
2883    Int_t ret = gROOT->LoadMacro(filename,error,check);
2884    // In case of error return the error code
2885    if (ret) return ret;
2886    // Append the macro name to the loaded macros list
2887    fgMacroNames += macroName;
2888    fgMacroNames += " ";
2889    return ret;
2890 }   
2891
2892 //______________________________________________________________________________
2893 void AliAnalysisManager::Lock()
2894 {
2895 // Security lock. This is to detect NORMAL user errors and not really to
2896 // protect against intentional hacks.
2897    if (fLocked) return;
2898    fLocked = kTRUE;
2899    if (fInputEventHandler)  fInputEventHandler->Lock();
2900    if (fOutputEventHandler) fOutputEventHandler->Lock();
2901    if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2902    Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2903 }
2904
2905 //______________________________________________________________________________
2906 void AliAnalysisManager::UnLock()
2907 {
2908 // Verbose unlocking. Hackers will be punished ;-) ... 
2909    if (!fLocked) return;
2910    fLocked = kFALSE;
2911    if (fInputEventHandler)  fInputEventHandler->UnLock();
2912    if (fOutputEventHandler) fOutputEventHandler->UnLock();
2913    if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2914    Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2915 }
2916
2917 //______________________________________________________________________________
2918 void AliAnalysisManager::Changed()
2919 {
2920 // All critical setters pass through the Changed method that throws an exception 
2921 // in case the lock was set.
2922    if (fLocked) Fatal("Changed","Critical setter called in locked mode");
2923 }