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