]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTGlobalTriggerDecision.cxx
bugfix 88038: inconsistent handling of reference counters in library manager
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTGlobalTriggerDecision.cxx
1 // $Id$
2 /**************************************************************************
3  * This file is property of and copyright by the ALICE HLT Project        *
4  * ALICE Experiment at CERN, All rights reserved.                         *
5  *                                                                        *
6  * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
7  *                  for The ALICE HLT Project.                            *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          *
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 /// @file   AliHLTGlobalTriggerDecision.cxx
19 /// @author Artur Szostak <artursz@iafrica.com>
20 /// @date   26 Nov 2008
21 /// @brief  Implementation of the AliHLTGlobalTriggerDecision class.
22 /// 
23 /// The global trigger decision class stores the global HLT decision.
24
25 #include "AliHLTGlobalTriggerDecision.h"
26 #include "Riostream.h"
27 #include "TClass.h"
28 #include "AliHLTMisc.h"
29 #include "AliHLTLogging.h"
30
31 ClassImp(AliHLTGlobalTriggerDecision)
32
33
34 namespace {
35 const char* kgNULLObjMessage =
36   "The global decision object contains NULL pointers in the fContributingTriggers array."
37   " This is unexpected and probably indicates a serious problem.";
38 const char* kgSplitModeMessage =
39   "The global decision object contains NULL pointers in the fInputObjects array."
40   " This means that it was written to a TTree branch with the split-mode > 0."
41   " This causes the custom streamer to be skipped and prevents the"
42   " fInputObjects array to be setup properly. In addition this can cause memory leaks.";
43 };
44
45
46 AliHLTGlobalTriggerDecision::AliHLTGlobalTriggerDecision() :
47 AliHLTTriggerDecision(0, "HLTGlobalTrigger"),
48   fContributingTriggers(AliHLTTriggerDecision::Class()),
49   fInputObjects(),
50   fCounters()
51 {
52   // Default constructor.
53   
54   // We set the ownership to false since the objects are deleted manually by this
55   // class in DeleteInputObjects().
56   fInputObjects.SetOwner(kFALSE);
57 }
58
59
60 AliHLTGlobalTriggerDecision::AliHLTGlobalTriggerDecision(
61     bool result, const AliHLTTriggerDomain& triggerDomain, const char* description
62   ) :
63   AliHLTTriggerDecision(result, "HLTGlobalTrigger", triggerDomain, description),
64   fContributingTriggers(AliHLTTriggerDecision::Class()),
65   fInputObjects(),
66   fCounters()
67 {
68   // Constructor specifying multiple information fields.
69   
70   Result(result);
71   // We set the ownership to false since the objects are deleted manually by this
72   // class in DeleteInputObjects().
73   fInputObjects.SetOwner(kFALSE);
74 }
75
76
77 AliHLTGlobalTriggerDecision::~AliHLTGlobalTriggerDecision()
78 {
79   // Default destructor.
80   
81   DeleteInputObjects();
82 }
83
84
85 void AliHLTGlobalTriggerDecision::Print(Option_t* option) const
86 {
87   // Prints the contents of the trigger decision.
88   
89   TString opt(option);
90   if (opt.Contains("compact"))
91   {
92     cout << "Global ";
93     AliHLTTriggerDecision::Print("");
94   }
95   else if (opt.Contains("short"))
96   {
97     cout << "Global ";
98     AliHLTTriggerDecision::Print(option);
99     cout << "#################### Input trigger decisions ####################" << endl;
100     for (Int_t i = 0; i < NumberOfTriggerInputs(); i++)
101     {
102       if (TriggerInput(i) != NULL)
103       {
104         TriggerInput(i)->Print(option);
105       }
106       else
107       {
108         AliHLTLogging log;
109         log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgNULLObjMessage);
110       }
111     }
112     if (NumberOfTriggerInputs() == 0)
113     {
114       cout << "(none)" << endl;
115     }
116   }
117   else if (opt.Contains("counters"))
118   {
119     cout << "Counter\tValue" << endl;
120     for (Int_t i = 0; i < fCounters.GetSize(); i++)
121     {
122       cout << i << "\t" << fCounters[i] << endl;
123     }
124     if (fCounters.GetSize() == 0)
125     {
126       cout << "(none)" << endl;
127     }
128   }
129   else
130   {
131     cout << "Global ";
132     AliHLTTriggerDecision::Print(option);
133     cout << "#################### Input trigger decisions ####################" << endl;
134     for (Int_t i = 0; i < NumberOfTriggerInputs(); i++)
135     {
136       cout << "-------------------- Input trigger decision " << i << " --------------------" << endl;
137       if (TriggerInput(i) != NULL)
138       {
139         TriggerInput(i)->Print(option);
140       }
141       else
142       {
143         AliHLTLogging log;
144         log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgNULLObjMessage);
145       }
146     }
147     if (NumberOfTriggerInputs() == 0)
148     {
149       cout << "(none)" << endl;
150     }
151     cout << "###################### Other input objects ######################" << endl;
152     for (Int_t i = 0; i < NumberOfInputObjects(); i++)
153     {
154       cout << "------------------------ Input object " << i << " ------------------------" << endl;
155       if (InputObject(i) != NULL)
156       {
157         InputObject(i)->Print(option);
158       }
159       else
160       {
161         AliHLTLogging log;
162         log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage);
163       }
164     }
165     if (NumberOfInputObjects() == 0)
166     {
167       cout << "(none)" << endl;
168     }
169     cout << "#################### Event class counters ####################" << endl;
170     cout << "Counter\tValue" << endl;
171     for (Int_t i = 0; i < fCounters.GetSize(); i++)
172     {
173       cout << i << "\t" << fCounters[i] << endl;
174     }
175     if (fCounters.GetSize() == 0)
176     {
177       cout << "(none)" << endl;
178     }
179   }
180 }
181
182 void AliHLTGlobalTriggerDecision::Copy(TObject &object) const
183 {
184   // copy this to the specified object
185
186   if (object.IsA() == AliHLTMisc::Instance().IsAliESDHLTDecision()) {
187     AliHLTMisc::Instance().Copy(this, &object);
188     return;
189   }
190
191   AliHLTGlobalTriggerDecision* pDecision=dynamic_cast<AliHLTGlobalTriggerDecision*>(&object);
192   if (pDecision)
193   {
194     // copy members if target is a AliHLTGlobalTriggerDecision
195     *pDecision=*this;
196   }
197   // copy the base class
198   AliHLTTriggerDecision::Copy(object);
199 }
200
201 TObject *AliHLTGlobalTriggerDecision::Clone(const char */*newname*/) const
202 {
203   // create a new clone, classname is ignored
204
205   return new AliHLTGlobalTriggerDecision(*this);
206 }
207
208 AliHLTGlobalTriggerDecision::AliHLTGlobalTriggerDecision(const AliHLTGlobalTriggerDecision& src) :
209   AliHLTTriggerDecision(src),
210   fContributingTriggers(AliHLTTriggerDecision::Class()),
211   fInputObjects(),
212   fCounters()
213 {
214   // Copy constructor performs a deep copy.
215   
216   // We set the ownership to false since the objects are deleted manually by this
217   // class in DeleteInputObjects().
218   fInputObjects.SetOwner(kFALSE);
219   
220   *this=src;
221 }
222
223 AliHLTGlobalTriggerDecision& AliHLTGlobalTriggerDecision::operator=(const AliHLTGlobalTriggerDecision& src)
224 {
225   // assignment operator performs a deep copy.
226
227   fContributingTriggers.Delete();
228   for (int triggerInput=0; triggerInput<src.NumberOfTriggerInputs(); triggerInput++) {
229     const AliHLTTriggerDecision* pTriggerObject=src.TriggerInput(triggerInput);
230     if (pTriggerObject != NULL)
231     {
232       // the AddTriggerInput function uses the copy constructor and
233       // makes a new object from the reference
234       AddTriggerInput(*pTriggerObject);
235     }
236     else
237     {
238       AliHLTLogging log;
239       log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgNULLObjMessage);
240     }
241   }
242
243   DeleteInputObjects();
244   for (int inputObject=0; inputObject<src.NumberOfInputObjects(); inputObject++) {
245     const TObject* pInputObject=src.InputObject(inputObject);
246     if (pInputObject != NULL)
247     {
248       // the AddInputObject function uses Clone() and
249       // makes a new object from the reference
250       AddInputObject(pInputObject);
251     }
252     else
253     {
254       AliHLTLogging log;
255       log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage);
256     }
257   }
258   
259   SetCounters(src.Counters());
260
261   return *this;
262 }
263
264
265 void AliHLTGlobalTriggerDecision::AddInputObject(const TObject* object)
266 {
267   // Adds an object to the list of input objects considered in the global trigger.
268   
269   if (object == NULL) return;
270   TObject* obj = object->Clone();
271   obj->SetBit(kCanDelete);
272   fInputObjects.Add(obj);
273 }
274
275
276 void AliHLTGlobalTriggerDecision::AddInputObjectRef(TObject* object, bool own)
277 {
278   // Adds an object to the list of input objects considered in the global trigger.
279   
280   if (object == NULL) return;
281   if (own)
282   {
283     object->SetBit(kCanDelete);
284   }
285   else
286   {
287     object->ResetBit(kCanDelete);
288   }
289   fInputObjects.Add(object);
290 }
291
292
293 void AliHLTGlobalTriggerDecision::SetCounters(const TArrayL64& counters, Long64_t eventCount)
294 {
295   // Sets the counter array.
296   // If the number of events is specified, an additional counter is added at the end.
297   fCounters = counters;
298   if (eventCount>=0) {
299     int size=fCounters.GetSize();
300     fCounters.Set(size+1);
301     fCounters[size]=eventCount;
302   }
303 }
304
305
306 void AliHLTGlobalTriggerDecision::Clear(Option_t* option)
307 {
308   // Clears the trigger domain and resets the decision result.
309   
310   AliHLTTriggerDecision::Clear(option);
311   // because of TClonesArray members in AliHLTTriggerDecision it is not
312   // enough to call Clear. Delete will also invoke the destructor of the
313   // elements which is necessary to do the proper internal cleanup
314   fContributingTriggers.Delete();
315   DeleteInputObjects();
316   fCounters.Set(0);
317 }
318
319
320 TObject* AliHLTGlobalTriggerDecision::FindObject(const char* name) const
321 {
322   // Finds the first object in fContributingTriggers or fInputObjects that has the given name.
323   
324   TObject* result = fContributingTriggers.FindObject(name);
325   if (result != NULL) return result;
326   return fInputObjects.FindObject(name);
327 }
328
329
330 TObject* AliHLTGlobalTriggerDecision::FindObject(const TObject* obj) const
331 {
332   // Finds the first object in fContributingTriggers or fInputObjects that matches
333   // based on a IsEqual() comparison.
334   
335   TObject* result = fContributingTriggers.FindObject(obj);
336   if (result != NULL) return result;
337   return fInputObjects.FindObject(obj);
338 }
339
340
341 void AliHLTGlobalTriggerDecision::DeleteInputObjects()
342 {
343   // Deletes the objects marked with kCanDelete in fInputObjects and clears the array.
344   
345   for (Int_t i = 0; i < NumberOfInputObjects(); i++)
346   {
347     TObject* obj = fInputObjects.UncheckedAt(i);
348     if (obj == NULL)
349     {
350       AliHLTLogging log;
351       log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage);
352       continue;
353     }
354     if (obj->TestBit(kCanDelete)) delete obj;
355   }
356   fInputObjects.Clear();
357 }
358
359
360 void AliHLTGlobalTriggerDecision::MarkInputObjectsAsOwned()
361 {
362   // Marks all input objects as owned.
363
364   // We must mark all the objects that were read into fInputObjects as owned.
365   // Otherwise we will have a memory leak in DeleteInputObjects.
366   bool loggedWarning = false;
367   for (Int_t i = 0; i < fInputObjects.GetEntriesFast(); ++i)
368   {
369     TObject* obj = fInputObjects.UncheckedAt(i);
370     // We must check if the object pointer is NULL. This could happen because the
371     // class dictionary has not been loaded, so the ReadClassBuffer streamer just
372     // silently skips the object but fills the fInputObjects array with a NULL pointer.
373     if (obj == NULL)
374     {
375       fInputObjects.RemoveAt(i);
376       if (not loggedWarning)
377       {
378         AliHLTLogging log;
379         log.LoggingVarargs(kHLTLogWarning, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__,
380           "The global trigger decision contains NULL pointers in the input object array."
381           " This is probably due to the fact that some class dictionaries have not been loaded."
382           " Will just remove the NULL pointer and continue."
383         );
384         loggedWarning = true;  // Prevent multiple warnings, one is enough.
385       }
386     }
387     else
388     {
389       obj->SetBit(kCanDelete);
390     }
391   }
392   // Compress the input object array to prevent any seg-faults due to access of
393   // NULL pointers if the objects were not loaded due to missing dictionaries.
394   fInputObjects.Compress();
395 }
396
397 #if ROOT_VERSION_CODE < ROOT_VERSION(5,26,0)
398 void AliHLTGlobalTriggerDecision::Streamer(TBuffer &b)
399 {
400    // Stream an object of class AliHLTGlobalTriggerDecision.
401
402    if (b.IsReading())
403    {
404      b.ReadClassBuffer(AliHLTGlobalTriggerDecision::Class(), this);
405      MarkInputObjectsAsOwned();
406    }
407    else
408    {
409      b.WriteClassBuffer(AliHLTGlobalTriggerDecision::Class(), this);
410    }
411 }
412 #endif // ROOT version check.