]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Correction for the usage of kParamContainer in grid mode
[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 //   AliAnalysysManager - 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 <Riostream.h>
29
30 #include <TError.h>
31 #include <TClass.h>
32 #include <TFile.h>
33 //#include <TKey.h>
34 #include <TMath.h>
35 #include <TH1.h>
36 #include <TMethodCall.h>
37 #include <TChain.h>
38 #include <TSystem.h>
39 #include <TROOT.h>
40 #include <TCanvas.h>
41 #include <TStopwatch.h>
42
43 #include "AliAnalysisSelector.h"
44 #include "AliAnalysisGrid.h"
45 #include "AliAnalysisTask.h"
46 #include "AliAnalysisDataContainer.h"
47 #include "AliAnalysisDataSlot.h"
48 #include "AliVEventHandler.h"
49 #include "AliVEventPool.h"
50 #include "AliSysInfo.h"
51 #include "AliAnalysisManager.h"
52
53 ClassImp(AliAnalysisManager)
54
55 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
56 TString AliAnalysisManager::fgCommonFileName = "";
57
58 //______________________________________________________________________________
59 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
60                    :TNamed(name,title),
61                     fTree(NULL),
62                     fInputEventHandler(NULL),
63                     fOutputEventHandler(NULL),
64                     fMCtruthEventHandler(NULL),
65                     fEventPool(NULL),
66                     fCurrentEntry(-1),
67                     fNSysInfo(0),
68                     fMode(kLocalAnalysis),
69                     fInitOK(kFALSE),
70                     fDebug(0),
71                     fSpecialOutputLocation(""), 
72                     fTasks(NULL),
73                     fTopTasks(NULL),
74                     fZombies(NULL),
75                     fContainers(NULL),
76                     fInputs(NULL),
77                     fOutputs(NULL),
78                     fParamCont(NULL),
79                     fCommonInput(NULL),
80                     fCommonOutput(NULL),
81                     fSelector(NULL),
82                     fGridHandler(NULL),
83                     fExtraFiles("")
84 {
85 // Default constructor.
86    fgAnalysisManager = this;
87    fgCommonFileName  = "AnalysisResults.root";
88    fTasks      = new TObjArray();
89    fTopTasks   = new TObjArray();
90    fZombies    = new TObjArray();
91    fContainers = new TObjArray();
92    fInputs     = new TObjArray();
93    fOutputs    = new TObjArray();
94    fParamCont  = new TObjArray();
95    SetEventLoop(kTRUE);
96    TObject::SetObjectStat(kFALSE);
97 }
98
99 //______________________________________________________________________________
100 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
101                    :TNamed(other),
102                     fTree(NULL),
103                     fInputEventHandler(NULL),
104                     fOutputEventHandler(NULL),
105                     fMCtruthEventHandler(NULL),
106                     fEventPool(NULL),
107                     fCurrentEntry(-1),
108                     fNSysInfo(0),
109                     fMode(other.fMode),
110                     fInitOK(other.fInitOK),
111                     fDebug(other.fDebug),
112                     fSpecialOutputLocation(""), 
113                     fTasks(NULL),
114                     fTopTasks(NULL),
115                     fZombies(NULL),
116                     fContainers(NULL),
117                     fInputs(NULL),
118                     fOutputs(NULL),
119                     fParamCont(NULL),
120                     fCommonInput(NULL),
121                     fCommonOutput(NULL),
122                     fSelector(NULL),
123                     fGridHandler(NULL),
124                     fExtraFiles()
125 {
126 // Copy constructor.
127    fTasks      = new TObjArray(*other.fTasks);
128    fTopTasks   = new TObjArray(*other.fTopTasks);
129    fZombies    = new TObjArray(*other.fZombies);
130    fContainers = new TObjArray(*other.fContainers);
131    fInputs     = new TObjArray(*other.fInputs);
132    fOutputs    = new TObjArray(*other.fOutputs);
133    fParamCont  = new TObjArray(*other.fParamCont);
134    fgCommonFileName  = "AnalysisResults.root";
135    fgAnalysisManager = this;
136    TObject::SetObjectStat(kFALSE);
137 }
138    
139 //______________________________________________________________________________
140 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
141 {
142 // Assignment
143    if (&other != this) {
144       TNamed::operator=(other);
145       fInputEventHandler   = other.fInputEventHandler;
146       fOutputEventHandler  = other.fOutputEventHandler;
147       fMCtruthEventHandler = other.fMCtruthEventHandler;
148       fEventPool           = other.fEventPool;
149       fTree       = NULL;
150       fCurrentEntry = -1;
151       fNSysInfo   = other.fNSysInfo;
152       fMode       = other.fMode;
153       fInitOK     = other.fInitOK;
154       fDebug      = other.fDebug;
155       fTasks      = new TObjArray(*other.fTasks);
156       fTopTasks   = new TObjArray(*other.fTopTasks);
157       fZombies    = new TObjArray(*other.fZombies);
158       fContainers = new TObjArray(*other.fContainers);
159       fInputs     = new TObjArray(*other.fInputs);
160       fOutputs    = new TObjArray(*other.fOutputs);
161       fParamCont  = new TObjArray(*other.fParamCont);
162       fCommonInput = NULL;
163       fCommonOutput = NULL;
164       fSelector   = NULL;
165       fGridHandler = NULL;
166       fExtraFiles = other.fExtraFiles;
167       fgCommonFileName = "AnalysisResults.root";
168       fgAnalysisManager = this;
169    }
170    return *this;
171 }
172
173 //______________________________________________________________________________
174 AliAnalysisManager::~AliAnalysisManager()
175 {
176 // Destructor.
177    if (fTasks) {fTasks->Delete(); delete fTasks;}
178    if (fTopTasks) delete fTopTasks;
179    if (fZombies) delete fZombies;
180    if (fContainers) {fContainers->Delete(); delete fContainers;}
181    if (fInputs) delete fInputs;
182    if (fOutputs) delete fOutputs;
183    if (fParamCont) delete fParamCont;
184    if (fGridHandler) delete fGridHandler;
185    if (fInputEventHandler) delete fInputEventHandler;
186    if (fOutputEventHandler) delete fOutputEventHandler;
187    if (fMCtruthEventHandler) delete fMCtruthEventHandler;
188    if (fEventPool) delete fEventPool;
189    if (fgAnalysisManager==this) fgAnalysisManager = NULL;
190    TObject::SetObjectStat(kTRUE);
191 }
192
193 //______________________________________________________________________________
194 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
195 {
196 // Read one entry of the tree or a whole branch.
197    fCurrentEntry = entry;
198    return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
199 }
200    
201 //______________________________________________________________________________
202 Bool_t AliAnalysisManager::Init(TTree *tree)
203 {
204   // The Init() function is called when the selector needs to initialize
205   // a new tree or chain. Typically here the branch addresses of the tree
206   // will be set. It is normaly not necessary to make changes to the
207   // generated code, but the routine can be extended by the user if needed.
208   // Init() will be called many times when running with PROOF.
209    Bool_t init = kFALSE;
210    if (!tree) return kFALSE; // Should not happen - protected in selector caller
211    if (fDebug > 0) {
212       printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
213    }
214    // Call InitTree of EventHandler
215    if (fOutputEventHandler) {
216       if (fMode == kProofAnalysis) {
217          init = fOutputEventHandler->Init(0x0, "proof");
218       } else {
219          init = fOutputEventHandler->Init(0x0, "local");
220       }
221       if (!init) {
222          Error("Init", "Output event handler failed to initialize");
223          return kFALSE;
224       }         
225    }
226    
227    if (fInputEventHandler) {
228       if (fMode == kProofAnalysis) {
229          init = fInputEventHandler->Init(tree, "proof");
230       } else {
231          init = fInputEventHandler->Init(tree, "local");
232       }
233       if (!init) {
234          Error("Init", "Input event handler failed to initialize tree"); 
235          return kFALSE;
236       }         
237    } else {
238       // If no input event handler we need to get the tree once
239       // for the chain
240       if(!tree->GetTree()) {
241          Long64_t readEntry = tree->LoadTree(0);
242          if (readEntry == -2) {
243             Error("Init", "Input tree has no entry. Exiting");
244             return kFALSE;
245          }
246       }   
247    }
248
249    if (fMCtruthEventHandler) {
250       if (fMode == kProofAnalysis) {
251          init = fMCtruthEventHandler->Init(0x0, "proof");
252       } else {
253          init = fMCtruthEventHandler->Init(0x0, "local");
254       }
255       if (!init) {
256          Error("Init", "MC event handler failed to initialize"); 
257          return kFALSE;
258       }         
259    }
260
261    if (!fInitOK) InitAnalysis();
262    if (!fInitOK) return kFALSE;
263    fTree = tree;
264    AliAnalysisDataContainer *top = fCommonInput;
265    if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
266    if (!top) {
267       Error("Init","No top input container !");
268       return kFALSE;
269    }
270    top->SetData(tree);
271    if (fDebug > 0) {
272       printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
273    }
274    return kTRUE;
275 }
276
277 //______________________________________________________________________________
278 void AliAnalysisManager::SlaveBegin(TTree *tree)
279 {
280   // The SlaveBegin() function is called after the Begin() function.
281   // When running with PROOF SlaveBegin() is called on each slave server.
282   // The tree argument is deprecated (on PROOF 0 is passed).
283    if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
284    static Bool_t isCalled = kFALSE;
285    Bool_t init = kFALSE;
286    Bool_t initOK = kTRUE;
287    TString msg;
288    TDirectory *curdir = gDirectory;
289    // Call SlaveBegin only once in case of mixing
290    if (isCalled && fMode==kMixingAnalysis) return;
291    // Call Init of EventHandler
292    if (fOutputEventHandler) {
293       if (fMode == kProofAnalysis) {
294          // Merging AOD's in PROOF via TProofOutputFile
295          if (fDebug > 1) printf("   Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
296          init = fOutputEventHandler->Init("proof");
297          if (!init) msg = "Failed to initialize output handler on worker";
298       } else {
299          init = fOutputEventHandler->Init("local");
300          if (!init) msg = "Failed to initialize output handler";
301       }
302       initOK &= init;
303       if (!fSelector) Error("SlaveBegin", "Selector not set");
304       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
305    }
306
307    if (fInputEventHandler) {
308       fInputEventHandler->SetInputTree(tree);
309       if (fMode == kProofAnalysis) {
310          init = fInputEventHandler->Init("proof");
311          if (!init) msg = "Failed to initialize input handler on worker";
312       } else {
313          init = fInputEventHandler->Init("local");
314          if (!init) msg = "Failed to initialize input handler";
315       }
316       initOK &= init;
317       if (!fSelector) Error("SlaveBegin", "Selector not set");      
318       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
319    }
320
321    if (fMCtruthEventHandler) {
322       if (fMode == kProofAnalysis) {
323          init = fMCtruthEventHandler->Init("proof");
324          if (!init) msg = "Failed to initialize MC handler on worker";
325       } else {
326          init = fMCtruthEventHandler->Init("local");
327          if (!init) msg = "Failed to initialize MC handler";
328       }
329       initOK &= init;
330       if (!fSelector) Error("SlaveBegin", "Selector not set");      
331       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
332    }
333    if (curdir) curdir->cd();
334    isCalled = kTRUE;
335    if (!initOK) return;   
336    TIter next(fTasks);
337    AliAnalysisTask *task;
338    // Call CreateOutputObjects for all tasks
339    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
340    Int_t itask = 0;
341    while ((task=(AliAnalysisTask*)next())) {
342       curdir = gDirectory;
343       task->CreateOutputObjects();
344       if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
345       itask++;
346       if (curdir) curdir->cd();
347    }
348    if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
349 }
350
351 //______________________________________________________________________________
352 Bool_t AliAnalysisManager::Notify()
353 {
354    // The Notify() function is called when a new file is opened. This
355    // can be either for a new TTree in a TChain or when when a new TTree
356    // is started when using PROOF. It is normaly not necessary to make changes
357    // to the generated code, but the routine can be extended by the
358    // user if needed. The return value is currently not used.
359    if (!fTree) return kFALSE;
360
361    TFile *curfile = fTree->GetCurrentFile();
362    if (!curfile) {
363       Error("Notify","No current file");
364       return kFALSE;
365    }   
366    
367    if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
368    TIter next(fTasks);
369    AliAnalysisTask *task;
370    // Call Notify for all tasks
371    while ((task=(AliAnalysisTask*)next())) 
372       task->Notify();
373         
374    // Call Notify of the event handlers
375    if (fInputEventHandler) {
376        fInputEventHandler->Notify(curfile->GetName());
377    }
378
379    if (fOutputEventHandler) {
380        fOutputEventHandler->Notify(curfile->GetName());
381    }
382
383    if (fMCtruthEventHandler) {
384        fMCtruthEventHandler->Notify(curfile->GetName());
385    }
386    if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
387    return kTRUE;
388 }    
389
390 //______________________________________________________________________________
391 Bool_t AliAnalysisManager::Process(Long64_t entry)
392 {
393   // The Process() function is called for each entry in the tree (or possibly
394   // keyed object in the case of PROOF) to be processed. The entry argument
395   // specifies which entry in the currently loaded tree is to be processed.
396   // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
397   // to read either all or the required parts of the data. When processing
398   // keyed objects with PROOF, the object is already loaded and is available
399   // via the fObject pointer.
400   //
401   // This function should contain the "body" of the analysis. It can contain
402   // simple or elaborate selection criteria, run algorithms on the data
403   // of the event and typically fill histograms.
404
405   // WARNING when a selector is used with a TChain, you must use
406   //  the pointer to the current TTree to call GetEntry(entry).
407   //  The entry is always the local entry number in the current tree.
408   //  Assuming that fChain is the pointer to the TChain being processed,
409   //  use fChain->GetTree()->GetEntry(entry).
410    if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
411
412    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
413    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
414    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
415    
416    GetEntry(entry);
417    ExecAnalysis();
418    if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
419    return kTRUE;
420 }
421
422 //______________________________________________________________________________
423 void AliAnalysisManager::PackOutput(TList *target)
424 {
425   // Pack all output data containers in the output list. Called at SlaveTerminate
426   // stage in PROOF case for each slave.
427    if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
428    if (!target) {
429       Error("PackOutput", "No target. Exiting.");
430       return;
431    }
432    TDirectory *cdir = gDirectory;
433    gROOT->cd();
434    if (fInputEventHandler)   fInputEventHandler  ->Terminate();
435    if (fOutputEventHandler)  fOutputEventHandler ->Terminate();
436    if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
437    gROOT->cd();
438
439    // Call FinishTaskOutput() for each event loop task (not called for 
440    // post-event loop tasks - use Terminate() fo those)
441    TIter nexttask(fTasks);
442    AliAnalysisTask *task;
443    while ((task=(AliAnalysisTask*)nexttask())) {
444       if (!task->IsPostEventLoop()) {
445          if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
446          task->FinishTaskOutput();
447          gROOT->cd();
448          if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
449       }
450    }      
451    
452    if (fMode == kProofAnalysis) {
453       TIter next(fOutputs);
454       AliAnalysisDataContainer *output;
455       Bool_t isManagedByHandler = kFALSE;
456       while ((output=(AliAnalysisDataContainer*)next())) {
457          // Do not consider outputs of post event loop tasks
458          isManagedByHandler = kFALSE;
459          if (output->GetProducer()->IsPostEventLoop()) continue;
460          const char *filename = output->GetFileName();
461          if (!(strcmp(filename, "default")) && fOutputEventHandler) {
462             isManagedByHandler = kTRUE;
463             printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
464             filename = fOutputEventHandler->GetOutputFileName();
465          }
466          // Check if data was posted to this container. If not, issue an error.
467          if (!output->GetData() && !isManagedByHandler) {
468             Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
469             continue;
470          }   
471          if (!output->IsSpecialOutput()) {
472             // Normal outputs
473             if (strlen(filename) && !isManagedByHandler) {
474                // Backup current folder
475                TDirectory *opwd = gDirectory;
476                // File resident outputs. 
477                // Check first if the file exists.
478                TString openoption = "RECREATE";
479                if (!gSystem->AccessPathName(output->GetFileName())) openoption = "UPDATE";
480                TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
481                // Save data to file, then close.
482                if (output->GetData()->InheritsFrom(TCollection::Class())) {
483                   // If data is a collection, we set the name of the collection 
484                   // as the one of the container and we save as a single key.
485                   TCollection *coll = (TCollection*)output->GetData();
486                   coll->SetName(output->GetName());
487                   coll->Write(output->GetName(), TObject::kSingleKey);
488                } else {
489                   if (output->GetData()->InheritsFrom(TTree::Class())) {
490                      TTree *tree = (TTree*)output->GetData();
491                      // Check if tree is in memory
492                      if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
493                      tree->AutoSave();
494                   } else {
495                      output->GetData()->Write();
496                   }   
497                }      
498                if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
499                if (fDebug > 2) {
500                   printf("   file %s listing content:\n", filename);
501                   file->ls();
502                }   
503                // Clear file list to release object ownership to user.
504 //               file->Clear();
505                file->Close();
506                output->SetFile(NULL);
507                // Restore current directory
508                if (opwd) opwd->cd();
509             } else {
510                // Memory-resident outputs   
511                if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
512             }   
513             AliAnalysisDataWrapper *wrap = 0;
514             if (isManagedByHandler) {
515                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
516                wrap->SetName(output->GetName());
517             }   
518             else                    wrap =output->ExportData();
519             // Output wrappers must NOT delete data after merging - the user owns them
520             wrap->SetDeleteData(kFALSE);
521             target->Add(wrap);
522          } else {
523          // Special outputs. The file must be opened and connected to the container.
524             TDirectory *opwd = gDirectory;
525             TFile *file = output->GetFile();
526             if (!file) {
527                AliAnalysisTask *producer = output->GetProducer();
528                Fatal("PackOutput", 
529                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
530                      output->GetFileName(), output->GetName(), producer->ClassName());
531                continue;
532             }   
533             TString outFilename = file->GetName();
534             if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
535             if (isManagedByHandler) {
536                // Terminate IO for files managed by the output handler
537                // file->Write() moved to AOD handler (A.G. 11.01.10)
538 //               if (file) file->Write();
539                if (file && fDebug > 2) {
540                   printf("   handled file %s listing content:\n", file->GetName());
541                   file->ls();
542                }   
543                fOutputEventHandler->TerminateIO();
544             } else {               
545                file->cd();
546                // Release object ownership to users after writing data to file
547                if (output->GetData()->InheritsFrom(TCollection::Class())) {
548                   // If data is a collection, we set the name of the collection 
549                   // as the one of the container and we save as a single key.
550                   TCollection *coll = (TCollection*)output->GetData();
551                   coll->SetName(output->GetName());
552                   coll->Write(output->GetName(), TObject::kSingleKey);
553                } else {
554                   if (output->GetData()->InheritsFrom(TTree::Class())) {
555                      TTree *tree = (TTree*)output->GetData();
556                      tree->SetDirectory(file);
557                      tree->AutoSave();
558                   } else {
559                      output->GetData()->Write();
560                   }   
561                }      
562                if (fDebug > 2) {
563                   printf("   file %s listing content:\n", output->GetFileName());
564                   file->ls();
565                }
566                // Clear file list to release object ownership to user.
567 //               file->Clear();
568                file->Close();
569                output->SetFile(NULL);
570             }
571             // Restore current directory
572             if (opwd) opwd->cd();
573             // Check if a special output location was provided or the output files have to be merged
574             if (strlen(fSpecialOutputLocation.Data())) {
575                TString remote = fSpecialOutputLocation;
576                remote += "/";
577                Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
578                if (remote.BeginsWith("alien://")) {
579                   gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
580                   remote += outFilename;
581                   remote.ReplaceAll(".root", Form("_%d.root", gid));
582                } else {   
583                   remote += Form("%s_%d_", gSystem->HostName(), gid);
584                   remote += outFilename;
585                }   
586                if (fDebug > 1) 
587                   Info("PackOutput", "Output file for container %s to be copied \n   at: %s. No merging.",
588                        output->GetName(), remote.Data());
589                TFile::Cp ( outFilename.Data(), remote.Data() );
590                // Copy extra outputs
591                if (fExtraFiles.Length() && isManagedByHandler) {
592                   TObjArray *arr = fExtraFiles.Tokenize(" ");
593                   TObjString *os;
594                   TIter nextfilename(arr);
595                   while ((os=(TObjString*)nextfilename())) {
596                      outFilename = os->GetString();
597                      remote = fSpecialOutputLocation;
598                      remote += "/";
599                      if (remote.BeginsWith("alien://")) {
600                         remote += outFilename;
601                         remote.ReplaceAll(".root", Form("_%d.root", gid));
602                      } else {   
603                         remote += Form("%s_%d_", gSystem->HostName(), gid);
604                         remote += outFilename;
605                      }   
606                      if (fDebug > 1) 
607                         Info("PackOutput", "Extra AOD file %s to be copied \n   at: %s. No merging.",
608                              outFilename.Data(), remote.Data());
609                      TFile::Cp ( outFilename.Data(), remote.Data() );
610                   }   
611                   delete arr;
612                }   
613             } else {
614             // No special location specified-> use TProofOutputFile as merging utility
615             // The file at this output slot must be opened in CreateOutputObjects
616                if (fDebug > 1) printf("   File for container %s to be merged via file merger...\n", output->GetName());
617             }
618          }      
619       }
620    } 
621    cdir->cd();
622    if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
623 }
624
625 //______________________________________________________________________________
626 void AliAnalysisManager::ImportWrappers(TList *source)
627 {
628 // Import data in output containers from wrappers coming in source.
629    if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
630    TIter next(fOutputs);
631    AliAnalysisDataContainer *cont;
632    AliAnalysisDataWrapper   *wrap;
633    Int_t icont = 0;
634    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
635    TDirectory *cdir = gDirectory;
636    while ((cont=(AliAnalysisDataContainer*)next())) {
637       wrap = 0;
638       if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
639       if (cont->IsRegisterDataset()) continue;
640       const char *filename = cont->GetFileName();
641       Bool_t isManagedByHandler = kFALSE;
642       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
643          isManagedByHandler = kTRUE;
644          filename = fOutputEventHandler->GetOutputFileName();
645       }
646       if (cont->IsSpecialOutput() || inGrid) {
647          if (strlen(fSpecialOutputLocation.Data())) continue;
648          // Copy merged file from PROOF scratch space. 
649          // In case of grid the files are already in the current directory.
650          if (!inGrid) {
651             if (isManagedByHandler && fExtraFiles.Length()) {
652                // Copy extra registered dAOD files.
653                TObjArray *arr = fExtraFiles.Tokenize(" ");
654                TObjString *os;
655                TIter nextfilename(arr);
656                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
657                delete arr;
658             }
659             if (!GetFileFromWrapper(filename, source)) continue;
660          }   
661          // Normally we should connect data from the copied file to the
662          // corresponding output container, but it is not obvious how to do this
663          // automatically if several objects in file...
664          TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
665          if (!f) f = TFile::Open(filename, "READ");
666          if (!f) {
667             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
668             continue;
669          }   
670          TObject *obj = 0;
671          // Cd to the directory pointed by the container
672          TString folder = cont->GetFolderName();
673          if (!folder.IsNull()) f->cd(folder);
674          // Try to fetch first an object having the container name.
675          obj = gDirectory->Get(cont->GetName());
676          if (!obj) {
677             Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()", 
678                     cont->GetName(), filename, cont->GetFolderName());
679             continue;
680          }  
681          wrap = new AliAnalysisDataWrapper(obj);
682          wrap->SetDeleteData(kFALSE);
683       }   
684       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
685       if (!wrap) {
686          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
687          continue;
688       }
689       icont++;
690       if (fDebug > 1) {
691          printf("   Importing data for container %s\n", cont->GetName());
692          if (strlen(filename)) printf("    -> file %s\n", filename);
693          else printf("\n");
694       }   
695       cont->ImportData(wrap);
696    }
697    if (cdir) cdir->cd();
698    if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
699 }
700
701 //______________________________________________________________________________
702 void AliAnalysisManager::UnpackOutput(TList *source)
703 {
704   // Called by AliAnalysisSelector::Terminate only on the client.
705    if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
706    if (!source) {
707       Error("UnpackOutput", "No target. Exiting.");
708       return;
709    }
710    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
711
712    if (fMode == kProofAnalysis) ImportWrappers(source);
713
714    TIter next(fOutputs);
715    AliAnalysisDataContainer *output;
716    while ((output=(AliAnalysisDataContainer*)next())) {
717       if (!output->GetData()) continue;
718       // Check if there are client tasks that run post event loop
719       if (output->HasConsumers()) {
720          // Disable event loop semaphore
721          output->SetPostEventLoop(kTRUE);
722          TObjArray *list = output->GetConsumers();
723          Int_t ncons = list->GetEntriesFast();
724          for (Int_t i=0; i<ncons; i++) {
725             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
726             task->CheckNotify(kTRUE);
727             // If task is active, execute it
728             if (task->IsPostEventLoop() && task->IsActive()) {
729                if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
730                task->ExecuteTask();
731             }   
732          }
733       }   
734    }
735    if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
736 }
737
738 //______________________________________________________________________________
739 void AliAnalysisManager::Terminate()
740 {
741   // The Terminate() function is the last function to be called during
742   // a query. It always runs on the client, it can be used to present
743   // the results graphically.
744    if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
745    TDirectory *cdir = gDirectory;
746    gROOT->cd();
747    AliAnalysisTask *task;
748    AliAnalysisDataContainer *output;
749    TIter next(fTasks);
750    TStopwatch timer;
751    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
752    // Call Terminate() for tasks
753    Int_t itask = 0;
754    while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
755       // Save all the canvases produced by the Terminate
756       TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
757       task->Terminate();
758       gROOT->cd();
759       if (getsysInfo) 
760          AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
761       itask++;   
762       if (TObject::TestBit(kSaveCanvases)) {
763          if (!gROOT->IsBatch()) {
764             if (fDebug>0) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...", task->ClassName());
765             timer.Start();
766             while (timer.CpuTime()<5) {
767                timer.Continue();
768                gSystem->ProcessEvents();
769             }
770          }
771          Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
772          if (iend==0) continue;
773          TCanvas *canvas;
774          for (Int_t ipict=0; ipict<iend; ipict++) {
775             canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
776             if (!canvas) continue;         
777             canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
778          } 
779          gROOT->GetListOfCanvases()->Delete(); 
780       }
781    }   
782    //
783    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
784    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
785    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
786    gROOT->cd();
787    TObjArray *allOutputs = new TObjArray();
788    Int_t icont;
789    for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
790    if (!IsSkipTerminate())
791       for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
792    TIter next1(allOutputs);
793    TString handlerFile = "";
794    if (fOutputEventHandler) {
795       handlerFile = fOutputEventHandler->GetOutputFileName();
796    }
797    icont = 0;
798    while ((output=(AliAnalysisDataContainer*)next1())) {
799       // Special outputs or grid files have the files already closed and written.
800       icont++;
801       if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
802       if (fMode == kProofAnalysis) {
803         if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
804       }  
805       const char *filename = output->GetFileName();
806       TString openoption = "RECREATE";
807       if (!(strcmp(filename, "default"))) continue;
808       if (!strlen(filename)) continue;
809       if (!output->GetData()) continue;
810       TDirectory *opwd = gDirectory;
811       TFile *file = output->GetFile();
812       if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
813       if (!file) {
814               //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
815          if (!gSystem->AccessPathName(filename)) openoption = "UPDATE";
816               if (fDebug>0) printf("Opening file: %s  option=%s\n",filename, openoption.Data());
817          file = new TFile(filename, openoption);
818       } else {
819          if (fDebug>0) printf("File already opened: %s\n", filename);
820       }   
821       if (file->IsZombie()) {
822          Error("Terminate", "Cannot open output file %s", filename);
823          continue;
824       }   
825       output->SetFile(file);
826       file->cd();
827       // Check for a folder request
828       TString dir = output->GetFolderName();
829       if (!dir.IsNull()) {
830          if (!file->GetDirectory(dir)) file->mkdir(dir);
831          file->cd(dir);
832       }  
833       if (fDebug > 0) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
834       if (output->GetData()->InheritsFrom(TCollection::Class())) {
835       // If data is a collection, we set the name of the collection 
836       // as the one of the container and we save as a single key.
837          TCollection *coll = (TCollection*)output->GetData();
838          coll->SetName(output->GetName());
839          coll->Write(output->GetName(), TObject::kSingleKey);
840       } else {
841          if (output->GetData()->InheritsFrom(TTree::Class())) {
842             TTree *tree = (TTree*)output->GetData();
843             tree->SetDirectory(gDirectory);
844             tree->AutoSave();
845          } else {
846             output->GetData()->Write();
847          }   
848       }      
849       if (opwd) opwd->cd();
850    }
851    gROOT->cd();
852    next1.Reset();
853    while ((output=(AliAnalysisDataContainer*)next1())) {
854       // Close all files at output
855       TDirectory *opwd = gDirectory;
856       if (output->GetFile()) {
857          // Clear file list to release object ownership to user.
858 //         output->GetFile()->Clear();
859          output->GetFile()->Close();
860          output->SetFile(NULL);
861          // Copy merged outputs in alien if requested
862          if (fSpecialOutputLocation.Length() && 
863              fSpecialOutputLocation.BeginsWith("alien://")) {
864             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
865             TFile::Cp(output->GetFile()->GetName(), 
866                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
867          }             
868       }   
869       if (opwd) opwd->cd();
870    }   
871    delete allOutputs;
872
873    if (getsysInfo) {
874       TDirectory *crtdir = gDirectory;
875       TFile f("syswatch.root", "RECREATE");
876       TH1 *hist;
877       TString cut;
878       if (!f.IsZombie()) {
879          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
880          tree->SetName("syswatch");
881          tree->SetMarkerStyle(kCircle);
882          tree->SetMarkerColor(kBlue);
883          tree->SetMarkerSize(0.5);
884          if (!gROOT->IsBatch()) {
885             tree->SetAlias("event", "id0");
886             tree->SetAlias("task",  "id1");
887             tree->SetAlias("stage", "id2");
888             // Already defined aliases
889             // tree->SetAlias("deltaT","stampSec-stampOldSec");
890             // tree->SetAlias("T","stampSec-first");
891             // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
892             // tree->SetAlias("VM","pI.fMemVirtual");
893             TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
894             Int_t npads = 1 /*COO plot for all tasks*/ +
895                           fTopTasks->GetEntries() /*Exec plot per task*/ +
896                           1 /*Terminate plot for all tasks*/ +
897                           1; /*vm plot*/
898                           
899             Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
900             if (npads<iopt*(iopt+1))
901                canvas->Divide(iopt, iopt+1, 0.01, 0.01);
902             else
903                canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
904             Int_t ipad = 1;
905             // draw the plot of deltaVM for Exec for each task
906             for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
907                task = (AliAnalysisTask*)fTopTasks->At(itask);
908                canvas->cd(ipad++);
909                cut = Form("task==%d && stage==1", itask);
910                tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
911                hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
912                if (hist) {
913                   hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
914                   hist->GetYaxis()->SetTitle("deltaVM [kB]");
915                }   
916             }
917             // Draw the plot of deltaVM for CreateOutputObjects for all tasks
918             canvas->cd(ipad++);
919             tree->SetMarkerStyle(kFullTriangleUp);
920             tree->SetMarkerColor(kRed);
921             tree->SetMarkerSize(0.8);
922             cut = "task>=0 && task<1000 && stage==0";
923             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
924             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
925             if (hist) {
926                hist->SetTitle("Memory in CreateOutputObjects()");
927                hist->GetYaxis()->SetTitle("deltaVM [kB]");
928                hist->GetXaxis()->SetTitle("task");
929             }   
930             // draw the plot of deltaVM for Terminate for all tasks
931             canvas->cd(ipad++);
932             tree->SetMarkerStyle(kOpenSquare);
933             tree->SetMarkerColor(kMagenta);
934             cut = "task>=0 && task<1000 && stage==2";
935             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
936             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
937             if (hist) {
938                hist->SetTitle("Memory in Terminate()");
939                hist->GetYaxis()->SetTitle("deltaVM [kB]");
940                hist->GetXaxis()->SetTitle("task");
941             }   
942             // Full VM profile
943             canvas->cd(ipad++);
944             tree->SetMarkerStyle(kFullCircle);
945             tree->SetMarkerColor(kGreen);
946             cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);            
947             tree->Draw("VM:event",cut,"", 1234567890, 0);
948             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
949             if (hist) {
950                hist->SetTitle("Virtual memory");
951                hist->GetYaxis()->SetTitle("VM [kB]");
952             }
953             canvas->Modified();   
954          }   
955          tree->SetMarkerStyle(kCircle);
956          tree->SetMarkerColor(kBlue);
957          tree->SetMarkerSize(0.5);
958          tree->Write();
959          f.Close();
960          delete tree;
961       }
962       if (crtdir) crtdir->cd();
963    }
964    // Validate the output files
965    if (ValidateOutputFiles()) {
966       ofstream out;
967       out.open("outputs_valid", ios::out);
968       out.close();
969    }
970    cdir->cd();      
971    if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
972 }
973 //______________________________________________________________________________
974 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
975 {
976 // Profiles the task having the itop index in the list of top (first level) tasks.
977    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
978    if (!task) {
979       Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
980       return;
981    }
982    ProfileTask(task->GetName(), option);
983 }      
984
985 //______________________________________________________________________________
986 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
987 {
988 // Profile a managed task after the execution of the analysis in case NSysInfo
989 // was used.
990    if (gSystem->AccessPathName("syswatch.root")) {
991       Error("ProfileTask", "No file syswatch.root found in the current directory");
992       return;
993    }
994    if (gROOT->IsBatch()) return;
995    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
996    if (!task) {
997       Error("ProfileTask", "No top task named %s known by the manager.", name);
998       return;
999    }
1000    Int_t itop = fTopTasks->IndexOf(task);
1001    Int_t itask = fTasks->IndexOf(task);
1002    // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1003    TDirectory *cdir = gDirectory;
1004    TFile f("syswatch.root");
1005    TTree *tree = (TTree*)f.Get("syswatch");
1006    if (!tree) {
1007       Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1008       return;
1009    }   
1010    if (fDebug > 0) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1011    TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1012    canvas->Divide(2, 2, 0.01, 0.01);
1013    Int_t ipad = 1;
1014    TString cut;
1015    TH1 *hist;
1016    // VM profile for COO and Terminate methods
1017    canvas->cd(ipad++);
1018    cut = Form("task==%d && (stage==0 || stage==2)",itask);
1019    tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1020    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1021    if (hist) {
1022       hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1023       hist->GetYaxis()->SetTitle("deltaVM [kB]");
1024       hist->GetXaxis()->SetTitle("method");
1025    }   
1026    // CPU profile per event
1027    canvas->cd(ipad++);
1028    cut = Form("task==%d && stage==1",itop);
1029    tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1030    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1031    if (hist) {
1032       hist->SetTitle("Execution time per event");
1033       hist->GetYaxis()->SetTitle("CPU/event [s]");
1034    }   
1035    // VM profile for Exec
1036    canvas->cd(ipad++);
1037    cut = Form("task==%d && stage==1",itop);
1038    tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1039    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1040    if (hist) {
1041       hist->SetTitle("Alocated VM[kB] per event");
1042       hist->GetYaxis()->SetTitle("deltaVM [kB]");
1043    }   
1044    canvas->Modified();
1045    delete tree;
1046    f.Close();
1047    if (cdir) cdir->cd();
1048 }     
1049
1050 //______________________________________________________________________________
1051 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1052 {
1053 // Adds a user task to the global list of tasks.
1054    if (fTasks->FindObject(task)) {
1055       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1056       return;
1057    }   
1058    task->SetActive(kFALSE);
1059    fTasks->Add(task);
1060 }  
1061
1062 //______________________________________________________________________________
1063 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1064 {
1065 // Retreive task by name.
1066    if (!fTasks) return NULL;
1067    return (AliAnalysisTask*)fTasks->FindObject(name);
1068 }
1069
1070 //______________________________________________________________________________
1071 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
1072                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
1073 {
1074 // Create a data container of a certain type. Types can be:
1075 //   kExchangeContainer  = 0, used to exchange data between tasks
1076 //   kInputContainer   = 1, used to store input data
1077 //   kOutputContainer  = 2, used for writing result to a file
1078 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1079 // the output object to a folder inside the output file
1080    if (fContainers->FindObject(name)) {
1081       Error("CreateContainer","A container named %s already defined !",name);
1082       return NULL;
1083    }   
1084    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1085    fContainers->Add(cont);
1086    switch (type) {
1087       case kInputContainer:
1088          fInputs->Add(cont);
1089          break;
1090       case kOutputContainer:
1091          fOutputs->Add(cont);
1092          if (filename && strlen(filename)) {
1093             cont->SetFileName(filename);
1094             cont->SetDataOwned(kFALSE);  // data owned by the file
1095          }   
1096          break;
1097       case kParamContainer:
1098          fParamCont->Add(cont);
1099          if (filename && strlen(filename)) {
1100             cont->SetFileName(filename);
1101             cont->SetDataOwned(kFALSE);  // data owned by the file
1102          }   
1103          break;
1104       case kExchangeContainer:
1105          break;   
1106    }
1107    return cont;
1108 }
1109          
1110 //______________________________________________________________________________
1111 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1112                                         AliAnalysisDataContainer *cont)
1113 {
1114 // Connect input of an existing task to a data container.
1115    if (!task) {
1116       Error("ConnectInput", "Task pointer is NULL");
1117       return kFALSE;
1118    }   
1119    if (!fTasks->FindObject(task)) {
1120       AddTask(task);
1121       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1122    } 
1123    Bool_t connected = task->ConnectInput(islot, cont);
1124    return connected;
1125 }   
1126
1127 //______________________________________________________________________________
1128 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1129                                         AliAnalysisDataContainer *cont)
1130 {
1131 // Connect output of an existing task to a data container.
1132    if (!task) {
1133       Error("ConnectOutput", "Task pointer is NULL");
1134       return kFALSE;
1135    }   
1136    if (!fTasks->FindObject(task)) {
1137       AddTask(task);
1138       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1139    } 
1140    Bool_t connected = task->ConnectOutput(islot, cont);
1141    return connected;
1142 }   
1143                                
1144 //______________________________________________________________________________
1145 void AliAnalysisManager::CleanContainers()
1146 {
1147 // Clean data from all containers that have already finished all client tasks.
1148    TIter next(fContainers);
1149    AliAnalysisDataContainer *cont;
1150    while ((cont=(AliAnalysisDataContainer *)next())) {
1151       if (cont->IsOwnedData() && 
1152           cont->IsDataReady() && 
1153           cont->ClientsExecuted()) cont->DeleteData();
1154    }
1155 }
1156
1157 //______________________________________________________________________________
1158 Bool_t AliAnalysisManager::InitAnalysis()
1159 {
1160 // Initialization of analysis chain of tasks. Should be called after all tasks
1161 // and data containers are properly connected
1162    // Reset flag and remove valid_outputs file if exists
1163    fInitOK = kFALSE;
1164    if (!gSystem->AccessPathName("outputs_valid"))
1165       gSystem->Unlink("outputs_valid");
1166    // Check for top tasks (depending only on input data containers)
1167    if (!fTasks->First()) {
1168       Error("InitAnalysis", "Analysis has no tasks !");
1169       return kFALSE;
1170    }   
1171    TIter next(fTasks);
1172    AliAnalysisTask *task;
1173    AliAnalysisDataContainer *cont;
1174    Int_t ntop = 0;
1175    Int_t nzombies = 0;
1176    Bool_t iszombie = kFALSE;
1177    Bool_t istop = kTRUE;
1178    Int_t i;
1179    while ((task=(AliAnalysisTask*)next())) {
1180       istop = kTRUE;
1181       iszombie = kFALSE;
1182       Int_t ninputs = task->GetNinputs();
1183       for (i=0; i<ninputs; i++) {
1184          cont = task->GetInputSlot(i)->GetContainer();
1185          if (!cont) {
1186             if (!iszombie) {
1187                task->SetZombie();
1188                fZombies->Add(task);
1189                nzombies++;
1190                iszombie = kTRUE;
1191             }   
1192             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
1193                   i, task->GetName()); 
1194          }
1195          if (iszombie) continue;
1196          // Check if cont is an input container
1197          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1198          // Connect to parent task
1199       }
1200       if (istop) {
1201          ntop++;
1202          fTopTasks->Add(task);
1203       }
1204    }
1205    if (!ntop) {
1206       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1207       return kFALSE;
1208    }                        
1209    // Check now if there are orphan tasks
1210    for (i=0; i<ntop; i++) {
1211       task = (AliAnalysisTask*)fTopTasks->At(i);
1212       task->SetUsed();
1213    }
1214    Int_t norphans = 0;
1215    next.Reset();
1216    while ((task=(AliAnalysisTask*)next())) {
1217       if (!task->IsUsed()) {
1218          norphans++;
1219          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1220       }   
1221    }          
1222    // Check the task hierarchy (no parent task should depend on data provided
1223    // by a daughter task)
1224    for (i=0; i<ntop; i++) {
1225       task = (AliAnalysisTask*)fTopTasks->At(i);
1226       if (task->CheckCircularDeps()) {
1227          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1228          PrintStatus("dep");
1229          return kFALSE;
1230       }   
1231    }
1232    // Check that all containers feeding post-event loop tasks are in the outputs list
1233    TIter nextcont(fContainers); // loop over all containers
1234    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1235       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1236          if (cont->HasConsumers()) {
1237          // Check if one of the consumers is post event loop
1238             TIter nextconsumer(cont->GetConsumers());
1239             while ((task=(AliAnalysisTask*)nextconsumer())) {
1240                if (task->IsPostEventLoop()) {
1241                   fOutputs->Add(cont);
1242                   break;
1243                }
1244             }
1245          }
1246       }
1247    }   
1248    // Check if all special output containers have a file name provided
1249    TIter nextout(fOutputs);
1250    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1251       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1252          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1253          return kFALSE;
1254       }
1255    }      
1256    fInitOK = kTRUE;
1257    return kTRUE;
1258 }   
1259
1260 //______________________________________________________________________________
1261 void AliAnalysisManager::PrintStatus(Option_t *option) const
1262 {
1263 // Print task hierarchy.
1264    if (!fInitOK) {
1265       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1266       return;
1267    }   
1268    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1269    if (getsysInfo)
1270       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1271    TIter next(fTopTasks);
1272    AliAnalysisTask *task;
1273    while ((task=(AliAnalysisTask*)next()))
1274       task->PrintTask(option);
1275 }
1276
1277 //______________________________________________________________________________
1278 void AliAnalysisManager::ResetAnalysis()
1279 {
1280 // Reset all execution flags and clean containers.
1281    CleanContainers();
1282 }
1283
1284 //______________________________________________________________________________
1285 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1286 {
1287 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1288 // MIX. Process nentries starting from firstentry
1289    Long64_t retv = 0;
1290    // Backup current directory and make sure gDirectory points to gROOT
1291    TDirectory *cdir = gDirectory;
1292    gROOT->cd();
1293    if (!fInitOK) {
1294       Error("StartAnalysis","Analysis manager was not initialized !");
1295       cdir->cd();
1296       return -1;
1297    }
1298    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1299    TString anaType = type;
1300    anaType.ToLower();
1301    fMode = kLocalAnalysis;
1302    Bool_t runlocalinit = kTRUE;
1303    if (anaType.Contains("file")) {
1304       runlocalinit = kFALSE;
1305    }   
1306    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1307    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1308    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1309
1310    if (fMode == kGridAnalysis) {
1311       if (!anaType.Contains("terminate")) {
1312          if (!fGridHandler) {
1313             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1314             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1315             cdir->cd();
1316             return -1;
1317          }
1318          // Write analysis manager in the analysis file
1319          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1320          // run local task configuration
1321          TIter nextTask(fTasks);
1322          AliAnalysisTask *task;
1323          while ((task=(AliAnalysisTask*)nextTask())) {
1324             task->LocalInit();
1325             gROOT->cd();
1326          }
1327          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1328             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1329             cdir->cd();
1330             return -1;
1331          }   
1332
1333          // Terminate grid analysis
1334          if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1335          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1336          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1337          if (!fGridHandler->MergeOutputs()) {
1338             // Return if outputs could not be merged or if it alien handler
1339             // was configured for offline mode or local testing.
1340             cdir->cd();
1341             return 0;
1342          }
1343       }   
1344       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1345       ImportWrappers(NULL);
1346       Terminate();
1347       cdir->cd();
1348       return 0;
1349    }
1350    char line[256];
1351    SetEventLoop(kFALSE);
1352    // Enable event loop mode if a tree was provided
1353    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1354
1355    TChain *chain = 0;
1356    TString ttype = "TTree";
1357    if (tree && tree->IsA() == TChain::Class()) {
1358       chain = (TChain*)tree;
1359       if (!chain || !chain->GetListOfFiles()->First()) {
1360          Error("StartAnalysis", "Cannot process null or empty chain...");
1361          cdir->cd();
1362          return -1;
1363       }   
1364       ttype = "TChain";
1365    }   
1366
1367    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1368    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1369    // Initialize locally all tasks (happens for all modes)
1370    TIter next(fTasks);
1371    AliAnalysisTask *task;
1372    if (runlocalinit) {
1373       while ((task=(AliAnalysisTask*)next())) {
1374          task->LocalInit();
1375          gROOT->cd();
1376       }
1377       if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1378    }   
1379    
1380    switch (fMode) {
1381       case kLocalAnalysis:
1382          if (!tree) {
1383             TIter nextT(fTasks);
1384             // Call CreateOutputObjects for all tasks
1385             Int_t itask = 0;
1386             while ((task=(AliAnalysisTask*)nextT())) {
1387                task->CreateOutputObjects();
1388                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1389                gROOT->cd();
1390                itask++;
1391             }   
1392             if (IsExternalLoop()) {
1393                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1394                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1395                return 0;
1396             }
1397             ExecAnalysis();
1398             Terminate();
1399             return 0;
1400          } 
1401          // Run tree-based analysis via AliAnalysisSelector  
1402          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1403          fSelector = new AliAnalysisSelector(this);
1404          retv = tree->Process(fSelector, "", nentries, firstentry);
1405          break;
1406       case kProofAnalysis:
1407          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1408             Error("StartAnalysis", "No PROOF!!! Exiting.");
1409             cdir->cd();
1410             return -1;
1411          }   
1412          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1413          gROOT->ProcessLine(line);
1414          if (chain) {
1415             chain->SetProof();
1416             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1417             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1418          } else {
1419             Error("StartAnalysis", "No chain!!! Exiting.");
1420             cdir->cd();
1421             return -1;
1422          }      
1423          break;
1424       case kGridAnalysis:
1425          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1426          break;
1427       case kMixingAnalysis:   
1428          // Run event mixing analysis
1429          if (!fEventPool) {
1430             Error("StartAnalysis", "Cannot run event mixing without event pool");
1431             cdir->cd();
1432             return -1;
1433          }
1434          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1435          fSelector = new AliAnalysisSelector(this);
1436          while ((chain=fEventPool->GetNextChain())) {
1437             next.Reset();
1438             // Call NotifyBinChange for all tasks
1439             while ((task=(AliAnalysisTask*)next()))
1440                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1441             retv = chain->Process(fSelector);
1442             if (retv < 0) {
1443                Error("StartAnalysis", "Mixing analysis failed");
1444                cdir->cd();
1445                return retv;
1446             }   
1447          }
1448          PackOutput(fSelector->GetOutputList());
1449          Terminate();
1450    }
1451    cdir->cd();
1452    return retv;
1453 }   
1454
1455 //______________________________________________________________________________
1456 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1457 {
1458 // Start analysis for this manager on a given dataset. Analysis task can be: 
1459 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1460    if (!fInitOK) {
1461       Error("StartAnalysis","Analysis manager was not initialized !");
1462       return -1;
1463    }
1464    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1465    TString anaType = type;
1466    anaType.ToLower();
1467    if (!anaType.Contains("proof")) {
1468       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1469       return -1;
1470    }   
1471    fMode = kProofAnalysis;
1472    char line[256];
1473    SetEventLoop(kTRUE);
1474    // Set the dataset flag
1475    TObject::SetBit(kUseDataSet);
1476    fTree = 0;
1477
1478    // Initialize locally all tasks
1479    TIter next(fTasks);
1480    AliAnalysisTask *task;
1481    while ((task=(AliAnalysisTask*)next())) {
1482       task->LocalInit();
1483    }
1484    
1485    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1486       Error("StartAnalysis", "No PROOF!!! Exiting.");
1487       return -1;
1488    }   
1489    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1490    gROOT->ProcessLine(line);
1491    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1492    if (!gROOT->ProcessLine(line)) {
1493       Error("StartAnalysis", "Dataset %s not found", dataset);
1494       return -1;
1495    }   
1496    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1497            dataset, nentries, firstentry);
1498    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1499    Long_t retv = (Long_t)gROOT->ProcessLine(line);
1500    return retv;
1501 }   
1502
1503 //______________________________________________________________________________
1504 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1505 {
1506 // Opens according the option the file specified by cont->GetFileName() and changes
1507 // current directory to cont->GetFolderName(). If the file was already opened, it
1508 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1509 // be optionally ignored.
1510   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1511   TString filename = cont->GetFileName();
1512   TFile *f = NULL;
1513   if (filename.IsNull()) {
1514     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1515     return NULL;
1516   }
1517   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1518       && !ignoreProof)
1519     f = mgr->OpenProofFile(cont,option);
1520   else {
1521     // Check first if the file is already opened
1522     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1523     if (f) {
1524       // Check if option "UPDATE" was preserved 
1525       TString opt(option);
1526       opt.ToUpper();
1527       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1528         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1529     } else {
1530       f = TFile::Open(filename, option);
1531     }    
1532   }   
1533   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1534     cont->SetFile(f);
1535     // Cd to file
1536     f->cd();
1537     // Check for a folder request
1538     TString dir = cont->GetFolderName(); 
1539     if (!dir.IsNull()) {
1540       if (!f->GetDirectory(dir)) f->mkdir(dir);
1541       f->cd(dir);
1542     }
1543     return f;
1544   }
1545   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1546   cont->SetFile(NULL);
1547   return NULL;
1548 }    
1549  
1550 //______________________________________________________________________________
1551 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
1552 {
1553 // Opens a special output file used in PROOF.
1554   TString line;
1555   TString filename = cont->GetFileName();
1556   if (cont == fCommonOutput) {
1557      if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1558      else Fatal("OpenProofFile","No output container. Exiting.");
1559   }   
1560   TFile *f = NULL;
1561   if (fMode!=kProofAnalysis || !fSelector) {
1562     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1563     return NULL;
1564   } 
1565   if (fSpecialOutputLocation.Length()) {
1566     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1567     if (f) {
1568       // Check if option "UPDATE" was preserved 
1569       TString opt(option);
1570       opt.ToUpper();
1571       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1572         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1573     } else {
1574       f = new TFile(filename, option);
1575     }
1576     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1577       cont->SetFile(f);
1578       // Cd to file
1579       f->cd();
1580       // Check for a folder request
1581       TString dir = cont->GetFolderName(); 
1582       if (dir.Length()) {
1583         if (!f->GetDirectory(dir)) f->mkdir(dir);
1584         f->cd(dir);
1585       }      
1586       return f;
1587     }
1588     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1589     cont->SetFile(NULL);
1590     return NULL;       
1591   }
1592   // Check if there is already a proof output file in the output list
1593   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1594   if (pof) {
1595     // Get the actual file
1596     line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1597     filename = (const char*)gROOT->ProcessLine(line);
1598     if (fDebug>1) {
1599       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1600     }  
1601     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1602     if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1603     // Check if option "UPDATE" was preserved 
1604     TString opt(option);
1605     opt.ToUpper();
1606     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1607       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1608   } else {
1609     if (cont->IsRegisterDataset()) {
1610       TString dsetName = filename;
1611       dsetName.ReplaceAll(".root", cont->GetTitle());
1612       dsetName.ReplaceAll(":","_");
1613       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1614       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1615     } else {
1616       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1617       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1618     }
1619     if (fDebug > 1) printf("=== %s\n", line.Data());
1620     gROOT->ProcessLine(line);
1621     line = Form("pf->OpenFile(\"%s\");", option);
1622     gROOT->ProcessLine(line);
1623     f = gFile;
1624     if (fDebug > 1) {
1625       gROOT->ProcessLine("pf->Print()");
1626       printf(" == proof file name: %s", f->GetName());
1627     }   
1628     // Add to proof output list
1629     line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1630     if (fDebug > 1) printf("=== %s\n", line.Data());
1631     gROOT->ProcessLine(line);
1632   }
1633   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1634     cont->SetFile(f);
1635     // Cd to file
1636     f->cd();
1637     // Check for a folder request
1638     TString dir = cont->GetFolderName(); 
1639     if (!dir.IsNull()) {
1640       if (!f->GetDirectory(dir)) f->mkdir(dir);
1641       f->cd(dir);
1642     }
1643     return f;
1644   }
1645   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1646   cont->SetFile(NULL);  
1647   return NULL;
1648 }   
1649
1650 //______________________________________________________________________________
1651 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1652 {
1653 // Execute analysis.
1654    static Long64_t ncalls = 0;
1655    if (fDebug > 0) printf("MGR: Processing event #%lld\n", ncalls);
1656    TDirectory *cdir = gDirectory;
1657    gROOT->cd();
1658    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1659    if (getsysInfo && ((ncalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)ncalls);
1660    ncalls++;
1661    if (!fInitOK) {
1662       Error("ExecAnalysis", "Analysis manager was not initialized !");
1663       cdir->cd();
1664       return;
1665    }
1666    AliAnalysisTask *task;
1667    // Check if the top tree is active.
1668    if (fTree) {
1669       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1670          AliSysInfo::AddStamp("Handlers_BeginEventGroup",(Int_t)ncalls, 1002, 0);
1671       TIter next(fTasks);
1672    // De-activate all tasks
1673       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1674       AliAnalysisDataContainer *cont = fCommonInput;
1675       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1676       if (!cont) {
1677               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1678          cdir->cd();
1679          return;
1680       }   
1681       cont->SetData(fTree); // This will notify all consumers
1682       Long64_t entry = fTree->GetTree()->GetReadEntry();      
1683 //
1684 //    Call BeginEvent() for optional input/output and MC services 
1685       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1686       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1687       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1688       gROOT->cd();
1689       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1690          AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
1691 //
1692 //    Execute the tasks
1693 //      TIter next1(cont->GetConsumers());
1694       TIter next1(fTopTasks);
1695       Int_t itask = 0;
1696       while ((task=(AliAnalysisTask*)next1())) {
1697          if (fDebug >1) {
1698             cout << "    Executing task " << task->GetName() << endl;
1699          }       
1700          task->ExecuteTask(option);
1701          gROOT->cd();
1702          if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1703             AliSysInfo::AddStamp(task->ClassName(),(Int_t)ncalls, itask, 1);
1704          itask++;   
1705       }
1706 //
1707 //    Call FinishEvent() for optional output and MC services 
1708       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1709       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1710       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1711       // Gather system information if requested
1712       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1713          AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1001, 1);
1714       cdir->cd();   
1715       return;
1716    }   
1717    // The event loop is not controlled by TSelector   
1718 //
1719 //  Call BeginEvent() for optional input/output and MC services 
1720    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1721    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1722    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1723    gROOT->cd();
1724    if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1725       AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
1726    TIter next2(fTopTasks);
1727    while ((task=(AliAnalysisTask*)next2())) {
1728       task->SetActive(kTRUE);
1729       if (fDebug > 1) {
1730          cout << "    Executing task " << task->GetName() << endl;
1731       }   
1732       task->ExecuteTask(option);
1733       gROOT->cd();
1734    }   
1735 //
1736 // Call FinishEvent() for optional output and MC services 
1737    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1738    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1739    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1740    if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1741       AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1);
1742    cdir->cd();   
1743 }
1744
1745 //______________________________________________________________________________
1746 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
1747 {
1748 // Set the input event handler and create a container for it.
1749    fInputEventHandler   = handler;
1750    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1751 //   Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1752 }
1753
1754 //______________________________________________________________________________
1755 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
1756 {
1757 // Set the input event handler and create a container for it.
1758    fOutputEventHandler   = handler;
1759    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1760    fCommonOutput->SetSpecialOutput();
1761 //   Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1762 }
1763
1764 //______________________________________________________________________________
1765 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1766 {
1767 // This method is used externally to register output files which are not
1768 // connected to any output container, so that the manager can properly register,
1769 // retrieve or merge them when running in distributed mode. The file names are
1770 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1771    if (fExtraFiles.Contains(fname)) return;
1772    if (fExtraFiles.Length()) fExtraFiles += " ";
1773    fExtraFiles += fname;
1774 }
1775
1776 //______________________________________________________________________________
1777 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
1778 {
1779 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1780    char fullPath[512];
1781    char chUrl[512];
1782    TObject *pof =  source->FindObject(filename);
1783    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1784       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1785       return kFALSE;
1786    }
1787    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", fullPath, pof));
1788    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", chUrl));
1789    TString clientUrl(chUrl);
1790    TString fullPath_str(fullPath);
1791    if (clientUrl.Contains("localhost")){
1792       TObjArray* array = fullPath_str.Tokenize ( "//" );
1793       TObjString *strobj = ( TObjString *)array->At(1);
1794       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1795       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1796       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1797       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1798       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
1799       delete arrayPort;
1800       delete array;
1801    }
1802    if (fDebug > 1) 
1803       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", fullPath_str.Data());
1804    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
1805    if (!gotit)
1806       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1807    return gotit;
1808 }
1809
1810 //______________________________________________________________________________
1811 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1812 {
1813 // Fill analysis type in the provided string.
1814    switch (fMode) {
1815       case kLocalAnalysis:
1816          type = "local";
1817          return;
1818       case kProofAnalysis:
1819          type = "proof";
1820          return;
1821       case kGridAnalysis:
1822          type = "grid";
1823          return;
1824       case kMixingAnalysis:
1825          type = "mix";
1826    }
1827 }
1828
1829 //______________________________________________________________________________
1830 Bool_t AliAnalysisManager::ValidateOutputFiles() const
1831 {
1832 // Validate all output files.
1833    TIter next(fOutputs);
1834    AliAnalysisDataContainer *output;
1835    TDirectory *cdir = gDirectory;
1836    TString openedFiles;
1837    while ((output=(AliAnalysisDataContainer*)next())) {
1838       if (output->IsRegisterDataset()) continue;
1839       TString filename = output->GetFileName();
1840       if (filename == "default") {
1841          if (!fOutputEventHandler) continue;
1842          filename = fOutputEventHandler->GetOutputFileName();
1843          // Main AOD may not be there
1844          if (gSystem->AccessPathName(filename)) continue;
1845       }
1846       // Check if the file is closed
1847       if (openedFiles.Contains(filename)) continue;;
1848       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1849       if (file) {
1850          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1851          // Clear file list to release object ownership to user.
1852 //         file->Clear();
1853          file->Close();
1854       }
1855       file = TFile::Open(filename);
1856       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1857          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1858          cdir->cd();
1859          return kFALSE;
1860       }
1861       file->Close();
1862       openedFiles += filename;
1863       openedFiles += " ";
1864    }
1865    cdir->cd();
1866    return kTRUE;
1867 }   
1868
1869 //______________________________________________________________________________
1870 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
1871 {
1872 // Implements a nice text mode progress bar.
1873    static Long64_t icount = 0;
1874    static TString oname;
1875    static TString nname;
1876    static Long64_t ocurrent = 0;
1877    static Long64_t osize = 0;
1878    static Int_t oseconds = 0;
1879    static TStopwatch *owatch = 0;
1880    static Bool_t oneoftwo = kFALSE;
1881    static Int_t nrefresh = 0;
1882    static Int_t nchecks = 0;
1883    const char symbol[4] = {'=','\\','|','/'}; 
1884    char progress[11] = "          ";
1885    Int_t ichar = icount%4;
1886    
1887    if (!refresh) {
1888       nrefresh = 0;
1889       if (!size) return;
1890       owatch = watch;
1891       oname = opname;
1892       ocurrent = TMath::Abs(current);
1893       osize = TMath::Abs(size);
1894       if (ocurrent > osize) ocurrent=osize;
1895    } else {
1896       nrefresh++;
1897       if (!osize) return;
1898    }     
1899    icount++;
1900    Double_t time = 0.;
1901    Int_t hours = 0;
1902    Int_t minutes = 0;
1903    Int_t seconds = 0;
1904    if (owatch && !last) {
1905       owatch->Stop();
1906       time = owatch->RealTime();
1907       hours = (Int_t)(time/3600.);
1908       time -= 3600*hours;
1909       minutes = (Int_t)(time/60.);
1910       time -= 60*minutes;
1911       seconds = (Int_t)time;
1912       if (refresh)  {
1913          if (oseconds==seconds) {
1914             owatch->Continue();
1915             return;
1916          }
1917          oneoftwo = !oneoftwo;   
1918       }
1919       oseconds = seconds;   
1920    }
1921    if (refresh && oneoftwo) {
1922       nname = oname;
1923       if (nchecks <= 0) nchecks = nrefresh+1;
1924       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
1925       oname = Form("     == %d%% ==", pctdone);
1926    }         
1927    Double_t percent = 100.0*ocurrent/osize;
1928    Int_t nchar = Int_t(percent/10);
1929    if (nchar>10) nchar=10;
1930    Int_t i;
1931    for (i=0; i<nchar; i++)  progress[i] = '=';
1932    progress[nchar] = symbol[ichar];
1933    for (i=nchar+1; i<10; i++) progress[i] = ' ';
1934    progress[10] = '\0';
1935    oname += "                    ";
1936    oname.Remove(20);
1937    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
1938    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
1939    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
1940    if (time>0.) fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d             \r", percent, hours, minutes, seconds);
1941    else fprintf(stderr, "[%6.2f %%]\r", percent);
1942    if (refresh && oneoftwo) oname = nname;
1943    if (owatch) owatch->Continue();
1944    if (last) {
1945       icount = 0;
1946       owatch = 0;
1947       ocurrent = 0;
1948       osize = 0;
1949       oseconds = 0;
1950       oneoftwo = kFALSE;
1951       nrefresh = 0;
1952       fprintf(stderr, "\n");
1953    }   
1954 }