Fixed error when copying output files coming from PROOF analysis in GRID
[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    while ((output=(AliAnalysisDataContainer*)next1())) {
969       // Close all files at output
970       TDirectory *opwd = gDirectory;
971       if (output->GetFile()) {
972          // Clear file list to release object ownership to user.
973 //         output->GetFile()->Clear();
974          output->GetFile()->Close();
975          // Copy merged outputs in alien if requested
976          if (fSpecialOutputLocation.Length() && 
977              fSpecialOutputLocation.BeginsWith("alien://")) {
978             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
979             gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
980             TFile::Cp(output->GetFile()->GetName(), 
981                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
982          }             
983          output->SetFile(NULL);
984       }   
985       if (opwd) opwd->cd();
986    }   
987    delete allOutputs;
988    //Write statistics information on the client
989    if (fStatistics) WriteStatisticsMsg(fNcalls);
990    if (getsysInfo) {
991       TDirectory *crtdir = gDirectory;
992       TFile f("syswatch.root", "RECREATE");
993       TH1 *hist;
994       TString cut;
995       if (!f.IsZombie()) {
996          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
997          tree->SetName("syswatch");
998          tree->SetMarkerStyle(kCircle);
999          tree->SetMarkerColor(kBlue);
1000          tree->SetMarkerSize(0.5);
1001          if (!gROOT->IsBatch()) {
1002             tree->SetAlias("event", "id0");
1003             tree->SetAlias("task",  "id1");
1004             tree->SetAlias("stage", "id2");
1005             // Already defined aliases
1006             // tree->SetAlias("deltaT","stampSec-stampOldSec");
1007             // tree->SetAlias("T","stampSec-first");
1008             // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1009             // tree->SetAlias("VM","pI.fMemVirtual");
1010             TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1011             Int_t npads = 1 /*COO plot for all tasks*/ +
1012                           fTopTasks->GetEntries() /*Exec plot per task*/ +
1013                           1 /*Terminate plot for all tasks*/ +
1014                           1; /*vm plot*/
1015                           
1016             Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1017             if (npads<iopt*(iopt+1))
1018                canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1019             else
1020                canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1021             Int_t ipad = 1;
1022             // draw the plot of deltaVM for Exec for each task
1023             for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1024                task = (AliAnalysisTask*)fTopTasks->At(itask);
1025                canvas->cd(ipad++);
1026                cut = Form("task==%d && stage==1", itask);
1027                tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1028                hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
1029                if (hist) {
1030                   hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1031                   hist->GetYaxis()->SetTitle("deltaVM [MB]");
1032                }   
1033             }
1034             // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1035             canvas->cd(ipad++);
1036             tree->SetMarkerStyle(kFullTriangleUp);
1037             tree->SetMarkerColor(kRed);
1038             tree->SetMarkerSize(0.8);
1039             cut = "task>=0 && task<1000 && stage==0";
1040             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1041             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
1042             if (hist) {
1043                hist->SetTitle("Memory in CreateOutputObjects()");
1044                hist->GetYaxis()->SetTitle("deltaVM [MB]");
1045                hist->GetXaxis()->SetTitle("task");
1046             }   
1047             // draw the plot of deltaVM for Terminate for all tasks
1048             canvas->cd(ipad++);
1049             tree->SetMarkerStyle(kOpenSquare);
1050             tree->SetMarkerColor(kMagenta);
1051             cut = "task>=0 && task<1000 && stage==2";
1052             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1053             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1054             if (hist) {
1055                hist->SetTitle("Memory in Terminate()");
1056                hist->GetYaxis()->SetTitle("deltaVM [MB]");
1057                hist->GetXaxis()->SetTitle("task");
1058             }   
1059             // Full VM profile
1060             canvas->cd(ipad++);
1061             tree->SetMarkerStyle(kFullCircle);
1062             tree->SetMarkerColor(kGreen);
1063             cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);            
1064             tree->Draw("VM:event",cut,"", 1234567890, 0);
1065             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1066             if (hist) {
1067                hist->SetTitle("Virtual memory");
1068                hist->GetYaxis()->SetTitle("VM [MB]");
1069             }
1070             canvas->Modified();   
1071          }   
1072          tree->SetMarkerStyle(kCircle);
1073          tree->SetMarkerColor(kBlue);
1074          tree->SetMarkerSize(0.5);
1075          tree->Write();
1076          f.Close();
1077          delete tree;
1078       }
1079       if (crtdir) crtdir->cd();
1080    }
1081    // Validate the output files
1082    if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1083       ofstream out;
1084       out.open("outputs_valid", ios::out);
1085       out.close();
1086    }
1087    cdir->cd();      
1088    if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1089 }
1090 //______________________________________________________________________________
1091 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1092 {
1093 // Profiles the task having the itop index in the list of top (first level) tasks.
1094    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1095    if (!task) {
1096       Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1097       return;
1098    }
1099    ProfileTask(task->GetName(), option);
1100 }      
1101
1102 //______________________________________________________________________________
1103 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1104 {
1105 // Profile a managed task after the execution of the analysis in case NSysInfo
1106 // was used.
1107    if (gSystem->AccessPathName("syswatch.root")) {
1108       Error("ProfileTask", "No file syswatch.root found in the current directory");
1109       return;
1110    }
1111    if (gROOT->IsBatch()) return;
1112    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1113    if (!task) {
1114       Error("ProfileTask", "No top task named %s known by the manager.", name);
1115       return;
1116    }
1117    Int_t itop = fTopTasks->IndexOf(task);
1118    Int_t itask = fTasks->IndexOf(task);
1119    // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1120    TDirectory *cdir = gDirectory;
1121    TFile f("syswatch.root");
1122    TTree *tree = (TTree*)f.Get("syswatch");
1123    if (!tree) {
1124       Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1125       return;
1126    }   
1127    if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1128    TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1129    canvas->Divide(2, 2, 0.01, 0.01);
1130    Int_t ipad = 1;
1131    TString cut;
1132    TH1 *hist;
1133    // VM profile for COO and Terminate methods
1134    canvas->cd(ipad++);
1135    cut = Form("task==%d && (stage==0 || stage==2)",itask);
1136    tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1137    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1138    if (hist) {
1139       hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1140       hist->GetYaxis()->SetTitle("deltaVM [MB]");
1141       hist->GetXaxis()->SetTitle("method");
1142    }   
1143    // CPU profile per event
1144    canvas->cd(ipad++);
1145    cut = Form("task==%d && stage==1",itop);
1146    tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1147    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1148    if (hist) {
1149       hist->SetTitle("Execution time per event");
1150       hist->GetYaxis()->SetTitle("CPU/event [s]");
1151    }   
1152    // VM profile for Exec
1153    canvas->cd(ipad++);
1154    cut = Form("task==%d && stage==1",itop);
1155    tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1156    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1157    if (hist) {
1158       hist->SetTitle("Alocated VM[MB] per event");
1159       hist->GetYaxis()->SetTitle("deltaVM [MB]");
1160    }   
1161    canvas->Modified();
1162    delete tree;
1163    f.Close();
1164    if (cdir) cdir->cd();
1165 }     
1166
1167 //______________________________________________________________________________
1168 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1169 {
1170 // Adds a user task to the global list of tasks.
1171    if (fInitOK) {
1172       Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1173       return;
1174    }   
1175       
1176    if (fTasks->FindObject(task)) {
1177       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1178       return;
1179    }   
1180    task->SetActive(kFALSE);
1181    fTasks->Add(task);
1182 }  
1183
1184 //______________________________________________________________________________
1185 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1186 {
1187 // Retreive task by name.
1188    if (!fTasks) return NULL;
1189    return (AliAnalysisTask*)fTasks->FindObject(name);
1190 }
1191
1192 //______________________________________________________________________________
1193 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
1194                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
1195 {
1196 // Create a data container of a certain type. Types can be:
1197 //   kExchangeContainer  = 0, used to exchange data between tasks
1198 //   kInputContainer   = 1, used to store input data
1199 //   kOutputContainer  = 2, used for writing result to a file
1200 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1201 // the output object to a folder inside the output file
1202    if (fContainers->FindObject(name)) {
1203       Error("CreateContainer","A container named %s already defined !",name);
1204       return NULL;
1205    }   
1206    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1207    fContainers->Add(cont);
1208    switch (type) {
1209       case kInputContainer:
1210          fInputs->Add(cont);
1211          break;
1212       case kOutputContainer:
1213          fOutputs->Add(cont);
1214          if (filename && strlen(filename)) {
1215             cont->SetFileName(filename);
1216             cont->SetDataOwned(kFALSE);  // data owned by the file
1217          }   
1218          break;
1219       case kParamContainer:
1220          fParamCont->Add(cont);
1221          if (filename && strlen(filename)) {
1222             cont->SetFileName(filename);
1223             cont->SetDataOwned(kFALSE);  // data owned by the file
1224          }   
1225          break;
1226       case kExchangeContainer:
1227          break;   
1228    }
1229    return cont;
1230 }
1231          
1232 //______________________________________________________________________________
1233 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1234                                         AliAnalysisDataContainer *cont)
1235 {
1236 // Connect input of an existing task to a data container.
1237    if (!task) {
1238       Error("ConnectInput", "Task pointer is NULL");
1239       return kFALSE;
1240    }   
1241    if (!fTasks->FindObject(task)) {
1242       AddTask(task);
1243       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1244    } 
1245    Bool_t connected = task->ConnectInput(islot, cont);
1246    return connected;
1247 }   
1248
1249 //______________________________________________________________________________
1250 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1251                                         AliAnalysisDataContainer *cont)
1252 {
1253 // Connect output of an existing task to a data container.
1254    if (!task) {
1255       Error("ConnectOutput", "Task pointer is NULL");
1256       return kFALSE;
1257    }   
1258    if (!fTasks->FindObject(task)) {
1259       AddTask(task);
1260       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1261    } 
1262    Bool_t connected = task->ConnectOutput(islot, cont);
1263    return connected;
1264 }   
1265                                
1266 //______________________________________________________________________________
1267 void AliAnalysisManager::CleanContainers()
1268 {
1269 // Clean data from all containers that have already finished all client tasks.
1270    TIter next(fContainers);
1271    AliAnalysisDataContainer *cont;
1272    while ((cont=(AliAnalysisDataContainer *)next())) {
1273       if (cont->IsOwnedData() && 
1274           cont->IsDataReady() && 
1275           cont->ClientsExecuted()) cont->DeleteData();
1276    }
1277 }
1278
1279 //______________________________________________________________________________
1280 Bool_t AliAnalysisManager::InitAnalysis()
1281 {
1282 // Initialization of analysis chain of tasks. Should be called after all tasks
1283 // and data containers are properly connected
1284    // Reset flag and remove valid_outputs file if exists
1285    if (fInitOK) return kTRUE;
1286    if (!gSystem->AccessPathName("outputs_valid"))
1287       gSystem->Unlink("outputs_valid");
1288    // Check for top tasks (depending only on input data containers)
1289    if (!fTasks->First()) {
1290       Error("InitAnalysis", "Analysis has no tasks !");
1291       return kFALSE;
1292    }   
1293    TIter next(fTasks);
1294    AliAnalysisTask *task;
1295    AliAnalysisDataContainer *cont;
1296    Int_t ntop = 0;
1297    Int_t nzombies = 0;
1298    Bool_t iszombie = kFALSE;
1299    Bool_t istop = kTRUE;
1300    Int_t i;
1301    while ((task=(AliAnalysisTask*)next())) {
1302       istop = kTRUE;
1303       iszombie = kFALSE;
1304       Int_t ninputs = task->GetNinputs();
1305       for (i=0; i<ninputs; i++) {
1306          cont = task->GetInputSlot(i)->GetContainer();
1307          if (!cont) {
1308             if (!iszombie) {
1309                task->SetZombie();
1310                fZombies->Add(task);
1311                nzombies++;
1312                iszombie = kTRUE;
1313             }   
1314             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
1315                   i, task->GetName()); 
1316          }
1317          if (iszombie) continue;
1318          // Check if cont is an input container
1319          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1320          // Connect to parent task
1321       }
1322       if (istop) {
1323          ntop++;
1324          fTopTasks->Add(task);
1325       }
1326    }
1327    if (!ntop) {
1328       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1329       return kFALSE;
1330    }                        
1331    // Check now if there are orphan tasks
1332    for (i=0; i<ntop; i++) {
1333       task = (AliAnalysisTask*)fTopTasks->At(i);
1334       task->SetUsed();
1335    }
1336    Int_t norphans = 0;
1337    next.Reset();
1338    while ((task=(AliAnalysisTask*)next())) {
1339       if (!task->IsUsed()) {
1340          norphans++;
1341          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1342       }   
1343    }          
1344    // Check the task hierarchy (no parent task should depend on data provided
1345    // by a daughter task)
1346    for (i=0; i<ntop; i++) {
1347       task = (AliAnalysisTask*)fTopTasks->At(i);
1348       if (task->CheckCircularDeps()) {
1349          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1350          PrintStatus("dep");
1351          return kFALSE;
1352       }   
1353    }
1354    // Check that all containers feeding post-event loop tasks are in the outputs list
1355    TIter nextcont(fContainers); // loop over all containers
1356    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1357       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1358          if (cont->HasConsumers()) {
1359          // Check if one of the consumers is post event loop
1360             TIter nextconsumer(cont->GetConsumers());
1361             while ((task=(AliAnalysisTask*)nextconsumer())) {
1362                if (task->IsPostEventLoop()) {
1363                   fOutputs->Add(cont);
1364                   break;
1365                }
1366             }
1367          }
1368       }
1369    }   
1370    // Check if all special output containers have a file name provided
1371    TIter nextout(fOutputs);
1372    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1373       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1374          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1375          return kFALSE;
1376       }
1377    }
1378    // Initialize requested branch list if needed
1379    if (!fAutoBranchHandling) {
1380       next.Reset();
1381       while ((task=(AliAnalysisTask*)next())) {
1382          if (!task->HasBranches()) {
1383             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\"",
1384                   task->GetName(), task->ClassName());
1385             return kFALSE;
1386          }
1387          if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1388             Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1389             return kFALSE;
1390          }
1391          TString taskbranches;
1392          task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1393          if (taskbranches.IsNull()) {
1394             Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1395                   task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1396             return kFALSE;      
1397          }
1398          AddBranches(taskbranches);
1399       }         
1400    }
1401    fInitOK = kTRUE;
1402    return kTRUE;
1403 }   
1404
1405 //______________________________________________________________________________
1406 void AliAnalysisManager::AddBranches(const char *branches)
1407 {
1408 // Add branches to the existing fRequestedBranches.
1409    TString br(branches);
1410    TObjArray *arr = br.Tokenize(",");
1411    TIter next(arr);
1412    TObject *obj;
1413    while ((obj=next())) {
1414       if (!fRequestedBranches.Contains(obj->GetName())) {
1415          if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1416          fRequestedBranches += obj->GetName();
1417       }
1418    }
1419   delete arr;
1420 }   
1421
1422 //______________________________________________________________________________
1423 void AliAnalysisManager::CheckBranches(Bool_t load)
1424 {
1425 // The method checks the input branches to be loaded during the analysis.
1426    if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;   
1427    TObjArray *arr = fRequestedBranches.Tokenize(",");
1428    TIter next(arr);
1429    TObject *obj;
1430    while ((obj=next())) {
1431       TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1432       if (!br) {
1433          br = fTree->GetBranch(obj->GetName());
1434          if (!br) {
1435             Error("CheckBranches", "Could not find branch %s",obj->GetName());
1436             continue;
1437          }
1438       }   
1439       fTable.Add(br);
1440       if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry());
1441    }
1442   delete arr;
1443 }
1444
1445 //______________________________________________________________________________
1446 Bool_t AliAnalysisManager::CheckTasks() const
1447 {
1448 // Check consistency of tasks.
1449    Int_t ntasks = fTasks->GetEntries();
1450    if (!ntasks) {
1451       Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1452       return kFALSE;
1453    }
1454    // Get the pointer to AliAnalysisTaskSE::Class()
1455    TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1456    // Loop all tasks to check if their corresponding library was loaded
1457    TIter next(fTasks);
1458    TObject *obj;
1459    while ((obj=next())) {
1460       if (obj->IsA() == badptr) {
1461          Error("CheckTasks", "##################\n \
1462          Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1463          return kFALSE;
1464       }
1465    }
1466    return kTRUE;      
1467 }   
1468
1469 //______________________________________________________________________________
1470 void AliAnalysisManager::PrintStatus(Option_t *option) const
1471 {
1472 // Print task hierarchy.
1473    if (!fInitOK) {
1474       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1475       return;
1476    }   
1477    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1478    if (getsysInfo)
1479       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1480    TIter next(fTopTasks);
1481    AliAnalysisTask *task;
1482    while ((task=(AliAnalysisTask*)next()))
1483       task->PrintTask(option);
1484   
1485    if (!fAutoBranchHandling && !fRequestedBranches.IsNull()) 
1486       printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1487   
1488   TString sopt(option);
1489   sopt.ToUpper();
1490   
1491   if (sopt.Contains("ALL"))
1492   {
1493     if ( fOutputEventHandler )
1494     {
1495       cout << TString('_',78) << endl;
1496       cout << "OutputEventHandler:" << endl;
1497       fOutputEventHandler->Print("   ");
1498     }
1499   }
1500 }
1501
1502 //______________________________________________________________________________
1503 void AliAnalysisManager::ResetAnalysis()
1504 {
1505 // Reset all execution flags and clean containers.
1506    CleanContainers();
1507 }
1508
1509 //______________________________________________________________________________
1510 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1511 {
1512 // Start analysis having a grid handler.
1513    if (!fGridHandler) {
1514       Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1515       Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1516       return -1;
1517    }
1518    TTree *tree = NULL;
1519    return StartAnalysis(type, tree, nentries, firstentry);
1520 }
1521
1522 //______________________________________________________________________________
1523 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1524 {
1525 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1526 // MIX. Process nentries starting from firstentry
1527    Long64_t retv = 0;
1528    // Backup current directory and make sure gDirectory points to gROOT
1529    TDirectory *cdir = gDirectory;
1530    gROOT->cd();
1531    if (!fInitOK) {
1532       Error("StartAnalysis","Analysis manager was not initialized !");
1533       cdir->cd();
1534       return -1;
1535    }
1536    if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1537    if (fDebug > 1) {
1538       printf("StartAnalysis %s\n",GetName());
1539       AliLog::SetGlobalLogLevel(AliLog::kInfo);
1540    }   
1541    fMaxEntries = nentries;
1542    fIsRemote = kFALSE;
1543    TString anaType = type;
1544    anaType.ToLower();
1545    fMode = kLocalAnalysis;
1546    Bool_t runlocalinit = kTRUE;
1547    if (anaType.Contains("file")) {
1548       runlocalinit = kFALSE;
1549       fIsRemote = kTRUE;
1550    }   
1551    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1552    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1553    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1554
1555    if (fMode == kGridAnalysis) {
1556       fIsRemote = kTRUE;
1557       if (!anaType.Contains("terminate")) {
1558          if (!fGridHandler) {
1559             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1560             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1561             cdir->cd();
1562             return -1;
1563          }
1564          // Write analysis manager in the analysis file
1565          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1566          // run local task configuration
1567          TIter nextTask(fTasks);
1568          AliAnalysisTask *task;
1569          while ((task=(AliAnalysisTask*)nextTask())) {
1570             task->LocalInit();
1571             gROOT->cd();
1572          }
1573          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1574             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1575             cdir->cd();
1576             return -1;
1577          }   
1578
1579          // Terminate grid analysis
1580          if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1581          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1582          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1583          if (!fGridHandler->MergeOutputs()) {
1584             // Return if outputs could not be merged or if it alien handler
1585             // was configured for offline mode or local testing.
1586             cdir->cd();
1587             return 0;
1588          }
1589       }   
1590       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1591       ImportWrappers(NULL);
1592       Terminate();
1593       cdir->cd();
1594       return 0;
1595    }
1596    TString line;
1597    SetEventLoop(kFALSE);
1598    // Enable event loop mode if a tree was provided
1599    if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1600
1601    TChain *chain = 0;
1602    TString ttype = "TTree";
1603    if (tree && tree->IsA() == TChain::Class()) {
1604       chain = (TChain*)tree;
1605       if (!chain || !chain->GetListOfFiles()->First()) {
1606          Error("StartAnalysis", "Cannot process null or empty chain...");
1607          cdir->cd();
1608          return -1;
1609       }   
1610       ttype = "TChain";
1611    }   
1612
1613    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1614    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1615    // Initialize locally all tasks (happens for all modes)
1616    TIter next(fTasks);
1617    AliAnalysisTask *task;
1618    if (runlocalinit) {
1619       while ((task=(AliAnalysisTask*)next())) {
1620          task->LocalInit();
1621          gROOT->cd();
1622       }
1623       if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1624    }   
1625    
1626    switch (fMode) {
1627       case kLocalAnalysis:
1628          if (!tree && !fGridHandler) {
1629             TIter nextT(fTasks);
1630             // Call CreateOutputObjects for all tasks
1631             Int_t itask = 0;
1632             Bool_t dirStatus = TH1::AddDirectoryStatus();
1633             while ((task=(AliAnalysisTask*)nextT())) {
1634                TH1::AddDirectory(kFALSE);
1635                task->CreateOutputObjects();
1636                if (!task->CheckPostData()) {
1637                   Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1638                         Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1639                         ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1640                }
1641                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1642                gROOT->cd();
1643                itask++;
1644             }   
1645             TH1::AddDirectory(dirStatus);
1646             if (IsExternalLoop()) {
1647                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1648                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1649                return 0;
1650             }
1651             ExecAnalysis();
1652             Terminate();
1653             return 0;
1654          } 
1655          fSelector = new AliAnalysisSelector(this);
1656          // Check if a plugin handler is used
1657          if (fGridHandler) {
1658             // Get the chain from the plugin
1659             TString dataType = "esdTree";
1660             if (fInputEventHandler) {
1661                dataType = fInputEventHandler->GetDataType();
1662                dataType.ToLower();
1663                dataType += "Tree";
1664             }   
1665             chain = fGridHandler->GetChainForTestMode(dataType);
1666             if (!chain) {
1667                Error("StartAnalysis", "No chain for test mode. Aborting.");
1668                return -1;
1669             }
1670             cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1671             retv = chain->Process(fSelector, "", nentries, firstentry);
1672             break;
1673          }
1674          // Run tree-based analysis via AliAnalysisSelector  
1675          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1676          retv = tree->Process(fSelector, "", nentries, firstentry);
1677          break;
1678       case kProofAnalysis:
1679          fIsRemote = kTRUE;
1680          // Check if the plugin is used
1681          if (fGridHandler) {
1682             return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1683          }
1684          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1685             Error("StartAnalysis", "No PROOF!!! Exiting.");
1686             cdir->cd();
1687             return -1;
1688          }   
1689          line = Form("gProof->AddInput((TObject*)%p);", this);
1690          gROOT->ProcessLine(line);
1691          if (chain) {
1692             chain->SetProof();
1693             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1694             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1695          } else {
1696             Error("StartAnalysis", "No chain!!! Exiting.");
1697             cdir->cd();
1698             return -1;
1699          }      
1700          break;
1701       case kGridAnalysis:
1702          fIsRemote = kTRUE;
1703          if (!anaType.Contains("terminate")) {
1704             if (!fGridHandler) {
1705                Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1706                Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1707                cdir->cd();
1708                return -1;
1709             }
1710             // Write analysis manager in the analysis file
1711             cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1712             // Start the analysis via the handler
1713             if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1714                Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1715                cdir->cd();
1716                return -1;
1717             }   
1718
1719             // Terminate grid analysis
1720             if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1721             if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1722             cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1723             if (!fGridHandler->MergeOutputs()) {
1724                // Return if outputs could not be merged or if it alien handler
1725                // was configured for offline mode or local testing.
1726                cdir->cd();
1727                return 0;
1728             }
1729          }   
1730          cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1731          ImportWrappers(NULL);
1732          Terminate();
1733          cdir->cd();
1734          return 0;
1735       case kMixingAnalysis:   
1736          // Run event mixing analysis
1737          if (!fEventPool) {
1738             Error("StartAnalysis", "Cannot run event mixing without event pool");
1739             cdir->cd();
1740             return -1;
1741          }
1742          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1743          fSelector = new AliAnalysisSelector(this);
1744          while ((chain=fEventPool->GetNextChain())) {
1745             next.Reset();
1746             // Call NotifyBinChange for all tasks
1747             while ((task=(AliAnalysisTask*)next()))
1748                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1749             retv = chain->Process(fSelector);
1750             if (retv < 0) {
1751                Error("StartAnalysis", "Mixing analysis failed");
1752                cdir->cd();
1753                return retv;
1754             }   
1755          }
1756          PackOutput(fSelector->GetOutputList());
1757          Terminate();
1758    }
1759    cdir->cd();
1760    return retv;
1761 }   
1762
1763 //______________________________________________________________________________
1764 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1765 {
1766 // Start analysis for this manager on a given dataset. Analysis task can be: 
1767 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1768    if (!fInitOK) {
1769       Error("StartAnalysis","Analysis manager was not initialized !");
1770       return -1;
1771    }
1772    fIsRemote = kTRUE;
1773    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1774    TString anaType = type;
1775    anaType.ToLower();
1776    if (!anaType.Contains("proof")) {
1777       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1778       return -1;
1779    }   
1780    fMode = kProofAnalysis;
1781    TString line;
1782    SetEventLoop(kTRUE);
1783    // Set the dataset flag
1784    TObject::SetBit(kUseDataSet);
1785    fTree = 0;
1786    if (fGridHandler) {
1787       // Start proof analysis using the grid handler
1788       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1789          Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1790          return -1;
1791       }
1792       // Check if the plugin is in test mode
1793       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1794          dataset = "test_collection";
1795       } else {
1796          dataset = fGridHandler->GetProofDataSet();
1797       }
1798    }   
1799
1800    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1801       Error("StartAnalysis", "No PROOF!!! Exiting.");
1802       return -1;
1803    }   
1804
1805    // Initialize locally all tasks
1806    TIter next(fTasks);
1807    AliAnalysisTask *task;
1808    while ((task=(AliAnalysisTask*)next())) {
1809       task->LocalInit();
1810    }
1811    
1812    line = Form("gProof->AddInput((TObject*)%p);", this);
1813    gROOT->ProcessLine(line);
1814    Long_t retv;
1815    line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1816                dataset, nentries, firstentry);
1817    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1818    retv = (Long_t)gROOT->ProcessLine(line);
1819    return retv;
1820 }   
1821
1822 //______________________________________________________________________________
1823 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1824 {
1825 // Opens according the option the file specified by cont->GetFileName() and changes
1826 // current directory to cont->GetFolderName(). If the file was already opened, it
1827 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1828 // be optionally ignored.
1829   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1830   TString filename = cont->GetFileName();
1831   TFile *f = NULL;
1832   if (filename.IsNull()) {
1833     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1834     return NULL;
1835   }
1836   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1837       && !ignoreProof)
1838     f = mgr->OpenProofFile(cont,option);
1839   else {
1840     // Check first if the file is already opened
1841     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1842     if (f) {
1843       // Check if option "UPDATE" was preserved 
1844       TString opt(option);
1845       opt.ToUpper();
1846       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1847         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1848     } else {
1849       f = TFile::Open(filename, option);
1850     }    
1851   }   
1852   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1853     cont->SetFile(f);
1854     // Cd to file
1855     f->cd();
1856     // Check for a folder request
1857     TString dir = cont->GetFolderName(); 
1858     if (!dir.IsNull()) {
1859       if (!f->GetDirectory(dir)) f->mkdir(dir);
1860       f->cd(dir);
1861     }
1862     return f;
1863   }
1864   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1865   cont->SetFile(NULL);
1866   return NULL;
1867 }    
1868  
1869 //______________________________________________________________________________
1870 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1871 {
1872 // Opens a special output file used in PROOF.
1873   TString line;
1874   TString filename = cont->GetFileName();
1875   if (cont == fCommonOutput) {
1876      if (fOutputEventHandler) {
1877         if (strlen(extaod)) filename = extaod;
1878         filename = fOutputEventHandler->GetOutputFileName();
1879      }   
1880      else Fatal("OpenProofFile","No output container. Exiting.");
1881   }   
1882   TFile *f = NULL;
1883   if (fMode!=kProofAnalysis || !fSelector) {
1884     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1885     return NULL;
1886   } 
1887   if (fSpecialOutputLocation.Length()) {
1888     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1889     if (f) {
1890       // Check if option "UPDATE" was preserved 
1891       TString opt(option);
1892       opt.ToUpper();
1893       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1894         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1895     } else {
1896       f = new TFile(filename, option);
1897     }
1898     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1899       cont->SetFile(f);
1900       // Cd to file
1901       f->cd();
1902       // Check for a folder request
1903       TString dir = cont->GetFolderName(); 
1904       if (dir.Length()) {
1905         if (!f->GetDirectory(dir)) f->mkdir(dir);
1906         f->cd(dir);
1907       }      
1908       return f;
1909     }
1910     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1911     cont->SetFile(NULL);
1912     return NULL;       
1913   }
1914   // Check if there is already a proof output file in the output list
1915   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1916   if (pof) {
1917     // Get the actual file
1918     line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
1919     filename = (const char*)gROOT->ProcessLine(line);
1920     if (fDebug>1) {
1921       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1922     }  
1923     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1924     if (!f) {
1925        Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1926        return NULL;
1927     }   
1928     // Check if option "UPDATE" was preserved 
1929     TString opt(option);
1930     opt.ToUpper();
1931     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1932       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1933   } else {
1934     if (cont->IsRegisterDataset()) {
1935       TString dsetName = filename;
1936       dsetName.ReplaceAll(".root", cont->GetTitle());
1937       dsetName.ReplaceAll(":","_");
1938       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1939       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1940     } else {
1941       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1942       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1943     }
1944     if (fDebug > 1) printf("=== %s\n", line.Data());
1945     gROOT->ProcessLine(line);
1946     line = Form("pf->OpenFile(\"%s\");", option);
1947     gROOT->ProcessLine(line);
1948     f = gFile;
1949     if (fDebug > 1) {
1950       gROOT->ProcessLine("pf->Print()");
1951       printf(" == proof file name: %s", f->GetName());
1952     }   
1953     // Add to proof output list
1954     line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
1955     if (fDebug > 1) printf("=== %s\n", line.Data());
1956     gROOT->ProcessLine(line);
1957   }
1958   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1959     cont->SetFile(f);
1960     // Cd to file
1961     f->cd();
1962     // Check for a folder request
1963     TString dir = cont->GetFolderName(); 
1964     if (!dir.IsNull()) {
1965       if (!f->GetDirectory(dir)) f->mkdir(dir);
1966       f->cd(dir);
1967     }
1968     return f;
1969   }
1970   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1971   cont->SetFile(NULL);  
1972   return NULL;
1973 }   
1974
1975 //______________________________________________________________________________
1976 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1977 {
1978 // Execute analysis.
1979    static Long64_t nentries = 0;
1980    static TTree *lastTree = 0;
1981    static TStopwatch *timer = new TStopwatch();
1982    // Only the first call to Process will trigger a true Notify. Other Notify
1983    // coming before is ignored.
1984    if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
1985       TObject::SetBit(AliAnalysisManager::kTrueNotify);
1986       Notify();
1987    }   
1988    if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
1989    else {
1990       if (fTree && (fTree != lastTree)) {
1991          nentries += fTree->GetEntries();
1992          lastTree = fTree;
1993       }   
1994       if (!fNcalls) timer->Start();
1995       if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
1996    }
1997    gROOT->cd();
1998    TDirectory *cdir = gDirectory;
1999    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2000    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2001    if (!fInitOK) {
2002       Error("ExecAnalysis", "Analysis manager was not initialized !");
2003       cdir->cd();
2004       return;
2005    }
2006    fNcalls++;
2007    AliAnalysisTask *task;
2008    // Check if the top tree is active.
2009    if (fTree) {
2010       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2011          AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2012       TIter next(fTasks);
2013    // De-activate all tasks
2014       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2015       AliAnalysisDataContainer *cont = fCommonInput;
2016       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2017       if (!cont) {
2018               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2019          cdir->cd();
2020          return;
2021       }   
2022       cont->SetData(fTree); // This will notify all consumers
2023       Long64_t entry = fTree->GetTree()->GetReadEntry();      
2024 //
2025 //    Call BeginEvent() for optional input/output and MC services 
2026       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
2027       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
2028       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2029       gROOT->cd();
2030       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2031          AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2032 //
2033 //    Execute the tasks
2034 //      TIter next1(cont->GetConsumers());
2035       TIter next1(fTopTasks);
2036       Int_t itask = 0;
2037       while ((task=(AliAnalysisTask*)next1())) {
2038          if (fDebug >1) {
2039             cout << "    Executing task " << task->GetName() << endl;
2040          }       
2041          task->ExecuteTask(option);
2042          gROOT->cd();
2043          if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2044             AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2045          itask++;   
2046       }
2047 //
2048 //    Call FinishEvent() for optional output and MC services 
2049       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2050       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2051       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2052       // Gather system information if requested
2053       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2054          AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2055       cdir->cd();   
2056       return;
2057    }   
2058    // The event loop is not controlled by TSelector   
2059 //
2060 //  Call BeginEvent() for optional input/output and MC services 
2061    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
2062    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
2063    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2064    gROOT->cd();
2065    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2066       AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2067    TIter next2(fTopTasks);
2068    while ((task=(AliAnalysisTask*)next2())) {
2069       task->SetActive(kTRUE);
2070       if (fDebug > 1) {
2071          cout << "    Executing task " << task->GetName() << endl;
2072       }   
2073       task->ExecuteTask(option);
2074       gROOT->cd();
2075    }   
2076 //
2077 // Call FinishEvent() for optional output and MC services 
2078    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2079    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2080    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2081    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2082       AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2083    cdir->cd();   
2084 }
2085
2086 //______________________________________________________________________________
2087 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2088 {
2089 // Check if the stdout is connected to a pipe (C.Holm)
2090   Bool_t ispipe = kFALSE;
2091   out.seekp(0, std::ios_base::cur);
2092   if (out.fail()) {
2093     out.clear();
2094     if (errno == ESPIPE) ispipe = kTRUE;
2095   }
2096   return ispipe;
2097 }
2098    
2099 //______________________________________________________________________________
2100 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2101 {
2102 // Set the input event handler and create a container for it.
2103    fInputEventHandler   = handler;
2104    if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2105 }
2106
2107 //______________________________________________________________________________
2108 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2109 {
2110 // Set the input event handler and create a container for it.
2111    fOutputEventHandler   = handler;
2112    if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2113    fCommonOutput->SetSpecialOutput();
2114 }
2115
2116 //______________________________________________________________________________
2117 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2118 {
2119 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2120    if (TObject::TestBit(kUseProgressBar)) {
2121       Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2122       return;
2123    }
2124    fDebug = level;
2125 }
2126    
2127 //______________________________________________________________________________
2128 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2129 {
2130 // Enable a text mode progress bar. Resets debug level to 0.
2131    Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n  ### NOTE: Debug level reset to 0 ###", freq);
2132    TObject::SetBit(kUseProgressBar,flag);
2133    fPBUpdateFreq = freq;
2134    fDebug = 0;
2135 }   
2136
2137 //______________________________________________________________________________
2138 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2139 {
2140 // This method is used externally to register output files which are not
2141 // connected to any output container, so that the manager can properly register,
2142 // retrieve or merge them when running in distributed mode. The file names are
2143 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2144    if (fExtraFiles.Contains(fname)) return;
2145    if (fExtraFiles.Length()) fExtraFiles += " ";
2146    fExtraFiles += fname;
2147 }
2148
2149 //______________________________________________________________________________
2150 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2151 {
2152 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2153    char fullPath[512];
2154    char chUrl[512];
2155    char tmp[1024];
2156    TObject *pof =  source->FindObject(filename);
2157    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2158       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2159       return kFALSE;
2160    }
2161    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2162    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2163    TString clientUrl(chUrl);
2164    TString fullPath_str(fullPath);
2165    if (clientUrl.Contains("localhost")){
2166       TObjArray* array = fullPath_str.Tokenize ( "//" );
2167       TObjString *strobj = ( TObjString *)array->At(1);
2168       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2169       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2170       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2171       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2172       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2173       delete arrayPort;
2174       delete array;
2175    }
2176    else if (clientUrl.Contains("__lite__")) { 
2177      // Special case for ProofLite environement - get file info and copy. 
2178      gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2179      fullPath_str = Form("%s/%s", tmp, fullPath);
2180    }
2181    if (fDebug > 1) 
2182      Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2183    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
2184    if (!gotit)
2185       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2186    return gotit;
2187 }
2188
2189 //______________________________________________________________________________
2190 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2191 {
2192 // Fill analysis type in the provided string.
2193    switch (fMode) {
2194       case kLocalAnalysis:
2195          type = "local";
2196          return;
2197       case kProofAnalysis:
2198          type = "proof";
2199          return;
2200       case kGridAnalysis:
2201          type = "grid";
2202          return;
2203       case kMixingAnalysis:
2204          type = "mix";
2205    }
2206 }
2207
2208 //______________________________________________________________________________
2209 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2210 {
2211 // Validate all output files.
2212    TIter next(fOutputs);
2213    AliAnalysisDataContainer *output;
2214    TDirectory *cdir = gDirectory;
2215    TString openedFiles;
2216    while ((output=(AliAnalysisDataContainer*)next())) {
2217       if (output->IsRegisterDataset()) continue;
2218       TString filename = output->GetFileName();
2219       if (filename == "default") {
2220          if (!fOutputEventHandler) continue;
2221          filename = fOutputEventHandler->GetOutputFileName();
2222          // Main AOD may not be there
2223          if (gSystem->AccessPathName(filename)) continue;
2224       }
2225       // Check if the file is closed
2226       if (openedFiles.Contains(filename)) continue;;
2227       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2228       if (file) {
2229          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2230          // Clear file list to release object ownership to user.
2231 //         file->Clear();
2232          file->Close();
2233       }
2234       file = TFile::Open(filename);
2235       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2236          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2237          cdir->cd();
2238          return kFALSE;
2239       }
2240       file->Close();
2241       openedFiles += filename;
2242       openedFiles += " ";
2243    }
2244    cdir->cd();
2245    return kTRUE;
2246 }   
2247
2248 //______________________________________________________________________________
2249 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2250 {
2251 // Implements a nice text mode progress bar.
2252    static Long64_t icount = 0;
2253    static TString oname;
2254    static TString nname;
2255    static Long64_t ocurrent = 0;
2256    static Long64_t osize = 0;
2257    static Int_t oseconds = 0;
2258    static TStopwatch *owatch = 0;
2259    static Bool_t oneoftwo = kFALSE;
2260    static Int_t nrefresh = 0;
2261    static Int_t nchecks = 0;
2262    static char lastChar = 0;
2263    const char symbol[4] = {'-','\\','|','/'}; 
2264    
2265    if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2266    if (!refresh) {
2267       nrefresh = 0;
2268       if (!size) return;
2269       owatch = watch;
2270       oname = opname;
2271       ocurrent = TMath::Abs(current);
2272       osize = TMath::Abs(size);
2273       if (ocurrent > osize) ocurrent=osize;
2274    } else {
2275       nrefresh++;
2276       if (!osize) return;
2277    }     
2278    if ((current % fPBUpdateFreq) != 0) return;
2279    icount++;
2280    char progress[11] = "          ";
2281    Int_t ichar = icount%4;
2282    Double_t time = 0.;
2283    Int_t hours = 0;
2284    Int_t minutes = 0;
2285    Int_t seconds = 0;
2286    if (owatch && !last) {
2287       owatch->Stop();
2288       time = owatch->RealTime();
2289       seconds   = int(time) % 60;
2290       minutes   = (int(time) / 60) % 60;
2291       hours     = (int(time) / 60 / 60);
2292       if (refresh)  {
2293          if (oseconds==seconds) {
2294             owatch->Continue();
2295             return;
2296          }
2297          oneoftwo = !oneoftwo;   
2298       }
2299       oseconds = seconds;   
2300    }
2301    if (refresh && oneoftwo) {
2302       nname = oname;
2303       if (nchecks <= 0) nchecks = nrefresh+1;
2304       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2305       oname = Form("     == %d%% ==", pctdone);
2306    }         
2307    Double_t percent = 100.0*ocurrent/osize;
2308    Int_t nchar = Int_t(percent/10);
2309    if (nchar>10) nchar=10;
2310    Int_t i;
2311    for (i=0; i<nchar; i++)  progress[i] = '=';
2312    progress[nchar] = symbol[ichar];
2313    for (i=nchar+1; i<10; i++) progress[i] = ' ';
2314    progress[10] = '\0';
2315    oname += "                    ";
2316    oname.Remove(20);
2317    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2318    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2319    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2320    if (time>0.) {
2321      Int_t full   = Int_t(ocurrent > 0 ? 
2322                           time * (float(osize)/ocurrent) + .5 : 
2323                           99*3600+59*60+59); 
2324      Int_t remain = Int_t(full - time);
2325      Int_t rsec   = remain % 60;
2326      Int_t rmin   = (remain / 60) % 60;
2327      Int_t rhour  = (remain / 60 / 60);
2328      fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d  ETA %.2d:%.2d:%.2d%c",
2329              percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2330    }
2331    else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2332    if (refresh && oneoftwo) oname = nname;
2333    if (owatch) owatch->Continue();
2334    if (last) {
2335       icount = 0;
2336       owatch = 0;
2337       ocurrent = 0;
2338       osize = 0;
2339       oseconds = 0;
2340       oneoftwo = kFALSE;
2341       nrefresh = 0;
2342       fprintf(stderr, "\n");
2343    }   
2344 }
2345
2346 //______________________________________________________________________________
2347 void AliAnalysisManager::DoLoadBranch(const char *name) 
2348 {
2349   // Get tree and load branch if needed.
2350   static Long64_t crtEntry = -100;
2351
2352   if (fAutoBranchHandling || !fTree)
2353     return;
2354
2355   TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2356   if (!br) {
2357     br = fTree->GetBranch(name);
2358     if (!br) {
2359       Error("DoLoadBranch", "Could not find branch %s",name);
2360       return;
2361     }
2362     fTable.Add(br);
2363   }
2364   if (br->GetReadEntry()==fCurrentEntry) return;
2365   Int_t ret = br->GetEntry(GetCurrentEntry());
2366   if (ret<0) {
2367     Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2368     if (crtEntry != fCurrentEntry) {
2369       CountEvent(1,0,1,0);
2370       crtEntry = fCurrentEntry;
2371     }  
2372   } else {
2373     if (crtEntry != fCurrentEntry) {
2374       CountEvent(1,1,0,0);
2375       crtEntry = fCurrentEntry;
2376     }
2377   }
2378 }
2379
2380 //______________________________________________________________________________
2381 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2382 {
2383 // Add the statistics task to the manager.
2384   if (fStatistics) {
2385      Info("AddStatisticsTask", "Already added");
2386      return;
2387   }
2388   TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2389   gROOT->ProcessLine(line);
2390 }  
2391
2392 //______________________________________________________________________________
2393 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2394 {
2395 // Bookkeep current event;
2396    if (!fStatistics) return;
2397    fStatistics->AddInput(ninput);
2398    fStatistics->AddProcessed(nprocessed);
2399    fStatistics->AddFailed(nfailed);
2400    fStatistics->AddAccepted(naccepted);
2401 }   
2402
2403 //______________________________________________________________________________
2404 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2405 {
2406 // Add a line in the statistics message. If available, the statistics message is written
2407 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2408 // on the client.
2409    if (!strlen(line)) return;
2410    if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2411    fStatisticsMsg += line;
2412 }
2413
2414 //______________________________________________________________________________
2415 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2416 {
2417 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2418    static Bool_t done = kFALSE;
2419    if (done) return;
2420    done = kTRUE;
2421    if (!fStatistics) return;
2422    ofstream out;
2423    AddStatisticsMsg(Form("Number of input events:        %lld",fStatistics->GetNinput()));
2424    AddStatisticsMsg(Form("Number of processed events:    %lld",fStatistics->GetNprocessed()));      
2425    AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2426    AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2427    out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2428                  fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2429                  fStatistics->GetNaccepted()), ios::out);      
2430    out << fStatisticsMsg << endl;
2431    out.close();
2432 }
2433
2434 //______________________________________________________________________________
2435 const char* AliAnalysisManager::GetOADBPath()
2436 {
2437 // returns the path of the OADB
2438 // this static function just depends on environment variables
2439
2440    static TString oadbPath;
2441
2442    if (gSystem->Getenv("OADB_PATH"))
2443       oadbPath = gSystem->Getenv("OADB_PATH");
2444    else if (gSystem->Getenv("ALICE_ROOT"))
2445       oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2446    else
2447       ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2448       
2449    return oadbPath;
2450 }
2451
2452 //______________________________________________________________________________
2453 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2454 {
2455 // Define a custom string variable mapped to a global unique name. The variable
2456 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2457    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2458    if (!mgr) {
2459       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2460       return;
2461    }   
2462    Bool_t valid = kFALSE;
2463    TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2464    if (valid) {
2465       ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2466       return;
2467    }
2468    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2469 }
2470
2471 //______________________________________________________________________________
2472 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2473 {
2474 // Static method to retrieve a global variable defined via SetGlobalStr.
2475    valid = kFALSE;
2476    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2477    if (!mgr) return 0;
2478    TObject *value = mgr->GetGlobals()->GetValue(key);
2479    if (!value) return 0;
2480    valid = kTRUE;
2481    return value->GetName();
2482 }
2483
2484 //______________________________________________________________________________
2485 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2486 {
2487 // Define a custom integer variable mapped to a global unique name. The variable
2488 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2489    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2490    if (!mgr) {
2491       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2492       return;
2493    }   
2494    Bool_t valid = kFALSE;
2495    Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2496    if (valid) {
2497       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2498       return;
2499    }
2500    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2501 }
2502
2503 //______________________________________________________________________________
2504 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2505 {
2506 // Static method to retrieve a global variable defined via SetGlobalInt.
2507    valid = kFALSE;
2508    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2509    if (!mgr) return 0;
2510    TObject *value = mgr->GetGlobals()->GetValue(key);
2511    if (!value) return 0;
2512    valid = kTRUE;
2513    TString s = value->GetName();
2514    return s.Atoi();
2515 }
2516
2517 //______________________________________________________________________________
2518 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2519 {
2520 // Define a custom double precision variable mapped to a global unique name. The variable
2521 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2522    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2523    if (!mgr) {
2524       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2525       return;
2526    }   
2527    Bool_t valid = kFALSE;
2528    Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2529    if (valid) {
2530       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2531       return;
2532    }
2533    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2534 }
2535
2536 //______________________________________________________________________________
2537 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2538 {
2539 // Static method to retrieve a global variable defined via SetGlobalDbl.
2540    valid = kFALSE;
2541    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2542    if (!mgr) return 0;
2543    TObject *value = mgr->GetGlobals()->GetValue(key);
2544    if (!value) return 0;
2545    valid = kTRUE;
2546    TString s = value->GetName();
2547    return s.Atof();
2548 }