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