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