]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Avoid doing multiple copies of the same file in AliEn if migration was requested...
[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 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1517 {
1518 // Start analysis having a grid handler.
1519    if (!fGridHandler) {
1520       Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1521       Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1522       return -1;
1523    }
1524    TTree *tree = NULL;
1525    return StartAnalysis(type, tree, nentries, firstentry);
1526 }
1527
1528 //______________________________________________________________________________
1529 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1530 {
1531 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1532 // MIX. Process nentries starting from firstentry
1533    Long64_t retv = 0;
1534    // Backup current directory and make sure gDirectory points to gROOT
1535    TDirectory *cdir = gDirectory;
1536    gROOT->cd();
1537    if (!fInitOK) {
1538       Error("StartAnalysis","Analysis manager was not initialized !");
1539       cdir->cd();
1540       return -1;
1541    }
1542    if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1543    if (fDebug > 1) {
1544       printf("StartAnalysis %s\n",GetName());
1545       AliLog::SetGlobalLogLevel(AliLog::kInfo);
1546    }   
1547    fMaxEntries = nentries;
1548    fIsRemote = kFALSE;
1549    TString anaType = type;
1550    anaType.ToLower();
1551    fMode = kLocalAnalysis;
1552    Bool_t runlocalinit = kTRUE;
1553    if (anaType.Contains("file")) {
1554       runlocalinit = kFALSE;
1555       fIsRemote = kTRUE;
1556    }   
1557    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1558    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1559    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1560
1561    if (fMode == kGridAnalysis) {
1562       fIsRemote = kTRUE;
1563       if (!anaType.Contains("terminate")) {
1564          if (!fGridHandler) {
1565             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1566             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1567             cdir->cd();
1568             return -1;
1569          }
1570          // Write analysis manager in the analysis file
1571          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1572          // run local task configuration
1573          TIter nextTask(fTasks);
1574          AliAnalysisTask *task;
1575          while ((task=(AliAnalysisTask*)nextTask())) {
1576             task->LocalInit();
1577             gROOT->cd();
1578          }
1579          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1580             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1581             cdir->cd();
1582             return -1;
1583          }   
1584
1585          // Terminate grid analysis
1586          if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1587          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1588          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1589          if (!fGridHandler->MergeOutputs()) {
1590             // Return if outputs could not be merged or if it alien handler
1591             // was configured for offline mode or local testing.
1592             cdir->cd();
1593             return 0;
1594          }
1595       }   
1596       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1597       ImportWrappers(NULL);
1598       Terminate();
1599       cdir->cd();
1600       return 0;
1601    }
1602    TString line;
1603    SetEventLoop(kFALSE);
1604    // Enable event loop mode if a tree was provided
1605    if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1606
1607    TChain *chain = 0;
1608    TString ttype = "TTree";
1609    if (tree && tree->IsA() == TChain::Class()) {
1610       chain = (TChain*)tree;
1611       if (!chain || !chain->GetListOfFiles()->First()) {
1612          Error("StartAnalysis", "Cannot process null or empty chain...");
1613          cdir->cd();
1614          return -1;
1615       }   
1616       ttype = "TChain";
1617    }   
1618
1619    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1620    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1621    // Initialize locally all tasks (happens for all modes)
1622    TIter next(fTasks);
1623    AliAnalysisTask *task;
1624    if (runlocalinit) {
1625       while ((task=(AliAnalysisTask*)next())) {
1626          task->LocalInit();
1627          gROOT->cd();
1628       }
1629       if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1630    }   
1631    
1632    switch (fMode) {
1633       case kLocalAnalysis:
1634          if (!tree && !fGridHandler) {
1635             TIter nextT(fTasks);
1636             // Call CreateOutputObjects for all tasks
1637             Int_t itask = 0;
1638             Bool_t dirStatus = TH1::AddDirectoryStatus();
1639             while ((task=(AliAnalysisTask*)nextT())) {
1640                TH1::AddDirectory(kFALSE);
1641                task->CreateOutputObjects();
1642                if (!task->CheckPostData()) {
1643                   Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1644                         Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1645                         ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1646                }
1647                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1648                gROOT->cd();
1649                itask++;
1650             }   
1651             TH1::AddDirectory(dirStatus);
1652             if (IsExternalLoop()) {
1653                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1654                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1655                return 0;
1656             }
1657             ExecAnalysis();
1658             Terminate();
1659             return 0;
1660          } 
1661          fSelector = new AliAnalysisSelector(this);
1662          // Check if a plugin handler is used
1663          if (fGridHandler) {
1664             // Get the chain from the plugin
1665             TString dataType = "esdTree";
1666             if (fInputEventHandler) {
1667                dataType = fInputEventHandler->GetDataType();
1668                dataType.ToLower();
1669                dataType += "Tree";
1670             }   
1671             chain = fGridHandler->GetChainForTestMode(dataType);
1672             if (!chain) {
1673                Error("StartAnalysis", "No chain for test mode. Aborting.");
1674                return -1;
1675             }
1676             cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1677             retv = chain->Process(fSelector, "", nentries, firstentry);
1678             break;
1679          }
1680          // Run tree-based analysis via AliAnalysisSelector  
1681          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1682          retv = tree->Process(fSelector, "", nentries, firstentry);
1683          break;
1684       case kProofAnalysis:
1685          fIsRemote = kTRUE;
1686          // Check if the plugin is used
1687          if (fGridHandler) {
1688             return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1689          }
1690          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1691             Error("StartAnalysis", "No PROOF!!! Exiting.");
1692             cdir->cd();
1693             return -1;
1694          }   
1695          line = Form("gProof->AddInput((TObject*)%p);", this);
1696          gROOT->ProcessLine(line);
1697          if (chain) {
1698             chain->SetProof();
1699             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1700             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1701          } else {
1702             Error("StartAnalysis", "No chain!!! Exiting.");
1703             cdir->cd();
1704             return -1;
1705          }      
1706          break;
1707       case kGridAnalysis:
1708          fIsRemote = kTRUE;
1709          if (!anaType.Contains("terminate")) {
1710             if (!fGridHandler) {
1711                Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1712                Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1713                cdir->cd();
1714                return -1;
1715             }
1716             // Write analysis manager in the analysis file
1717             cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1718             // Start the analysis via the handler
1719             if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1720                Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1721                cdir->cd();
1722                return -1;
1723             }   
1724
1725             // Terminate grid analysis
1726             if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1727             if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1728             cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1729             if (!fGridHandler->MergeOutputs()) {
1730                // Return if outputs could not be merged or if it alien handler
1731                // was configured for offline mode or local testing.
1732                cdir->cd();
1733                return 0;
1734             }
1735          }   
1736          cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1737          ImportWrappers(NULL);
1738          Terminate();
1739          cdir->cd();
1740          return 0;
1741       case kMixingAnalysis:   
1742          // Run event mixing analysis
1743          if (!fEventPool) {
1744             Error("StartAnalysis", "Cannot run event mixing without event pool");
1745             cdir->cd();
1746             return -1;
1747          }
1748          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1749          fSelector = new AliAnalysisSelector(this);
1750          while ((chain=fEventPool->GetNextChain())) {
1751             next.Reset();
1752             // Call NotifyBinChange for all tasks
1753             while ((task=(AliAnalysisTask*)next()))
1754                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1755             retv = chain->Process(fSelector);
1756             if (retv < 0) {
1757                Error("StartAnalysis", "Mixing analysis failed");
1758                cdir->cd();
1759                return retv;
1760             }   
1761          }
1762          PackOutput(fSelector->GetOutputList());
1763          Terminate();
1764    }
1765    cdir->cd();
1766    return retv;
1767 }   
1768
1769 //______________________________________________________________________________
1770 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1771 {
1772 // Start analysis for this manager on a given dataset. Analysis task can be: 
1773 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1774    if (!fInitOK) {
1775       Error("StartAnalysis","Analysis manager was not initialized !");
1776       return -1;
1777    }
1778    fIsRemote = kTRUE;
1779    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1780    TString anaType = type;
1781    anaType.ToLower();
1782    if (!anaType.Contains("proof")) {
1783       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1784       return -1;
1785    }   
1786    fMode = kProofAnalysis;
1787    TString line;
1788    SetEventLoop(kTRUE);
1789    // Set the dataset flag
1790    TObject::SetBit(kUseDataSet);
1791    fTree = 0;
1792    if (fGridHandler) {
1793       // Start proof analysis using the grid handler
1794       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1795          Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1796          return -1;
1797       }
1798       // Check if the plugin is in test mode
1799       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1800          dataset = "test_collection";
1801       } else {
1802          dataset = fGridHandler->GetProofDataSet();
1803       }
1804    }   
1805
1806    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1807       Error("StartAnalysis", "No PROOF!!! Exiting.");
1808       return -1;
1809    }   
1810
1811    // Initialize locally all tasks
1812    TIter next(fTasks);
1813    AliAnalysisTask *task;
1814    while ((task=(AliAnalysisTask*)next())) {
1815       task->LocalInit();
1816    }
1817    
1818    line = Form("gProof->AddInput((TObject*)%p);", this);
1819    gROOT->ProcessLine(line);
1820    Long_t retv;
1821    line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1822                dataset, nentries, firstentry);
1823    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1824    retv = (Long_t)gROOT->ProcessLine(line);
1825    return retv;
1826 }   
1827
1828 //______________________________________________________________________________
1829 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1830 {
1831 // Opens according the option the file specified by cont->GetFileName() and changes
1832 // current directory to cont->GetFolderName(). If the file was already opened, it
1833 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1834 // be optionally ignored.
1835   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1836   TString filename = cont->GetFileName();
1837   TFile *f = NULL;
1838   if (filename.IsNull()) {
1839     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1840     return NULL;
1841   }
1842   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1843       && !ignoreProof)
1844     f = mgr->OpenProofFile(cont,option);
1845   else {
1846     // Check first if the file is already opened
1847     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1848     if (f) {
1849       // Check if option "UPDATE" was preserved 
1850       TString opt(option);
1851       opt.ToUpper();
1852       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1853         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1854     } else {
1855       f = TFile::Open(filename, option);
1856     }    
1857   }   
1858   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1859     cont->SetFile(f);
1860     // Cd to file
1861     f->cd();
1862     // Check for a folder request
1863     TString dir = cont->GetFolderName(); 
1864     if (!dir.IsNull()) {
1865       if (!f->GetDirectory(dir)) f->mkdir(dir);
1866       f->cd(dir);
1867     }
1868     return f;
1869   }
1870   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1871   cont->SetFile(NULL);
1872   return NULL;
1873 }    
1874  
1875 //______________________________________________________________________________
1876 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1877 {
1878 // Opens a special output file used in PROOF.
1879   TString line;
1880   TString filename = cont->GetFileName();
1881   if (cont == fCommonOutput) {
1882      if (fOutputEventHandler) {
1883         if (strlen(extaod)) filename = extaod;
1884         filename = fOutputEventHandler->GetOutputFileName();
1885      }   
1886      else Fatal("OpenProofFile","No output container. Exiting.");
1887   }   
1888   TFile *f = NULL;
1889   if (fMode!=kProofAnalysis || !fSelector) {
1890     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1891     return NULL;
1892   } 
1893   if (fSpecialOutputLocation.Length()) {
1894     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1895     if (f) {
1896       // Check if option "UPDATE" was preserved 
1897       TString opt(option);
1898       opt.ToUpper();
1899       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1900         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1901     } else {
1902       f = new TFile(filename, option);
1903     }
1904     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1905       cont->SetFile(f);
1906       // Cd to file
1907       f->cd();
1908       // Check for a folder request
1909       TString dir = cont->GetFolderName(); 
1910       if (dir.Length()) {
1911         if (!f->GetDirectory(dir)) f->mkdir(dir);
1912         f->cd(dir);
1913       }      
1914       return f;
1915     }
1916     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1917     cont->SetFile(NULL);
1918     return NULL;       
1919   }
1920   // Check if there is already a proof output file in the output list
1921   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1922   if (pof) {
1923     // Get the actual file
1924     line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
1925     filename = (const char*)gROOT->ProcessLine(line);
1926     if (fDebug>1) {
1927       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1928     }  
1929     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1930     if (!f) {
1931        Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1932        return NULL;
1933     }   
1934     // Check if option "UPDATE" was preserved 
1935     TString opt(option);
1936     opt.ToUpper();
1937     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1938       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1939   } else {
1940     if (cont->IsRegisterDataset()) {
1941       TString dsetName = filename;
1942       dsetName.ReplaceAll(".root", cont->GetTitle());
1943       dsetName.ReplaceAll(":","_");
1944       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1945       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1946     } else {
1947       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1948       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1949     }
1950     if (fDebug > 1) printf("=== %s\n", line.Data());
1951     gROOT->ProcessLine(line);
1952     line = Form("pf->OpenFile(\"%s\");", option);
1953     gROOT->ProcessLine(line);
1954     f = gFile;
1955     if (fDebug > 1) {
1956       gROOT->ProcessLine("pf->Print()");
1957       printf(" == proof file name: %s", f->GetName());
1958     }   
1959     // Add to proof output list
1960     line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
1961     if (fDebug > 1) printf("=== %s\n", line.Data());
1962     gROOT->ProcessLine(line);
1963   }
1964   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1965     cont->SetFile(f);
1966     // Cd to file
1967     f->cd();
1968     // Check for a folder request
1969     TString dir = cont->GetFolderName(); 
1970     if (!dir.IsNull()) {
1971       if (!f->GetDirectory(dir)) f->mkdir(dir);
1972       f->cd(dir);
1973     }
1974     return f;
1975   }
1976   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1977   cont->SetFile(NULL);  
1978   return NULL;
1979 }   
1980
1981 //______________________________________________________________________________
1982 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1983 {
1984 // Execute analysis.
1985    static Long64_t nentries = 0;
1986    static TTree *lastTree = 0;
1987    static TStopwatch *timer = new TStopwatch();
1988    // Only the first call to Process will trigger a true Notify. Other Notify
1989    // coming before is ignored.
1990    if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
1991       TObject::SetBit(AliAnalysisManager::kTrueNotify);
1992       Notify();
1993    }   
1994    if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
1995    else {
1996       if (fTree && (fTree != lastTree)) {
1997          nentries += fTree->GetEntries();
1998          lastTree = fTree;
1999       }   
2000       if (!fNcalls) timer->Start();
2001       if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2002    }
2003    gROOT->cd();
2004    TDirectory *cdir = gDirectory;
2005    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2006    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2007    if (!fInitOK) {
2008       Error("ExecAnalysis", "Analysis manager was not initialized !");
2009       cdir->cd();
2010       return;
2011    }
2012    fNcalls++;
2013    AliAnalysisTask *task;
2014    // Check if the top tree is active.
2015    if (fTree) {
2016       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2017          AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2018       TIter next(fTasks);
2019    // De-activate all tasks
2020       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2021       AliAnalysisDataContainer *cont = fCommonInput;
2022       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2023       if (!cont) {
2024               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2025          cdir->cd();
2026          return;
2027       }   
2028       cont->SetData(fTree); // This will notify all consumers
2029       Long64_t entry = fTree->GetTree()->GetReadEntry();      
2030 //
2031 //    Call BeginEvent() for optional input/output and MC services 
2032       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
2033       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
2034       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2035       gROOT->cd();
2036       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2037          AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2038 //
2039 //    Execute the tasks
2040 //      TIter next1(cont->GetConsumers());
2041       TIter next1(fTopTasks);
2042       Int_t itask = 0;
2043       while ((task=(AliAnalysisTask*)next1())) {
2044          if (fDebug >1) {
2045             cout << "    Executing task " << task->GetName() << endl;
2046          }       
2047          task->ExecuteTask(option);
2048          gROOT->cd();
2049          if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2050             AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2051          itask++;   
2052       }
2053 //
2054 //    Call FinishEvent() for optional output and MC services 
2055       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2056       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2057       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2058       // Gather system information if requested
2059       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2060          AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2061       cdir->cd();   
2062       return;
2063    }   
2064    // The event loop is not controlled by TSelector   
2065 //
2066 //  Call BeginEvent() for optional input/output and MC services 
2067    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
2068    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
2069    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2070    gROOT->cd();
2071    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2072       AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2073    TIter next2(fTopTasks);
2074    while ((task=(AliAnalysisTask*)next2())) {
2075       task->SetActive(kTRUE);
2076       if (fDebug > 1) {
2077          cout << "    Executing task " << task->GetName() << endl;
2078       }   
2079       task->ExecuteTask(option);
2080       gROOT->cd();
2081    }   
2082 //
2083 // Call FinishEvent() for optional output and MC services 
2084    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2085    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2086    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2087    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2088       AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2089    cdir->cd();   
2090 }
2091
2092 //______________________________________________________________________________
2093 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2094 {
2095 // Check if the stdout is connected to a pipe (C.Holm)
2096   Bool_t ispipe = kFALSE;
2097   out.seekp(0, std::ios_base::cur);
2098   if (out.fail()) {
2099     out.clear();
2100     if (errno == ESPIPE) ispipe = kTRUE;
2101   }
2102   return ispipe;
2103 }
2104    
2105 //______________________________________________________________________________
2106 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2107 {
2108 // Set the input event handler and create a container for it.
2109    fInputEventHandler   = handler;
2110    if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2111 }
2112
2113 //______________________________________________________________________________
2114 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2115 {
2116 // Set the input event handler and create a container for it.
2117    fOutputEventHandler   = handler;
2118    if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2119    fCommonOutput->SetSpecialOutput();
2120 }
2121
2122 //______________________________________________________________________________
2123 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2124 {
2125 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2126    if (TObject::TestBit(kUseProgressBar)) {
2127       Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2128       return;
2129    }
2130    fDebug = level;
2131 }
2132    
2133 //______________________________________________________________________________
2134 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2135 {
2136 // Enable a text mode progress bar. Resets debug level to 0.
2137    Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n  ### NOTE: Debug level reset to 0 ###", freq);
2138    TObject::SetBit(kUseProgressBar,flag);
2139    fPBUpdateFreq = freq;
2140    fDebug = 0;
2141 }   
2142
2143 //______________________________________________________________________________
2144 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2145 {
2146 // This method is used externally to register output files which are not
2147 // connected to any output container, so that the manager can properly register,
2148 // retrieve or merge them when running in distributed mode. The file names are
2149 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2150    if (fExtraFiles.Contains(fname)) return;
2151    if (fExtraFiles.Length()) fExtraFiles += " ";
2152    fExtraFiles += fname;
2153 }
2154
2155 //______________________________________________________________________________
2156 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2157 {
2158 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2159    char fullPath[512];
2160    char chUrl[512];
2161    char tmp[1024];
2162    TObject *pof =  source->FindObject(filename);
2163    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2164       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2165       return kFALSE;
2166    }
2167    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2168    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2169    TString clientUrl(chUrl);
2170    TString fullPath_str(fullPath);
2171    if (clientUrl.Contains("localhost")){
2172       TObjArray* array = fullPath_str.Tokenize ( "//" );
2173       TObjString *strobj = ( TObjString *)array->At(1);
2174       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2175       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2176       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2177       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2178       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2179       delete arrayPort;
2180       delete array;
2181    }
2182    else if (clientUrl.Contains("__lite__")) { 
2183      // Special case for ProofLite environement - get file info and copy. 
2184      gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2185      fullPath_str = Form("%s/%s", tmp, fullPath);
2186    }
2187    if (fDebug > 1) 
2188      Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2189    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
2190    if (!gotit)
2191       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2192    return gotit;
2193 }
2194
2195 //______________________________________________________________________________
2196 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2197 {
2198 // Fill analysis type in the provided string.
2199    switch (fMode) {
2200       case kLocalAnalysis:
2201          type = "local";
2202          return;
2203       case kProofAnalysis:
2204          type = "proof";
2205          return;
2206       case kGridAnalysis:
2207          type = "grid";
2208          return;
2209       case kMixingAnalysis:
2210          type = "mix";
2211    }
2212 }
2213
2214 //______________________________________________________________________________
2215 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2216 {
2217 // Validate all output files.
2218    TIter next(fOutputs);
2219    AliAnalysisDataContainer *output;
2220    TDirectory *cdir = gDirectory;
2221    TString openedFiles;
2222    while ((output=(AliAnalysisDataContainer*)next())) {
2223       if (output->IsRegisterDataset()) continue;
2224       TString filename = output->GetFileName();
2225       if (filename == "default") {
2226          if (!fOutputEventHandler) continue;
2227          filename = fOutputEventHandler->GetOutputFileName();
2228          // Main AOD may not be there
2229          if (gSystem->AccessPathName(filename)) continue;
2230       }
2231       // Check if the file is closed
2232       if (openedFiles.Contains(filename)) continue;;
2233       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2234       if (file) {
2235          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2236          // Clear file list to release object ownership to user.
2237 //         file->Clear();
2238          file->Close();
2239       }
2240       file = TFile::Open(filename);
2241       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2242          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2243          cdir->cd();
2244          return kFALSE;
2245       }
2246       file->Close();
2247       openedFiles += filename;
2248       openedFiles += " ";
2249    }
2250    cdir->cd();
2251    return kTRUE;
2252 }   
2253
2254 //______________________________________________________________________________
2255 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2256 {
2257 // Implements a nice text mode progress bar.
2258    static Long64_t icount = 0;
2259    static TString oname;
2260    static TString nname;
2261    static Long64_t ocurrent = 0;
2262    static Long64_t osize = 0;
2263    static Int_t oseconds = 0;
2264    static TStopwatch *owatch = 0;
2265    static Bool_t oneoftwo = kFALSE;
2266    static Int_t nrefresh = 0;
2267    static Int_t nchecks = 0;
2268    static char lastChar = 0;
2269    const char symbol[4] = {'-','\\','|','/'}; 
2270    
2271    if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2272    if (!refresh) {
2273       nrefresh = 0;
2274       if (!size) return;
2275       owatch = watch;
2276       oname = opname;
2277       ocurrent = TMath::Abs(current);
2278       osize = TMath::Abs(size);
2279       if (ocurrent > osize) ocurrent=osize;
2280    } else {
2281       nrefresh++;
2282       if (!osize) return;
2283    }     
2284    if ((current % fPBUpdateFreq) != 0) return;
2285    icount++;
2286    char progress[11] = "          ";
2287    Int_t ichar = icount%4;
2288    Double_t time = 0.;
2289    Int_t hours = 0;
2290    Int_t minutes = 0;
2291    Int_t seconds = 0;
2292    if (owatch && !last) {
2293       owatch->Stop();
2294       time = owatch->RealTime();
2295       seconds   = int(time) % 60;
2296       minutes   = (int(time) / 60) % 60;
2297       hours     = (int(time) / 60 / 60);
2298       if (refresh)  {
2299          if (oseconds==seconds) {
2300             owatch->Continue();
2301             return;
2302          }
2303          oneoftwo = !oneoftwo;   
2304       }
2305       oseconds = seconds;   
2306    }
2307    if (refresh && oneoftwo) {
2308       nname = oname;
2309       if (nchecks <= 0) nchecks = nrefresh+1;
2310       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2311       oname = Form("     == %d%% ==", pctdone);
2312    }         
2313    Double_t percent = 100.0*ocurrent/osize;
2314    Int_t nchar = Int_t(percent/10);
2315    if (nchar>10) nchar=10;
2316    Int_t i;
2317    for (i=0; i<nchar; i++)  progress[i] = '=';
2318    progress[nchar] = symbol[ichar];
2319    for (i=nchar+1; i<10; i++) progress[i] = ' ';
2320    progress[10] = '\0';
2321    oname += "                    ";
2322    oname.Remove(20);
2323    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2324    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2325    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2326    if (time>0.) {
2327      Int_t full   = Int_t(ocurrent > 0 ? 
2328                           time * (float(osize)/ocurrent) + .5 : 
2329                           99*3600+59*60+59); 
2330      Int_t remain = Int_t(full - time);
2331      Int_t rsec   = remain % 60;
2332      Int_t rmin   = (remain / 60) % 60;
2333      Int_t rhour  = (remain / 60 / 60);
2334      fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d  ETA %.2d:%.2d:%.2d%c",
2335              percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2336    }
2337    else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2338    if (refresh && oneoftwo) oname = nname;
2339    if (owatch) owatch->Continue();
2340    if (last) {
2341       icount = 0;
2342       owatch = 0;
2343       ocurrent = 0;
2344       osize = 0;
2345       oseconds = 0;
2346       oneoftwo = kFALSE;
2347       nrefresh = 0;
2348       fprintf(stderr, "\n");
2349    }   
2350 }
2351
2352 //______________________________________________________________________________
2353 void AliAnalysisManager::DoLoadBranch(const char *name) 
2354 {
2355   // Get tree and load branch if needed.
2356   static Long64_t crtEntry = -100;
2357
2358   if (fAutoBranchHandling || !fTree)
2359     return;
2360
2361   TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2362   if (!br) {
2363     br = fTree->GetBranch(name);
2364     if (!br) {
2365       Error("DoLoadBranch", "Could not find branch %s",name);
2366       return;
2367     }
2368     fTable.Add(br);
2369   }
2370   if (br->GetReadEntry()==fCurrentEntry) return;
2371   Int_t ret = br->GetEntry(GetCurrentEntry());
2372   if (ret<0) {
2373     Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2374     if (crtEntry != fCurrentEntry) {
2375       CountEvent(1,0,1,0);
2376       crtEntry = fCurrentEntry;
2377     }  
2378   } else {
2379     if (crtEntry != fCurrentEntry) {
2380       CountEvent(1,1,0,0);
2381       crtEntry = fCurrentEntry;
2382     }
2383   }
2384 }
2385
2386 //______________________________________________________________________________
2387 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2388 {
2389 // Add the statistics task to the manager.
2390   if (fStatistics) {
2391      Info("AddStatisticsTask", "Already added");
2392      return;
2393   }
2394   TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2395   gROOT->ProcessLine(line);
2396 }  
2397
2398 //______________________________________________________________________________
2399 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2400 {
2401 // Bookkeep current event;
2402    if (!fStatistics) return;
2403    fStatistics->AddInput(ninput);
2404    fStatistics->AddProcessed(nprocessed);
2405    fStatistics->AddFailed(nfailed);
2406    fStatistics->AddAccepted(naccepted);
2407 }   
2408
2409 //______________________________________________________________________________
2410 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2411 {
2412 // Add a line in the statistics message. If available, the statistics message is written
2413 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2414 // on the client.
2415    if (!strlen(line)) return;
2416    if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2417    fStatisticsMsg += line;
2418 }
2419
2420 //______________________________________________________________________________
2421 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2422 {
2423 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2424    static Bool_t done = kFALSE;
2425    if (done) return;
2426    done = kTRUE;
2427    if (!fStatistics) return;
2428    ofstream out;
2429    AddStatisticsMsg(Form("Number of input events:        %lld",fStatistics->GetNinput()));
2430    AddStatisticsMsg(Form("Number of processed events:    %lld",fStatistics->GetNprocessed()));      
2431    AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2432    AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2433    out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2434                  fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2435                  fStatistics->GetNaccepted()), ios::out);      
2436    out << fStatisticsMsg << endl;
2437    out.close();
2438 }
2439
2440 //______________________________________________________________________________
2441 const char* AliAnalysisManager::GetOADBPath()
2442 {
2443 // returns the path of the OADB
2444 // this static function just depends on environment variables
2445
2446    static TString oadbPath;
2447
2448    if (gSystem->Getenv("OADB_PATH"))
2449       oadbPath = gSystem->Getenv("OADB_PATH");
2450    else if (gSystem->Getenv("ALICE_ROOT"))
2451       oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2452    else
2453       ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2454       
2455    return oadbPath;
2456 }
2457
2458 //______________________________________________________________________________
2459 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2460 {
2461 // Define a custom string variable mapped to a global unique name. The variable
2462 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2463    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2464    if (!mgr) {
2465       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2466       return;
2467    }   
2468    Bool_t valid = kFALSE;
2469    TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2470    if (valid) {
2471       ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2472       return;
2473    }
2474    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2475 }
2476
2477 //______________________________________________________________________________
2478 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2479 {
2480 // Static method to retrieve a global variable defined via SetGlobalStr.
2481    valid = kFALSE;
2482    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2483    if (!mgr) return 0;
2484    TObject *value = mgr->GetGlobals()->GetValue(key);
2485    if (!value) return 0;
2486    valid = kTRUE;
2487    return value->GetName();
2488 }
2489
2490 //______________________________________________________________________________
2491 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2492 {
2493 // Define a custom integer variable mapped to a global unique name. The variable
2494 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2495    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2496    if (!mgr) {
2497       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2498       return;
2499    }   
2500    Bool_t valid = kFALSE;
2501    Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2502    if (valid) {
2503       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2504       return;
2505    }
2506    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2507 }
2508
2509 //______________________________________________________________________________
2510 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2511 {
2512 // Static method to retrieve a global variable defined via SetGlobalInt.
2513    valid = kFALSE;
2514    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2515    if (!mgr) return 0;
2516    TObject *value = mgr->GetGlobals()->GetValue(key);
2517    if (!value) return 0;
2518    valid = kTRUE;
2519    TString s = value->GetName();
2520    return s.Atoi();
2521 }
2522
2523 //______________________________________________________________________________
2524 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2525 {
2526 // Define a custom double precision variable mapped to a global unique name. The variable
2527 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2528    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2529    if (!mgr) {
2530       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2531       return;
2532    }   
2533    Bool_t valid = kFALSE;
2534    Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2535    if (valid) {
2536       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2537       return;
2538    }
2539    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2540 }
2541
2542 //______________________________________________________________________________
2543 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2544 {
2545 // Static method to retrieve a global variable defined via SetGlobalDbl.
2546    valid = kFALSE;
2547    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2548    if (!mgr) return 0;
2549    TObject *value = mgr->GetGlobals()->GetValue(key);
2550    if (!value) return 0;
2551    valid = kTRUE;
2552    TString s = value->GetName();
2553    return s.Atof();
2554 }