fixed compiler problem
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisDataContainer.cxx
CommitLineData
d3106602 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// AliAnalysysDataContainer - Container of data of arbitrary type deriving
21// from TObject used for analysis. A container must be connected to the
22// output data slot of a single analysis task (producer) , but also as
23// input slot for possibly several other tasks (consumers). The connected
24// slots must enforce the same data type as the container (or a derived type).
25// A container becomes the owner of the contained data once this was produced.
26//
27// Containers should be defined by the analysis module using:
28//
29// AliAnalysisModule::AddContainer(const char *name, TClass *type);
30//
31// A container should be connected to a producer:
32
33// AliAnalysisModule::ConnectOutput(AliAnalysisTask *task,
34// AliAnalysisDataContainer *cont)
35// and to its consumers:
36//
37// AliAnalysisModule::ConnectInput(AliAnalysisTask *task, Int_t islot,
38// AliAnalysisDataContainer *cont)
39//
40// The container will create an implicit connection between the producer task
41// and all consumers, which will become sub-tasks of the producer.
42//
43//==============================================================================
44
11026a80 45#include "Riostream.h"
46
d3106602 47#include "TClass.h"
48#include "TTree.h"
49#include "TFile.h"
11026a80 50//#include "AliLog.h"
d3106602 51
52#include "AliAnalysisDataContainer.h"
53#include "AliAnalysisDataSlot.h"
54#include "AliAnalysisTask.h"
55
56ClassImp(AliAnalysisDataContainer)
57
58//______________________________________________________________________________
37a26056 59AliAnalysisDataContainer::AliAnalysisDataContainer() : TNamed(),
60 fDataReady(kFALSE),
61 fOwnedData(kFALSE),
327eaf46 62 fFile(NULL),
37a26056 63 fData(NULL),
64 fType(NULL),
65 fProducer(NULL),
66 fConsumers(NULL)
d3106602 67{
68// Default ctor.
d3106602 69}
37a26056 70
d3106602 71//______________________________________________________________________________
72AliAnalysisDataContainer::AliAnalysisDataContainer(const char *name, TClass *type)
37a26056 73 :TNamed(name,""),
74 fDataReady(kFALSE),
75 fOwnedData(kTRUE),
327eaf46 76 fFile(NULL),
37a26056 77 fData(NULL),
78 fType(type),
79 fProducer(NULL),
80 fConsumers(NULL)
d3106602 81{
82// Normal constructor.
37a26056 83}
84
85//______________________________________________________________________________
86AliAnalysisDataContainer::AliAnalysisDataContainer(const AliAnalysisDataContainer &cont)
87 :TNamed(cont),
88 fDataReady(cont.fDataReady),
89 fOwnedData(kFALSE),
327eaf46 90 fFile(cont.fFile),
37a26056 91 fData(cont.fData),
92 fType(cont.fType),
93 fProducer(cont.fProducer),
94 fConsumers(NULL)
95{
96// Copy ctor.
97 if (cont.fConsumers) {
98 fConsumers = new TObjArray(2);
99 Int_t ncons = cont.fConsumers->GetEntriesFast();
100 for (Int_t i=0; i<ncons; i++) fConsumers->Add(cont.fConsumers->At(i));
101 }
d3106602 102}
103
104//______________________________________________________________________________
105AliAnalysisDataContainer::~AliAnalysisDataContainer()
106{
107// Destructor. Deletes data ! (What happens if data is a container ???)
108 if (fData && fOwnedData) delete fData;
109 if (fConsumers) delete fConsumers;
327eaf46 110 if (fFile) {
111 fFile->Close();
112 delete fFile;
113 }
d3106602 114}
115
116//______________________________________________________________________________
37a26056 117AliAnalysisDataContainer &AliAnalysisDataContainer::operator=(const AliAnalysisDataContainer &cont)
118{
119// Assignment.
120 if (&cont != this) {
121 TNamed::operator=(cont);
122 fDataReady = cont.fDataReady;
123 fOwnedData = kFALSE; // !!! Data owned by cont.
327eaf46 124 fFile = cont.fFile;
37a26056 125 fData = cont.fData;
126 fType = cont.fType;
127 fProducer = cont.fProducer;
128 if (cont.fConsumers) {
129 fConsumers = new TObjArray(2);
130 Int_t ncons = cont.fConsumers->GetEntriesFast();
131 for (Int_t i=0; i<ncons; i++) fConsumers->Add(cont.fConsumers->At(i));
132 }
133 }
134 return *this;
135}
136
137//______________________________________________________________________________
327eaf46 138Bool_t AliAnalysisDataContainer::SetData(TObject *data, Option_t *)
d3106602 139{
140// Set the data as READY only if it was published by the producer.
d3106602 141 // If there is no producer declared, this is a top level container.
142 AliAnalysisTask *task;
327eaf46 143 Bool_t init = kFALSE;
d3106602 144 Int_t i, nc;
145 if (!fProducer) {
327eaf46 146 if (data != fData) init = kTRUE;
d3106602 147 fData = data;
148 fDataReady = kTRUE;
149 if (fConsumers) {
150 nc = fConsumers->GetEntriesFast();
151 for (i=0; i<nc; i++) {
152 task = (AliAnalysisTask*)fConsumers->At(i);
327eaf46 153 task->CheckNotify(init);
d3106602 154 }
155 }
156 return kTRUE;
157 }
158 // Check if it is the producer who published the data
159 if (fProducer->GetPublishedData()==data) {
160 fData = data;
161 fDataReady = kTRUE;
d3106602 162 if (fConsumers) {
163 nc = fConsumers->GetEntriesFast();
164 for (i=0; i<nc; i++) {
165 task = (AliAnalysisTask*)fConsumers->At(i);
166 task->CheckNotify();
167 }
168 }
169 return kTRUE;
170 } else {
11026a80 171 cout<<"Data for container "<<GetName()<<" can be published only by producer task "<<fProducer->GetName()<<endl;
172 //AliWarning(Form("Data for container %s can be published only by producer task %s", GetName(), fProducer->GetName()));
173 return kFALSE;
d3106602 174 }
175}
176
177//______________________________________________________________________________
327eaf46 178void AliAnalysisDataContainer::OpenFile(const char *name, Option_t *option)
d3106602 179{
327eaf46 180// Data will be written to this file at the end of processing.
d3106602 181// Option represent the way the file is accessed: NEW, APPEND, ...
327eaf46 182 if (fFile) {
183 fFile->Close();
184 delete fFile;
185 }
186 fFile = new TFile(name, option);
187 if (fFile->IsZombie()) {
11026a80 188 cout<<"Cannot open file "<<name<<" with option "<<option<<endl;
189 //AliError(Form("Cannot open file %s with option %s",name,option));
327eaf46 190 fFile = 0;
191 }
d3106602 192}
193
194//______________________________________________________________________________
327eaf46 195void AliAnalysisDataContainer::WriteData()
196{
197// Write data to the file.
198 if (fFile) {
199 TDirectory *cursav = gDirectory;
200 fFile->cd();
201 fData->Write();
202// fFile->Write();
203 if (cursav) cursav->cd();
204 }
205}
206
207//______________________________________________________________________________
d3106602 208void AliAnalysisDataContainer::GetEntry(Long64_t ientry)
209{
210// If data is ready and derives from TTree or from TBranch, this will get the
211// requested entry in memory if not already loaded.
212 if (!fDataReady) return;
327eaf46 213 Bool_t istree = fType->InheritsFrom(TTree::Class());
214 if (istree) {
d3106602 215 TTree *tree = (TTree*)fData;
216 if (tree->GetReadEntry() != ientry) tree->GetEntry(ientry);
217 return;
218 }
327eaf46 219 Bool_t isbranch = fType->InheritsFrom(TBranch::Class());
220 if (isbranch) {
d3106602 221 TBranch *branch = (TBranch*)fData;
222 if (branch->GetReadEntry() != ientry) branch->GetEntry(ientry);
223 return;
224 }
225}
226
227//______________________________________________________________________________
228void AliAnalysisDataContainer::SetProducer(AliAnalysisTask *prod, Int_t islot)
229{
230// Set the producer of data. The slot number is required for data type checking.
231 if (fProducer) {
11026a80 232 cout<<"Data container "<<GetName()<<" already has a producer: "<<fProducer->GetName()<<endl;
233 //AliWarning(Form("Data container %s already has a producer: %s",GetName(),fProducer->GetName()));
d3106602 234 }
235 if (fDataReady) {
11026a80 236 cout<<GetName()<<" container contains data - cannot change producer!"<<endl;
237 //AliError(Form("%s container contains data - cannot change producer!", GetName()));
d3106602 238 return;
239 }
240 AliAnalysisDataSlot *slot = prod->GetOutputSlot(islot);
241 if (!slot) {
11026a80 242 cout<<"Producer task "<<prod->GetName()<<" does not have an output #"<<islot<<endl;
243 //AliError(Form("Producer task %s does not have an output #%i", prod->GetName(),islot));
d3106602 244 return;
245 }
246 if (!slot->GetType()->InheritsFrom(fType)) {
11026a80 247 cout<<"Data type "<<slot->GetType()->GetName()<<"for output slot "<<islot<<" of task "<<prod->GetName()<<" does not match container type "<<fType->GetName()<<endl;
248 //AliError(Form("Data type %s for output slot %i of task %s does not match container type %s", slot->GetType()->GetName(),islot,prod->GetName(),fType->GetName()));
d3106602 249 return;
250 }
251
252 fProducer = prod;
253 // Add all consumers as daughter tasks
254 TIter next(fConsumers);
255 AliAnalysisTask *cons;
256 while ((cons=(AliAnalysisTask*)next())) {
257 if (!prod->GetListOfTasks()->FindObject(cons)) prod->Add(cons);
258 }
259}
260
261//______________________________________________________________________________
262void AliAnalysisDataContainer::AddConsumer(AliAnalysisTask *consumer, Int_t islot)
263{
264// Add a consumer for contained data;
265 AliAnalysisDataSlot *slot = consumer->GetInputSlot(islot);
266 if (!slot) {
11026a80 267 cout<<"Consumer task "<< consumer->GetName()<<" does not have an input #"<<islot<<endl;
268 //AliError(Form("Consumer task %s does not have an input #%i", consumer->GetName(),islot));
d3106602 269 return;
270 }
271 if (!slot->GetType()->InheritsFrom(fType)) {
11026a80 272 cout<<"Data type "<<slot->GetType()->GetName()<<" for input slot "<<islot<<" of task "<<consumer->GetName()<<" does not match container type "<<fType->GetName()<<endl;
273 //AliError(Form("Data type %s for input slot %i of task %s does not match container type %s", slot->GetType()->GetName(),islot,consumer->GetName(),fType->GetName()));
d3106602 274 return;
275 }
276
277 if (!fConsumers) fConsumers = new TObjArray(2);
278 fConsumers->Add(consumer);
279 // Add the consumer task to the list of task of the producer
280 if (fProducer && !fProducer->GetListOfTasks()->FindObject(consumer))
281 fProducer->Add(consumer);
282}
283
284//______________________________________________________________________________
285Bool_t AliAnalysisDataContainer::ClientsExecuted() const
286{
287// Check if all client tasks have executed.
288 TIter next(fConsumers);
289 AliAnalysisTask *task;
290 while ((task=(AliAnalysisTask*)next())) {
291 if (!task->HasExecuted()) return kFALSE;
292 }
293 return kTRUE;
294}
295
296//______________________________________________________________________________
297void AliAnalysisDataContainer::DeleteData()
298{
299// Delete data if not needed anymore.
300 if (!fDataReady || !ClientsExecuted()) {
11026a80 301 cout<<"Data not ready or not all clients of container "<<GetName()<<" executed. Data not deleted."<<endl;
302 //AliWarning(Form("Data not ready or not all clients of container %s executed. Data not deleted.", GetName()));
d3106602 303 return;
304 }
305 if (!fOwnedData) {
11026a80 306 cout<<"Data not owned by container "<<GetName()<<". Not deleted."<<endl;
307 //AliWarning(Form("Data not owned by container %s. Not deleted.", GetName()));
d3106602 308 return;
309 }
310 delete fData;
311 fData = 0;
312 fDataReady = kFALSE;
313}
314
315//______________________________________________________________________________
316void AliAnalysisDataContainer::PrintContainer(Option_t *option, Int_t indent) const
317{
318// Print info about this container.
319 TString ind;
320 for (Int_t i=0; i<indent; i++) ind += " ";
321 TString opt(option);
322 opt.ToLower();
323 Bool_t dep = (opt.Contains("dep"))?kTRUE:kFALSE;
324 if (!dep) {
325 printf("%s\n", Form("%sContainer: %s type: %s", ind.Data(), GetName(), fType->GetName()));
326 if (fProducer)
327 printf("%s\n", Form("%s = Data producer: task %s",ind.Data(),fProducer->GetName()));
328 else
329 printf("%s\n", Form("%s= No data producer"));
330 printf("%s", Form("%s = Consumer tasks: "));
331 if (!fConsumers || !fConsumers->GetEntriesFast()) printf("-none-\n");
332 else printf("\n");
333 }
334 TIter next(fConsumers);
335 AliAnalysisTask *task;
336 while ((task=(AliAnalysisTask*)next())) task->PrintTask(option, indent+3);
337}