]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Bug fix in array size
[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 <TClass.h>
31 #include <TFile.h>
32 #include <TKey.h>
33 #include <TMethodCall.h>
34 #include <TChain.h>
35 #include <TSystem.h>
36 #include <TROOT.h>
37 #include <TCanvas.h>
38
39 #include "AliAnalysisSelector.h"
40 #include "AliAnalysisGrid.h"
41 #include "AliAnalysisTask.h"
42 #include "AliAnalysisDataContainer.h"
43 #include "AliAnalysisDataSlot.h"
44 #include "AliVEventHandler.h"
45 #include "AliVEventPool.h"
46 #include "AliSysInfo.h"
47 #include "AliAnalysisManager.h"
48
49 ClassImp(AliAnalysisManager)
50
51 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
52
53 //______________________________________________________________________________
54 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
55                    :TNamed(name,title),
56                     fTree(NULL),
57                     fInputEventHandler(NULL),
58                     fOutputEventHandler(NULL),
59                     fMCtruthEventHandler(NULL),
60                     fEventPool(NULL),
61                     fCurrentEntry(-1),
62                     fNSysInfo(0),
63                     fMode(kLocalAnalysis),
64                     fInitOK(kFALSE),
65                     fDebug(0),
66                     fSpecialOutputLocation(""), 
67                     fTasks(NULL),
68                     fTopTasks(NULL),
69                     fZombies(NULL),
70                     fContainers(NULL),
71                     fInputs(NULL),
72                     fOutputs(NULL),
73                     fCommonInput(NULL),
74                     fCommonOutput(NULL),
75                     fSelector(NULL),
76                     fGridHandler(NULL),
77                     fExtraFiles("")
78 {
79 // Default constructor.
80    fgAnalysisManager = this;
81    fTasks      = new TObjArray();
82    fTopTasks   = new TObjArray();
83    fZombies    = new TObjArray();
84    fContainers = new TObjArray();
85    fInputs     = new TObjArray();
86    fOutputs    = new TObjArray();
87    SetEventLoop(kTRUE);
88 }
89
90 //______________________________________________________________________________
91 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
92                    :TNamed(other),
93                     fTree(NULL),
94                     fInputEventHandler(NULL),
95                     fOutputEventHandler(NULL),
96                     fMCtruthEventHandler(NULL),
97                     fEventPool(NULL),
98                     fCurrentEntry(-1),
99                     fNSysInfo(0),
100                     fMode(other.fMode),
101                     fInitOK(other.fInitOK),
102                     fDebug(other.fDebug),
103                     fSpecialOutputLocation(""), 
104                     fTasks(NULL),
105                     fTopTasks(NULL),
106                     fZombies(NULL),
107                     fContainers(NULL),
108                     fInputs(NULL),
109                     fOutputs(NULL),
110                     fCommonInput(NULL),
111                     fCommonOutput(NULL),
112                     fSelector(NULL),
113                     fGridHandler(NULL),
114                     fExtraFiles()
115 {
116 // Copy constructor.
117    fTasks      = new TObjArray(*other.fTasks);
118    fTopTasks   = new TObjArray(*other.fTopTasks);
119    fZombies    = new TObjArray(*other.fZombies);
120    fContainers = new TObjArray(*other.fContainers);
121    fInputs     = new TObjArray(*other.fInputs);
122    fOutputs    = new TObjArray(*other.fOutputs);
123    fgAnalysisManager = this;
124 }
125    
126 //______________________________________________________________________________
127 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
128 {
129 // Assignment
130    if (&other != this) {
131       TNamed::operator=(other);
132       fInputEventHandler   = other.fInputEventHandler;
133       fOutputEventHandler  = other.fOutputEventHandler;
134       fMCtruthEventHandler = other.fMCtruthEventHandler;
135       fEventPool           = other.fEventPool;
136       fTree       = NULL;
137       fCurrentEntry = -1;
138       fNSysInfo   = other.fNSysInfo;
139       fMode       = other.fMode;
140       fInitOK     = other.fInitOK;
141       fDebug      = other.fDebug;
142       fTasks      = new TObjArray(*other.fTasks);
143       fTopTasks   = new TObjArray(*other.fTopTasks);
144       fZombies    = new TObjArray(*other.fZombies);
145       fContainers = new TObjArray(*other.fContainers);
146       fInputs     = new TObjArray(*other.fInputs);
147       fOutputs    = new TObjArray(*other.fOutputs);
148       fCommonInput = NULL;
149       fCommonOutput = NULL;
150       fSelector   = NULL;
151       fGridHandler = NULL;
152       fExtraFiles = other.fExtraFiles;
153       fgAnalysisManager = this;
154    }
155    return *this;
156 }
157
158 //______________________________________________________________________________
159 AliAnalysisManager::~AliAnalysisManager()
160 {
161 // Destructor.
162    if (fTasks) {fTasks->Delete(); delete fTasks;}
163    if (fTopTasks) delete fTopTasks;
164    if (fZombies) delete fZombies;
165    if (fContainers) {fContainers->Delete(); delete fContainers;}
166    if (fInputs) delete fInputs;
167    if (fOutputs) delete fOutputs;
168    if (fGridHandler) delete fGridHandler;
169    if (fgAnalysisManager==this) fgAnalysisManager = NULL;
170 }
171
172 //______________________________________________________________________________
173 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
174 {
175 // Read one entry of the tree or a whole branch.
176    if (fDebug > 0) Printf("== AliAnalysisManager::GetEntry(%lld)", entry);
177    fCurrentEntry = entry;
178    return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
179 }
180    
181 //______________________________________________________________________________
182 Bool_t AliAnalysisManager::Init(TTree *tree)
183 {
184   // The Init() function is called when the selector needs to initialize
185   // a new tree or chain. Typically here the branch addresses of the tree
186   // will be set. It is normaly not necessary to make changes to the
187   // generated code, but the routine can be extended by the user if needed.
188   // Init() will be called many times when running with PROOF.
189    Bool_t init = kFALSE;
190    if (!tree) return kFALSE; // Should not happen - protected in selector caller
191    if (fDebug > 0) {
192       Printf("->AliAnalysisManager::Init(%s)", tree->GetName());
193    }
194    // Call InitTree of EventHandler
195    if (fOutputEventHandler) {
196       if (fMode == kProofAnalysis) {
197          init = fOutputEventHandler->Init(0x0, "proof");
198       } else {
199          init = fOutputEventHandler->Init(0x0, "local");
200       }
201       if (!init) {
202          Error("Init", "Output event handler failed to initialize");
203          return kFALSE;
204       }         
205    }
206    
207    if (fInputEventHandler) {
208       if (fMode == kProofAnalysis) {
209          init = fInputEventHandler->Init(tree, "proof");
210       } else {
211          init = fInputEventHandler->Init(tree, "local");
212       }
213       if (!init) {
214          Error("Init", "Input event handler failed to initialize tree"); 
215          return kFALSE;
216       }         
217    } else {
218       // If no input event handler we need to get the tree once
219       // for the chain
220       if(!tree->GetTree()) {
221          Long64_t readEntry = tree->LoadTree(0);
222          if (readEntry == -2) {
223             Error("Init", "Input tree has no entry. Aborting");
224             return kFALSE;
225          }
226       }   
227    }
228
229    if (fMCtruthEventHandler) {
230       if (fMode == kProofAnalysis) {
231          init = fMCtruthEventHandler->Init(0x0, "proof");
232       } else {
233          init = fMCtruthEventHandler->Init(0x0, "local");
234       }
235       if (!init) {
236          Error("Init", "MC event handler failed to initialize"); 
237          return kFALSE;
238       }         
239    }
240
241    if (!fInitOK) InitAnalysis();
242    if (!fInitOK) return kFALSE;
243    fTree = tree;
244    AliAnalysisDataContainer *top = fCommonInput;
245    if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
246    if (!top) {
247       Error("Init","No top input container !");
248       return kFALSE;
249    }
250    top->SetData(tree);
251    if (fDebug > 0) {
252       Printf("<-AliAnalysisManager::Init(%s)", tree->GetName());
253    }
254    return kTRUE;
255 }
256
257 //______________________________________________________________________________
258 void AliAnalysisManager::SlaveBegin(TTree *tree)
259 {
260   // The SlaveBegin() function is called after the Begin() function.
261   // When running with PROOF SlaveBegin() is called on each slave server.
262   // The tree argument is deprecated (on PROOF 0 is passed).
263    if (fDebug > 0) Printf("->AliAnalysisManager::SlaveBegin()");
264    static Bool_t isCalled = kFALSE;
265    Bool_t init = kFALSE;
266    Bool_t initOK = kTRUE;
267    TString msg;
268    TDirectory *curdir = gDirectory;
269    // Call SlaveBegin only once in case of mixing
270    if (isCalled && fMode==kMixingAnalysis) return;
271    // Call Init of EventHandler
272    if (fOutputEventHandler) {
273       if (fMode == kProofAnalysis) {
274          // Merging AOD's in PROOF via TProofOutputFile
275          if (fDebug > 1) Printf("   Initializing AOD output file %s...", fOutputEventHandler->GetOutputFileName());
276          init = fOutputEventHandler->Init("proof");
277          if (!init) msg = "Failed to initialize output handler on worker";
278       } else {
279          init = fOutputEventHandler->Init("local");
280          if (!init) msg = "Failed to initialize output handler";
281       }
282       initOK &= init;
283       if (!fSelector) Error("SlaveBegin", "Selector not set");
284       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
285    }
286
287    if (fInputEventHandler) {
288       fInputEventHandler->SetInputTree(tree);
289       if (fMode == kProofAnalysis) {
290          init = fInputEventHandler->Init("proof");
291          if (!init) msg = "Failed to initialize input handler on worker";
292       } else {
293          init = fInputEventHandler->Init("local");
294          if (!init) msg = "Failed to initialize input handler";
295       }
296       initOK &= init;
297       if (!fSelector) Error("SlaveBegin", "Selector not set");      
298       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
299    }
300
301    if (fMCtruthEventHandler) {
302       if (fMode == kProofAnalysis) {
303          init = fMCtruthEventHandler->Init("proof");
304          if (!init) msg = "Failed to initialize MC handler on worker";
305       } else {
306          init = fMCtruthEventHandler->Init("local");
307          if (!init) msg = "Failed to initialize MC handler";
308       }
309       initOK &= init;
310       if (!fSelector) Error("SlaveBegin", "Selector not set");      
311       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
312    }
313    if (curdir) curdir->cd();
314    isCalled = kTRUE;
315    if (!initOK) return;   
316    TIter next(fTasks);
317    AliAnalysisTask *task;
318    // Call CreateOutputObjects for all tasks
319    while ((task=(AliAnalysisTask*)next())) {
320       curdir = gDirectory;
321       task->CreateOutputObjects();
322       if (curdir) curdir->cd();
323    }
324    if (fDebug > 0) Printf("<-AliAnalysisManager::SlaveBegin()");
325 }
326
327 //______________________________________________________________________________
328 Bool_t AliAnalysisManager::Notify()
329 {
330    // The Notify() function is called when a new file is opened. This
331    // can be either for a new TTree in a TChain or when when a new TTree
332    // is started when using PROOF. It is normaly not necessary to make changes
333    // to the generated code, but the routine can be extended by the
334    // user if needed. The return value is currently not used.
335    if (!fTree) return kFALSE;
336
337    TFile *curfile = fTree->GetCurrentFile();
338    if (!curfile) {
339       Error("Notify","No current file");
340       return kFALSE;
341    }   
342    
343    if (fDebug > 0) Printf("->AliAnalysisManager::Notify() file: %s", curfile->GetName());
344    TIter next(fTasks);
345    AliAnalysisTask *task;
346    // Call Notify for all tasks
347    while ((task=(AliAnalysisTask*)next())) 
348       task->Notify();
349         
350    // Call Notify of the event handlers
351    if (fInputEventHandler) {
352        fInputEventHandler->Notify(curfile->GetName());
353    }
354
355    if (fOutputEventHandler) {
356        fOutputEventHandler->Notify(curfile->GetName());
357    }
358
359    if (fMCtruthEventHandler) {
360        fMCtruthEventHandler->Notify(curfile->GetName());
361    }
362    if (fDebug > 0) Printf("<-AliAnalysisManager::Notify()");
363    return kTRUE;
364 }    
365
366 //______________________________________________________________________________
367 Bool_t AliAnalysisManager::Process(Long64_t entry)
368 {
369   // The Process() function is called for each entry in the tree (or possibly
370   // keyed object in the case of PROOF) to be processed. The entry argument
371   // specifies which entry in the currently loaded tree is to be processed.
372   // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
373   // to read either all or the required parts of the data. When processing
374   // keyed objects with PROOF, the object is already loaded and is available
375   // via the fObject pointer.
376   //
377   // This function should contain the "body" of the analysis. It can contain
378   // simple or elaborate selection criteria, run algorithms on the data
379   // of the event and typically fill histograms.
380
381   // WARNING when a selector is used with a TChain, you must use
382   //  the pointer to the current TTree to call GetEntry(entry).
383   //  The entry is always the local entry number in the current tree.
384   //  Assuming that fChain is the pointer to the TChain being processed,
385   //  use fChain->GetTree()->GetEntry(entry).
386    if (fDebug > 0) Printf("->AliAnalysisManager::Process(%lld)", entry);
387
388    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
389    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
390    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
391    
392    GetEntry(entry);
393    ExecAnalysis();
394    if (fDebug > 0) Printf("<-AliAnalysisManager::Process()");
395    return kTRUE;
396 }
397
398 //______________________________________________________________________________
399 void AliAnalysisManager::PackOutput(TList *target)
400 {
401   // Pack all output data containers in the output list. Called at SlaveTerminate
402   // stage in PROOF case for each slave.
403    if (fDebug > 0) Printf("->AliAnalysisManager::PackOutput()");
404    if (!target) {
405       Error("PackOutput", "No target. Aborting.");
406       return;
407    }
408    if (fInputEventHandler)   fInputEventHandler  ->Terminate();
409    if (fOutputEventHandler)  fOutputEventHandler ->Terminate();
410    if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
411
412    // Call FinishTaskOutput() for each event loop task (not called for 
413    // post-event loop tasks - use Terminate() fo those)
414    TIter nexttask(fTasks);
415    AliAnalysisTask *task;
416    while ((task=(AliAnalysisTask*)nexttask())) {
417       if (!task->IsPostEventLoop()) {
418          if (fDebug > 0) Printf("->FinishTaskOutput: task %s", task->GetName());
419          task->FinishTaskOutput();
420          if (fDebug > 0) Printf("<-FinishTaskOutput: task %s", task->GetName());
421       }
422    }      
423    
424    if (fMode == kProofAnalysis) {
425       TIter next(fOutputs);
426       AliAnalysisDataContainer *output;
427       Bool_t isManagedByHandler = kFALSE;
428       while ((output=(AliAnalysisDataContainer*)next())) {
429          // Do not consider outputs of post event loop tasks
430          isManagedByHandler = kFALSE;
431          if (output->GetProducer()->IsPostEventLoop()) continue;
432          const char *filename = output->GetFileName();
433          if (!(strcmp(filename, "default")) && fOutputEventHandler) {
434             isManagedByHandler = kTRUE;
435             Printf("#### Handler output. Extra: %s", fExtraFiles.Data());
436             filename = fOutputEventHandler->GetOutputFileName();
437          }
438          // Check if data was posted to this container. If not, issue an error.
439          if (!output->GetData() && !isManagedByHandler) {
440             Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
441             continue;
442          }   
443          if (!output->IsSpecialOutput()) {
444             // Normal outputs
445             if (strlen(filename) && !isManagedByHandler) {
446                // File resident outputs
447                TFile *file = output->GetFile();
448                // Backup current folder
449                TDirectory *opwd = gDirectory;
450                // Create file if not existing and register to container.
451                if (file) file->cd();
452                else      file = new TFile(filename, "RECREATE"); 
453                if (file->IsZombie()) {
454                   Fatal("PackOutput", "Could not recreate file %s", filename);
455                   return;
456                }   
457                output->SetFile(file);
458                // Clear file list to release object ownership to user.
459                file->Clear();
460                // Save data to file, then close.
461                if (output->GetData()->InheritsFrom(TCollection::Class())) {
462                   // If data is a collection, we set the name of the collection 
463                   // as the one of the container and we save as a single key.
464                   TCollection *coll = (TCollection*)output->GetData();
465                   coll->SetName(output->GetName());
466                   coll->Write(output->GetName(), TObject::kSingleKey);
467                } else {
468                   if (output->GetData()->InheritsFrom(TTree::Class())) {
469                      TTree *tree = (TTree*)output->GetData();
470                      // tree->SetDirectory(file);
471                      tree->AutoSave();
472                   } else {
473                      output->GetData()->Write();
474                   }   
475                }      
476                if (fDebug > 1) Printf("PackOutput %s: memory merge, file resident output", output->GetName());
477                if (fDebug > 2) {
478                   Printf("   file %s listing content:", filename);
479                   file->ls();
480                }   
481                file->Close();
482                // Restore current directory
483                if (opwd) opwd->cd();
484             } else {
485                // Memory-resident outputs   
486                if (fDebug > 1) Printf("PackOutput %s: memory merge memory resident output", filename);
487             }   
488             AliAnalysisDataWrapper *wrap = 0;
489             if (isManagedByHandler) {
490                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
491                wrap->SetName(output->GetName());
492             }   
493             else                    wrap =output->ExportData();
494             // Output wrappers must NOT delete data after merging - the user owns them
495             wrap->SetDeleteData(kFALSE);
496             target->Add(wrap);
497          } else {
498          // Special outputs. The file must be opened and connected to the container.
499             TDirectory *opwd = gDirectory;
500             TFile *file = output->GetFile();
501             if (!file) {
502                AliAnalysisTask *producer = output->GetProducer();
503                Error("PackOutput", 
504                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
505                      output->GetFileName(), output->GetName(), producer->ClassName());
506                continue;
507             }   
508             TString outFilename = file->GetName();
509             if (fDebug > 1) Printf("PackOutput %s: special output", output->GetName());
510             if (isManagedByHandler) {
511                // Terminate IO for files managed by the output handler
512                if (file) file->Write();
513                if (file && fDebug > 2) {
514                   Printf("   handled file %s listing content:", file->GetName());
515                   file->ls();
516                }   
517                fOutputEventHandler->TerminateIO();
518             } else {               
519                file->cd();
520                // Release object ownership to users after writing data to file
521                if (output->GetData()->InheritsFrom(TCollection::Class())) {
522                   // If data is a collection, we set the name of the collection 
523                   // as the one of the container and we save as a single key.
524                   TCollection *coll = (TCollection*)output->GetData();
525                   coll->SetName(output->GetName());
526                   coll->Write(output->GetName(), TObject::kSingleKey);
527                } else {
528                   if (output->GetData()->InheritsFrom(TTree::Class())) {
529                      TTree *tree = (TTree*)output->GetData();
530                      tree->SetDirectory(file);
531                      tree->AutoSave();
532                   } else {
533                      output->GetData()->Write();
534                   }   
535                }      
536                file->Clear();
537                if (fDebug > 2) {
538                   Printf("   file %s listing content:", output->GetFileName());
539                   file->ls();
540                }
541                file->Close();
542             }
543             // Restore current directory
544             if (opwd) opwd->cd();
545             // Check if a special output location was provided or the output files have to be merged
546             if (strlen(fSpecialOutputLocation.Data())) {
547                TString remote = fSpecialOutputLocation;
548                remote += "/";
549                Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
550                if (remote.BeginsWith("alien://")) {
551                   gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
552                   remote += outFilename;
553                   remote.ReplaceAll(".root", Form("_%d.root", gid));
554                } else {   
555                   remote += Form("%s_%d_", gSystem->HostName(), gid);
556                   remote += outFilename;
557                }   
558                if (fDebug > 1) 
559                   Info("PackOutput", "Output file for container %s to be copied \n   at: %s. No merging.",
560                        output->GetName(), remote.Data());
561                TFile::Cp ( outFilename.Data(), remote.Data() );
562                // Copy extra outputs
563                if (fExtraFiles.Length() && isManagedByHandler) {
564                   TObjArray *arr = fExtraFiles.Tokenize(" ");
565                   TObjString *os;
566                   TIter nextfilename(arr);
567                   while ((os=(TObjString*)nextfilename())) {
568                      outFilename = os->GetString();
569                      remote = fSpecialOutputLocation;
570                      remote += "/";
571                      if (remote.BeginsWith("alien://")) {
572                         remote += outFilename;
573                         remote.ReplaceAll(".root", Form("_%d.root", gid));
574                      } else {   
575                         remote += Form("%s_%d_", gSystem->HostName(), gid);
576                         remote += outFilename;
577                      }   
578                      if (fDebug > 1) 
579                         Info("PackOutput", "Extra AOD file %s to be copied \n   at: %s. No merging.",
580                              outFilename.Data(), remote.Data());
581                      TFile::Cp ( outFilename.Data(), remote.Data() );
582                   }   
583                   delete arr;
584                }   
585             } else {
586             // No special location specified-> use TProofOutputFile as merging utility
587             // The file at this output slot must be opened in CreateOutputObjects
588                if (fDebug > 1) Printf("   File for container %s to be merged via file merger...", output->GetName());
589             }
590          }      
591       }
592    } 
593    if (fDebug > 0) Printf("<-AliAnalysisManager::PackOutput: output list contains %d containers", target->GetSize());
594 }
595
596 //______________________________________________________________________________
597 void AliAnalysisManager::ImportWrappers(TList *source)
598 {
599 // Import data in output containers from wrappers coming in source.
600    if (fDebug > 0) Printf("->AliAnalysisManager::ImportWrappers()");
601    TIter next(fOutputs);
602    AliAnalysisDataContainer *cont;
603    AliAnalysisDataWrapper   *wrap;
604    Int_t icont = 0;
605    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
606    while ((cont=(AliAnalysisDataContainer*)next())) {
607       wrap = 0;
608       if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
609       const char *filename = cont->GetFileName();
610       Bool_t isManagedByHandler = kFALSE;
611       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
612          isManagedByHandler = kTRUE;
613          filename = fOutputEventHandler->GetOutputFileName();
614       }
615       if (cont->IsSpecialOutput() || inGrid) {
616          if (strlen(fSpecialOutputLocation.Data())) continue;
617          // Copy merged file from PROOF scratch space. 
618          // In case of grid the files are already in the current directory.
619          if (!inGrid) {
620             if (isManagedByHandler && fExtraFiles.Length()) {
621                // Copy extra registered dAOD files.
622                TObjArray *arr = fExtraFiles.Tokenize(" ");
623                TObjString *os;
624                TIter nextfilename(arr);
625                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
626                delete arr;
627             }
628             if (!GetFileFromWrapper(filename, source)) continue;
629          }   
630          // Normally we should connect data from the copied file to the
631          // corresponding output container, but it is not obvious how to do this
632          // automatically if several objects in file...
633          TFile *f = TFile::Open(filename, "READ");
634          if (!f) {
635             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
636             continue;
637          }   
638          TObject *obj = 0;
639          // Try to fetch first a list object having the container name.
640          obj = f->Get(cont->GetName());
641          if (!obj) {
642          // Fetch first object from file having the container type.
643             TIter nextkey(f->GetListOfKeys());
644             TKey *key;
645             while ((key=(TKey*)nextkey())) {
646                obj = f->Get(key->GetName());
647                if (obj && obj->IsA()->InheritsFrom(cont->GetType())) break;
648             }                     
649          }
650          if (!obj) {
651             Error("ImportWrappers", "Could not find object for container %s in file %s", cont->GetName(), filename);
652             continue;
653          }  
654          wrap = new AliAnalysisDataWrapper(obj);
655          wrap->SetDeleteData(kFALSE);
656       }   
657       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
658       if (!wrap) {
659          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
660          continue;
661       }
662       icont++;
663       if (fDebug > 1) {
664          Printf("   Importing data for container %s", cont->GetName());
665          if (strlen(filename)) Printf("    -> file %s", filename);
666          else Printf("");
667       }   
668       cont->ImportData(wrap);
669    }         
670    if (fDebug > 0) Printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported", icont);
671 }
672
673 //______________________________________________________________________________
674 void AliAnalysisManager::UnpackOutput(TList *source)
675 {
676   // Called by AliAnalysisSelector::Terminate only on the client.
677    if (fDebug > 0) Printf("->AliAnalysisManager::UnpackOutput()");
678    if (!source) {
679       Error("UnpackOutput", "No target. Aborting.");
680       return;
681    }
682    if (fDebug > 1) Printf("   Source list contains %d containers", source->GetSize());
683
684    if (fMode == kProofAnalysis) ImportWrappers(source);
685
686    TIter next(fOutputs);
687    AliAnalysisDataContainer *output;
688    while ((output=(AliAnalysisDataContainer*)next())) {
689       if (!output->GetData()) continue;
690       // Check if there are client tasks that run post event loop
691       if (output->HasConsumers()) {
692          // Disable event loop semaphore
693          output->SetPostEventLoop(kTRUE);
694          TObjArray *list = output->GetConsumers();
695          Int_t ncons = list->GetEntriesFast();
696          for (Int_t i=0; i<ncons; i++) {
697             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
698             task->CheckNotify(kTRUE);
699             // If task is active, execute it
700             if (task->IsPostEventLoop() && task->IsActive()) {
701                if (fDebug > 0) Printf("== Executing post event loop task %s", task->GetName());
702                task->ExecuteTask();
703             }   
704          }
705       }   
706    }
707    if (fDebug > 0) Printf("<-AliAnalysisManager::UnpackOutput()");
708 }
709
710 //______________________________________________________________________________
711 void AliAnalysisManager::Terminate()
712 {
713   // The Terminate() function is the last function to be called during
714   // a query. It always runs on the client, it can be used to present
715   // the results graphically.
716    if (fDebug > 0) Printf("->AliAnalysisManager::Terminate()");
717    AliAnalysisTask *task;
718    TIter next(fTasks);
719    // Call Terminate() for tasks
720    while ((task=(AliAnalysisTask*)next())) task->Terminate();
721    //
722    TIter next1(fOutputs);
723    AliAnalysisDataContainer *output;
724    while ((output=(AliAnalysisDataContainer*)next1())) {
725       // Special outputs or grid files have the files already closed and written.
726       if (fMode == kGridAnalysis) continue;
727       if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
728       const char *filename = output->GetFileName();
729       if (!(strcmp(filename, "default"))) {
730          if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
731          TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
732          if (aodfile) {
733             if (fDebug > 1) Printf("Writing output handler file: %s", filename);
734             aodfile->Write();
735             continue;
736          }   
737       }      
738       if (!strlen(filename)) continue;
739       if (!output->GetData()) continue;
740       TFile *file = output->GetFile();
741       TDirectory *opwd = gDirectory;
742       file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
743       if (!file) file = new TFile(filename, "RECREATE");
744       if (file->IsZombie()) continue;
745       output->SetFile(file);
746       file->cd();
747       if (fDebug > 1) Printf("   writing output data %s to file %s", output->GetData()->GetName(), file->GetName());
748       if (output->GetData()->InheritsFrom(TCollection::Class())) {
749       // If data is a collection, we set the name of the collection 
750       // as the one of the container and we save as a single key.
751          TCollection *coll = (TCollection*)output->GetData();
752          coll->SetName(output->GetName());
753          coll->Write(output->GetName(), TObject::kSingleKey);
754       } else {
755          if (output->GetData()->InheritsFrom(TTree::Class())) {
756             TTree *tree = (TTree*)output->GetData();
757             tree->SetDirectory(file);
758             tree->AutoSave();
759          } else {
760             output->GetData()->Write();
761          }   
762       }      
763       if (opwd) opwd->cd();
764    }   
765    next1.Reset();
766    while ((output=(AliAnalysisDataContainer*)next1())) {
767       // Close all files at output
768       TDirectory *opwd = gDirectory;
769       if (output->GetFile()) {
770          output->GetFile()->Close();
771          // Copy merged outputs in alien if requested
772          if (fSpecialOutputLocation.Length() && 
773              fSpecialOutputLocation.BeginsWith("alien://")) {
774             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
775             TFile::Cp(output->GetFile()->GetName(), 
776                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
777          }             
778       }   
779       if (opwd) opwd->cd();
780    }   
781
782    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
783    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
784    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
785
786    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
787    if (getsysInfo) {
788       TDirectory *cdir = gDirectory;
789       TFile f("syswatch.root", "RECREATE");
790       if (!f.IsZombie()) {
791          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
792          tree->SetMarkerStyle(kCircle);
793          tree->SetMarkerColor(kBlue);
794          tree->SetMarkerSize(0.5);
795          if (!gROOT->IsBatch()) {
796             tree->SetAlias("event", "id0");
797             tree->SetAlias("memUSED", "mi.fMemUsed");
798             new TCanvas("SysInfo","SysInfo",10,10,800,600);
799             tree->Draw("memUSED:event","","", 1234567890, 0);
800          }   
801          tree->Write();
802          f.Close();
803          delete tree;
804       }
805       if (cdir) cdir->cd();
806    }
807    // Validate the output files
808    if (ValidateOutputFiles()) {
809       ofstream out;
810       out.open("outputs_valid", ios::out);
811       out.close();
812    }      
813    if (fDebug > 0) Printf("<-AliAnalysisManager::Terminate()");
814 }
815
816 //______________________________________________________________________________
817 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
818 {
819 // Adds a user task to the global list of tasks.
820    if (fTasks->FindObject(task)) {
821       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
822       return;
823    }   
824    task->SetActive(kFALSE);
825    fTasks->Add(task);
826 }  
827
828 //______________________________________________________________________________
829 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
830 {
831 // Retreive task by name.
832    if (!fTasks) return NULL;
833    return (AliAnalysisTask*)fTasks->FindObject(name);
834 }
835
836 //______________________________________________________________________________
837 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
838                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
839 {
840 // Create a data container of a certain type. Types can be:
841 //   kExchangeContainer  = 0, used to exchange date between tasks
842 //   kInputContainer   = 1, used to store input data
843 //   kOutputContainer  = 2, used for posting results
844    if (fContainers->FindObject(name)) {
845       Error("CreateContainer","A container named %s already defined !",name);
846       return NULL;
847    }   
848    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
849    fContainers->Add(cont);
850    switch (type) {
851       case kInputContainer:
852          fInputs->Add(cont);
853          break;
854       case kOutputContainer:
855          fOutputs->Add(cont);
856          if (filename && strlen(filename)) {
857             cont->SetFileName(filename);
858             cont->SetDataOwned(kFALSE);  // data owned by the file
859          }   
860          break;
861       case kExchangeContainer:
862          break;   
863    }
864    return cont;
865 }
866          
867 //______________________________________________________________________________
868 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
869                                         AliAnalysisDataContainer *cont)
870 {
871 // Connect input of an existing task to a data container.
872    if (!task) {
873       Error("ConnectInput", "Task pointer is NULL");
874       return kFALSE;
875    }   
876    if (!fTasks->FindObject(task)) {
877       AddTask(task);
878       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
879    } 
880    Bool_t connected = task->ConnectInput(islot, cont);
881    return connected;
882 }   
883
884 //______________________________________________________________________________
885 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
886                                         AliAnalysisDataContainer *cont)
887 {
888 // Connect output of an existing task to a data container.
889    if (!task) {
890       Error("ConnectOutput", "Task pointer is NULL");
891       return kFALSE;
892    }   
893    if (!fTasks->FindObject(task)) {
894       AddTask(task);
895       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
896    } 
897    Bool_t connected = task->ConnectOutput(islot, cont);
898    return connected;
899 }   
900                                
901 //______________________________________________________________________________
902 void AliAnalysisManager::CleanContainers()
903 {
904 // Clean data from all containers that have already finished all client tasks.
905    TIter next(fContainers);
906    AliAnalysisDataContainer *cont;
907    while ((cont=(AliAnalysisDataContainer *)next())) {
908       if (cont->IsOwnedData() && 
909           cont->IsDataReady() && 
910           cont->ClientsExecuted()) cont->DeleteData();
911    }
912 }
913
914 //______________________________________________________________________________
915 Bool_t AliAnalysisManager::InitAnalysis()
916 {
917 // Initialization of analysis chain of tasks. Should be called after all tasks
918 // and data containers are properly connected
919    // Reset flag and remove valid_outputs file if exists
920    fInitOK = kFALSE;
921    if (!gSystem->AccessPathName("outputs_valid"))
922       gSystem->Unlink("outputs_valid");
923    // Check for top tasks (depending only on input data containers)
924    if (!fTasks->First()) {
925       Error("InitAnalysis", "Analysis has no tasks !");
926       return kFALSE;
927    }   
928    TIter next(fTasks);
929    AliAnalysisTask *task;
930    AliAnalysisDataContainer *cont;
931    Int_t ntop = 0;
932    Int_t nzombies = 0;
933    Bool_t iszombie = kFALSE;
934    Bool_t istop = kTRUE;
935    Int_t i;
936    while ((task=(AliAnalysisTask*)next())) {
937       istop = kTRUE;
938       iszombie = kFALSE;
939       Int_t ninputs = task->GetNinputs();
940       for (i=0; i<ninputs; i++) {
941          cont = task->GetInputSlot(i)->GetContainer();
942          if (!cont) {
943             if (!iszombie) {
944                task->SetZombie();
945                fZombies->Add(task);
946                nzombies++;
947                iszombie = kTRUE;
948             }   
949             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
950                   i, task->GetName()); 
951          }
952          if (iszombie) continue;
953          // Check if cont is an input container
954          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
955          // Connect to parent task
956       }
957       if (istop) {
958          ntop++;
959          fTopTasks->Add(task);
960       }
961    }
962    if (!ntop) {
963       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
964       return kFALSE;
965    }                        
966    // Check now if there are orphan tasks
967    for (i=0; i<ntop; i++) {
968       task = (AliAnalysisTask*)fTopTasks->At(i);
969       task->SetUsed();
970    }
971    Int_t norphans = 0;
972    next.Reset();
973    while ((task=(AliAnalysisTask*)next())) {
974       if (!task->IsUsed()) {
975          norphans++;
976          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
977       }   
978    }          
979    // Check the task hierarchy (no parent task should depend on data provided
980    // by a daughter task)
981    for (i=0; i<ntop; i++) {
982       task = (AliAnalysisTask*)fTopTasks->At(i);
983       if (task->CheckCircularDeps()) {
984          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
985          PrintStatus("dep");
986          return kFALSE;
987       }   
988    }
989    // Check that all containers feeding post-event loop tasks are in the outputs list
990    TIter nextcont(fContainers); // loop over all containers
991    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
992       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
993          if (cont->HasConsumers()) {
994          // Check if one of the consumers is post event loop
995             TIter nextconsumer(cont->GetConsumers());
996             while ((task=(AliAnalysisTask*)nextconsumer())) {
997                if (task->IsPostEventLoop()) {
998                   fOutputs->Add(cont);
999                   break;
1000                }
1001             }
1002          }
1003       }
1004    }   
1005    // Check if all special output containers have a file name provided
1006    TIter nextout(fOutputs);
1007    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1008       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1009          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1010          return kFALSE;
1011       }
1012    }      
1013    fInitOK = kTRUE;
1014    return kTRUE;
1015 }   
1016
1017 //______________________________________________________________________________
1018 void AliAnalysisManager::PrintStatus(Option_t *option) const
1019 {
1020 // Print task hierarchy.
1021    if (!fInitOK) {
1022       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1023       return;
1024    }   
1025    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1026    if (getsysInfo)
1027       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1028    TIter next(fTopTasks);
1029    AliAnalysisTask *task;
1030    while ((task=(AliAnalysisTask*)next()))
1031       task->PrintTask(option);
1032 }
1033
1034 //______________________________________________________________________________
1035 void AliAnalysisManager::ResetAnalysis()
1036 {
1037 // Reset all execution flags and clean containers.
1038    CleanContainers();
1039 }
1040
1041 //______________________________________________________________________________
1042 void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
1043 {
1044 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1045 // MIX. Process nentries starting from firstentry
1046    if (!fInitOK) {
1047       Error("StartAnalysis","Analysis manager was not initialized !");
1048       return;
1049    }
1050    if (fDebug > 0) Printf("StartAnalysis %s",GetName());
1051    TString anaType = type;
1052    anaType.ToLower();
1053    fMode = kLocalAnalysis;
1054    Bool_t runlocalinit = kTRUE;
1055    if (anaType.Contains("file")) runlocalinit = kFALSE;
1056    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1057    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1058    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1059
1060    if (fMode == kGridAnalysis) {
1061       if (!fGridHandler) {
1062          Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1063          Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1064          return;
1065       }
1066       // Write analysis manager in the analysis file
1067       cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1068       // run local task configuration
1069       TIter nextTask(fTasks);
1070       AliAnalysisTask *task;
1071       while ((task=(AliAnalysisTask*)nextTask())) {
1072          task->LocalInit();
1073       }
1074       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1075          Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1076          return;
1077       }   
1078
1079       // Terminate grid analysis
1080       if (fSelector && fSelector->GetStatus() == -1) return;
1081       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1082       cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1083       if (!fGridHandler->MergeOutputs()) {
1084          // Return if outputs could not be merged or if it alien handler
1085          // was configured for offline mode or local testing.
1086          return;
1087       }
1088       ImportWrappers(NULL);
1089       Terminate();
1090       return;
1091    }
1092    char line[256];
1093    SetEventLoop(kFALSE);
1094    // Enable event loop mode if a tree was provided
1095    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1096
1097    TChain *chain = 0;
1098    TString ttype = "TTree";
1099    if (tree && tree->IsA() == TChain::Class()) {
1100       chain = (TChain*)tree;
1101       if (!chain || !chain->GetListOfFiles()->First()) {
1102          Error("StartAnalysis", "Cannot process null or empty chain...");
1103          return;
1104       }   
1105       ttype = "TChain";
1106    }   
1107
1108    // Initialize locally all tasks (happens for all modes)
1109    TIter next(fTasks);
1110    AliAnalysisTask *task;
1111    if (runlocalinit) {
1112       while ((task=(AliAnalysisTask*)next())) {
1113          task->LocalInit();
1114       }
1115    }   
1116    
1117    switch (fMode) {
1118       case kLocalAnalysis:
1119          if (!tree) {
1120             TIter nextT(fTasks);
1121             // Call CreateOutputObjects for all tasks
1122             while ((task=(AliAnalysisTask*)nextT())) {
1123                TDirectory *curdir = gDirectory;
1124                task->CreateOutputObjects();
1125                if (curdir) curdir->cd();
1126             }   
1127             ExecAnalysis();
1128             Terminate();
1129             return;
1130          } 
1131          // Run tree-based analysis via AliAnalysisSelector  
1132          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1133          fSelector = new AliAnalysisSelector(this);
1134          tree->Process(fSelector, "", nentries, firstentry);
1135          break;
1136       case kProofAnalysis:
1137          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1138             Error("StartAnalysis", "No PROOF!!! Aborting.");
1139             return;
1140          }   
1141          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1142          gROOT->ProcessLine(line);
1143          if (chain) {
1144             chain->SetProof();
1145             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1146             chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1147          } else {
1148             Error("StartAnalysis", "No chain!!! Aborting.");
1149             return;
1150          }      
1151          break;
1152       case kGridAnalysis:
1153          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1154          break;
1155       case kMixingAnalysis:   
1156          // Run event mixing analysis
1157          if (!fEventPool) {
1158             Error("StartAnalysis", "Cannot run event mixing without event pool");
1159             return;
1160          }
1161          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1162          fSelector = new AliAnalysisSelector(this);
1163          while ((chain=fEventPool->GetNextChain())) {
1164             next.Reset();
1165             // Call NotifyBinChange for all tasks
1166             while ((task=(AliAnalysisTask*)next()))
1167                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1168             chain->Process(fSelector);
1169          }
1170          PackOutput(fSelector->GetOutputList());
1171          Terminate();
1172    }   
1173 }   
1174
1175 //______________________________________________________________________________
1176 void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1177 {
1178 // Start analysis for this manager on a given dataset. Analysis task can be: 
1179 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1180    if (!fInitOK) {
1181       Error("StartAnalysis","Analysis manager was not initialized !");
1182       return;
1183    }
1184    if (fDebug > 0) Printf("StartAnalysis %s",GetName());
1185    TString anaType = type;
1186    anaType.ToLower();
1187    if (!anaType.Contains("proof")) {
1188       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1189       return;
1190    }   
1191    fMode = kProofAnalysis;
1192    char line[256];
1193    SetEventLoop(kTRUE);
1194    // Set the dataset flag
1195    TObject::SetBit(kUseDataSet);
1196    fTree = 0;
1197
1198    // Initialize locally all tasks
1199    TIter next(fTasks);
1200    AliAnalysisTask *task;
1201    while ((task=(AliAnalysisTask*)next())) {
1202       task->LocalInit();
1203    }
1204    
1205    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1206       Error("StartAnalysis", "No PROOF!!! Aborting.");
1207       return;
1208    }   
1209    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1210    gROOT->ProcessLine(line);
1211    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1212    if (!gROOT->ProcessLine(line)) {
1213       Error("StartAnalysis", "Dataset %s not found", dataset);
1214       return;
1215    }   
1216    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1217            dataset, nentries, firstentry);
1218    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1219    gROOT->ProcessLine(line);
1220 }   
1221
1222 //______________________________________________________________________________
1223 TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1224 {
1225 // Opens a special output file used in PROOF.
1226    char line[256];
1227    if (fMode!=kProofAnalysis || !fSelector) {
1228       Error("OpenProofFile","Cannot open PROOF file %s",filename);
1229       return NULL;
1230    } 
1231    if (fSpecialOutputLocation.Length()) {
1232       TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1233       if (!f) f = new TFile(filename, option);
1234       return f;
1235    }   
1236    sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
1237    if (fDebug > 1) Printf("=== %s", line);
1238    gROOT->ProcessLine(line);
1239    sprintf(line, "pf->OpenFile(\"%s\");", option);
1240    gROOT->ProcessLine(line);
1241    if (fDebug > 1) {
1242       gROOT->ProcessLine("pf->Print()");
1243       Printf(" == proof file name: %s", gFile->GetName());
1244    }   
1245    sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1246    if (fDebug > 1) Printf("=== %s", line);
1247    gROOT->ProcessLine(line);
1248    return gFile;
1249 }   
1250
1251 //______________________________________________________________________________
1252 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1253 {
1254 // Execute analysis.
1255    static Long64_t ncalls = 0;
1256    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1257    if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1258    ncalls++;
1259    if (!fInitOK) {
1260      Error("ExecAnalysis", "Analysis manager was not initialized !");
1261       return;
1262    }   
1263    AliAnalysisTask *task;
1264    // Check if the top tree is active.
1265    if (fTree) {
1266       TIter next(fTasks);
1267    // De-activate all tasks
1268       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1269       AliAnalysisDataContainer *cont = fCommonInput;
1270       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1271       if (!cont) {
1272               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1273          return;
1274       }   
1275       cont->SetData(fTree); // This will notify all consumers
1276       Long64_t entry = fTree->GetTree()->GetReadEntry();
1277       
1278 //
1279 //    Call BeginEvent() for optional input/output and MC services 
1280       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1281       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1282       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1283 //
1284 //    Execute the tasks
1285 //      TIter next1(cont->GetConsumers());
1286       TIter next1(fTopTasks);
1287       while ((task=(AliAnalysisTask*)next1())) {
1288          if (fDebug >1) {
1289             cout << "    Executing task " << task->GetName() << endl;
1290          }   
1291          
1292          task->ExecuteTask(option);
1293       }
1294 //
1295 //    Call FinishEvent() for optional output and MC services 
1296       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1297       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1298       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1299       // Gather system information if requested
1300       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1301          AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
1302       return;
1303    }   
1304    // The event loop is not controlled by TSelector   
1305 //
1306 //  Call BeginEvent() for optional input/output and MC services 
1307    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1308    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1309    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1310    TIter next2(fTopTasks);
1311    while ((task=(AliAnalysisTask*)next2())) {
1312       task->SetActive(kTRUE);
1313       if (fDebug > 1) {
1314          cout << "    Executing task " << task->GetName() << endl;
1315       }   
1316       task->ExecuteTask(option);
1317    }   
1318 //
1319 // Call FinishEvent() for optional output and MC services 
1320    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1321    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1322    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1323 }
1324
1325 //______________________________________________________________________________
1326 void AliAnalysisManager::FinishAnalysis()
1327 {
1328 // Finish analysis.
1329 }
1330
1331 //______________________________________________________________________________
1332 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler*  handler)
1333 {
1334 // Set the input event handler and create a container for it.
1335    fInputEventHandler   = handler;
1336    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1337    Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1338 }
1339
1340 //______________________________________________________________________________
1341 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler*  handler)
1342 {
1343 // Set the input event handler and create a container for it.
1344    fOutputEventHandler   = handler;
1345    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1346    fCommonOutput->SetSpecialOutput();
1347    Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1348 }
1349
1350 //______________________________________________________________________________
1351 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1352 {
1353 // This method is used externally to register output files which are not
1354 // connected to any output container, so that the manager can properly register,
1355 // retrieve or merge them when running in distributed mode. The file names are
1356 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1357    if (fExtraFiles.Length()) fExtraFiles += " ";
1358    fExtraFiles += fname;
1359 }
1360
1361 //______________________________________________________________________________
1362 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1363 {
1364 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1365    char full_path[512];
1366    char ch_url[512];
1367    TObject *pof =  source->FindObject(filename);
1368    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1369       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1370       return kFALSE;
1371    }
1372    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1373    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1374    TString clientUrl(ch_url);
1375    TString full_path_str(full_path);
1376    if (clientUrl.Contains("localhost")){
1377       TObjArray* array = full_path_str.Tokenize ( "//" );
1378       TObjString *strobj = ( TObjString *)array->At(1);
1379       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1380       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1381       full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1382       full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1383       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1384       delete arrayPort;
1385       delete array;
1386    }
1387    if (fDebug > 1) 
1388       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1389    Bool_t gotit = TFile::Cp(full_path_str.Data(), filename); 
1390    if (!gotit)
1391       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1392    return gotit;
1393 }
1394
1395 //______________________________________________________________________________
1396 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1397 {
1398 // Fill analysis type in the provided string.
1399    switch (fMode) {
1400       case kLocalAnalysis:
1401          type = "local";
1402          return;
1403       case kProofAnalysis:
1404          type = "proof";
1405          return;
1406       case kGridAnalysis:
1407          type = "grid";
1408          return;
1409       case kMixingAnalysis:
1410          type = "mix";
1411    }
1412 }
1413
1414 //______________________________________________________________________________
1415 Bool_t AliAnalysisManager::ValidateOutputFiles() const
1416 {
1417 // Validate all output files.
1418    TIter next(fOutputs);
1419    AliAnalysisDataContainer *output;
1420    TDirectory *cdir = gDirectory;
1421    while ((output=(AliAnalysisDataContainer*)next())) {
1422       TString filename = output->GetFileName();
1423       if (filename == "default") {
1424          if (!fOutputEventHandler) continue;
1425          filename = fOutputEventHandler->GetOutputFileName();
1426       }
1427       // Check if the file is closed
1428       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1429       if (file) {
1430          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1431          file->Close();
1432       }
1433       file = TFile::Open(filename);
1434       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1435          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1436          cdir->cd();
1437          return kFALSE;
1438       }
1439       file->Close();
1440    }
1441    cdir->cd();
1442    return kTRUE;
1443 }