]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTCTPData.cxx
adding protection in copy constructor: check for source array size
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTCTPData.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /** @file   AliHLTCTPData.cxx
20     @author Matthias Richter
21     @date   2009-08-20
22     @brief  Container for CTP trigger classes and counters
23 */
24
25 #include "AliHLTCTPData.h"
26 #include "AliHLTReadoutList.h"
27 #include "TClass.h"
28 #include "TObjString.h"
29 #include "TFormula.h"
30
31 /** ROOT macro for the implementation of ROOT specific class methods */
32 ClassImp(AliHLTCTPData)
33
34 AliHLTCTPData::AliHLTCTPData()
35   : TNamed("AliHLTCTPData", "HLT counters for the CTP")
36   , AliHLTLogging()
37   , fMask(0)
38   , fTriggers(0)
39   , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
40   , fCounters(gkNCTPTriggerClasses)
41 {
42   // see header file for class documentation
43   // or
44   // refer to README to build package
45   // or
46   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
47 }
48
49 AliHLTCTPData::AliHLTCTPData(const char* parameter)
50   : TNamed("AliHLTCTPData", "HLT counters for the CTP")
51   , AliHLTLogging()
52   , fMask(0)
53   , fTriggers(0)
54   , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses)
55   , fCounters(gkNCTPTriggerClasses)
56 {
57   // see header file for class documentation
58   InitCTPTriggerClasses(parameter);
59 }
60
61 AliHLTCTPData::~AliHLTCTPData()
62 {
63   // see header file for class documentation
64   fClassIds.Delete();
65 }
66
67 AliHLTCTPData::AliHLTCTPData(const AliHLTCTPData& src)
68   : TNamed(src.GetName(), src.GetTitle())
69   , AliHLTLogging()
70   , fMask(src.Mask())
71   , fTriggers(src.fTriggers)
72   , fClassIds(src.fClassIds)
73   , fCounters(src.Counters())
74 {
75   // see header file for class documentation
76 }
77
78 AliHLTCTPData& AliHLTCTPData::operator=(const AliHLTCTPData& src)
79 {
80   // see header file for class documentation
81   if (this!=&src) {
82     SetName(src.GetName());
83     SetTitle(src.GetTitle());
84     fMask=src.Mask();
85     fClassIds.Delete();
86     fClassIds.ExpandCreate(gkNCTPTriggerClasses);
87     for (int i=0; i<gkNCTPTriggerClasses; i++) {
88       if (i>src.fClassIds.GetLast()) break;
89       ((TNamed*)fClassIds.At(i))->SetName(src.fClassIds.At(i)->GetName());
90       ((TNamed*)fClassIds.At(i))->SetTitle(src.fClassIds.At(i)->GetTitle());
91     }
92     fCounters=src.Counters();
93   }
94
95   return *this;
96 }
97
98 int AliHLTCTPData::Add(const AliHLTCTPData& src, int factor, int &skipped)
99 {
100   // see header file for class documentation
101   
102   skipped=0;
103   for (int i=0; i<gkNCTPTriggerClasses; i++) {
104     TString c;
105     c=fClassIds.At(i)->GetName();
106     if (c.IsNull()) continue;
107     if (c.CompareTo(src.fClassIds.At(i)->GetName())==0) {
108       fCounters[i]+=factor*src.Counter(i);
109     } else {
110       skipped++;
111     }
112   }
113   return 0;
114 }
115
116 AliHLTCTPData& AliHLTCTPData::operator += (const AliHLTCTPData& src)
117 {
118   // see header file for class documentation
119   
120   int nofInconsistencies=0;
121   Add(src, 1, nofInconsistencies);
122   if (nofInconsistencies>0) {
123     HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
124   }
125   return *this;
126 }
127
128 AliHLTCTPData& AliHLTCTPData::operator -= (const AliHLTCTPData& src)
129 {
130   // see header file for class documentation
131   
132   int nofInconsistencies=0;
133   Add(src, -1, nofInconsistencies);
134   if (nofInconsistencies>0) {
135     HLTError("Inconsistent operants: skipping %d of %d CTP classes for operation", nofInconsistencies, gkNCTPTriggerClasses);
136   }
137   return *this;
138 }
139
140 AliHLTCTPData AliHLTCTPData::operator + (const AliHLTCTPData& src) const
141 {
142   // see header file for class documentation
143
144   AliHLTCTPData result(*this);
145   result+=src;
146   return result;
147 }
148
149 AliHLTCTPData AliHLTCTPData::operator - (const AliHLTCTPData& src) const
150 {
151   // see header file for class documentation
152
153   AliHLTCTPData result(*this);
154   result-=src;
155   return result;
156 }
157
158 int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString)
159 {
160   // see header file for function documentation
161   if (!ctpString) return -EINVAL;
162
163   HLTImportant("Parameter: %s", ctpString);
164
165   fMask=0;
166   fClassIds.Delete();
167   fClassIds.ExpandCreate(gkNCTPTriggerClasses);
168
169   // general format of the CTP_TRIGGER_CLASS parameter
170   // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
171   HLTDebug(": %s", ctpString);
172   TString string=ctpString;
173   if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", "");
174   TObjArray* classEntries=string.Tokenize(",");
175   if (classEntries) {
176     enum {kBit=0, kName, kDetectors};
177     for (int i=0; i<classEntries->GetEntriesFast(); i++) {
178       TString entry=((TObjString*)classEntries->At(i))->GetString();
179       TObjArray* entryParams=entry.Tokenize(":");
180       if (entryParams) {
181         if (entryParams->GetEntriesFast()==3 &&
182             (((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) {
183           int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi();
184           if (index<gkNCTPTriggerClasses) {
185             AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index));
186             if (pCTPClass) {
187               fMask|=(AliHLTUInt64_t)0x1 << index;
188               pCTPClass->SetTitle("CTP Class");
189               pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data());
190               TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-");
191               if (detectors) {
192                 for (int dix=0; dix<detectors->GetEntriesFast(); dix++) {
193                   if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) {
194                     HLTError("invalid detector list format: trigger class entry %s", entry.Data());
195                     break;
196                   }
197                   // see AliHLTReadoutList::EDetectorId for defines of detectors
198                   pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi());
199                 }
200                 delete detectors;
201               }
202             } else {
203             }
204           } else {
205             // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses)
206             HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses);
207           }
208         } else {
209           HLTError("invalid trigger class entry %s", entry.Data());
210         }
211         delete entryParams;
212       }
213     }
214     delete classEntries;
215   }
216
217   ResetCounters();
218
219   return 0;
220 }
221
222 AliHLTUInt64_t AliHLTCTPData::ActiveTriggers(const AliHLTComponentTriggerData& trigData)
223 {
224   // extract active triggers from the trigger data
225  
226   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) return (AliHLTUInt64_t)0;
227
228   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
229   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
230   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
231   triggerMask<<=32;
232   triggerMask|=evtData->fCommonHeader[5];
233   return triggerMask;
234 }
235
236 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, const AliHLTComponentTriggerData& trigData) const
237 {
238   // see header file for function documentation
239   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
240     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
241     return false;
242   }
243
244   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
245   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
246   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
247   triggerMask<<=32;
248   triggerMask|=evtData->fCommonHeader[5];
249
250   if (fMask!=0 && (triggerMask & fMask)==0) {
251     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
252     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
253     return false;
254   }
255
256   return EvaluateCTPTriggerClass(expression, triggerMask);
257 }
258
259 bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTUInt64_t triggerMask) const
260 {
261   // see header file for function documentation
262
263   // use a TFormula to interprete the expression
264   // all classname are replaced by '[n]' which means the n'th parameter in the formula
265   // the parameters are set to 0 or 1 depending on the bit in the trigger mask
266   //
267   // TODO: this will most likely fail for class names like 'base', 'baseA', 'baseB'
268   // the class names must be fully unique, none must be contained as substring in
269   // another class name. Probably not needed for the moment but needs to be extended.
270   vector<Double_t> par;
271   TString condition=expression;
272   for (int i=0; i<gkNCTPTriggerClasses; i++) {
273     const char* className=Name(i);
274     if (className && strlen(className)>0) {
275       //HLTDebug("checking trigger class %s", className.Data());
276       if (condition.Contains(className)) {
277         TString replace; replace.Form("[%d]", par.size());
278         //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
279         condition.ReplaceAll(className, replace);
280         if (triggerMask&((AliHLTUInt64_t)0x1<<i)) par.push_back(1.0);
281         else par.push_back(0.0);
282       }
283     }
284   }
285
286   TFormula form("trigger expression", condition);
287   if (form.Compile()!=0) {
288     HLTError("invalid expression %s", expression);
289     return false;
290   }
291   if (form.EvalPar(&par[0], &par[0])>0.5) return true;
292   return false;
293 }
294
295 void AliHLTCTPData::ResetCounters()
296 {
297   // see header file for function documentation
298   fCounters.Set(gkNCTPTriggerClasses);
299   fCounters.Reset();
300 }
301
302 int AliHLTCTPData::Index(const char* name) const
303 {
304   // see header file for function documentation
305   TObject* obj=fClassIds.FindObject(name);
306   return obj!=NULL?fClassIds.IndexOf(obj):-1;
307 }
308
309 void AliHLTCTPData::Increment(const char* classIds)
310 {
311   // see header file for function documentation
312   TString string=classIds;
313   TObjArray* classEntries=string.Tokenize(",");
314   if (classEntries) {
315     for (int i=0; i<classEntries->GetEntriesFast(); i++) {
316       int index=Index(((TObjString*)classEntries->At(i))->GetString().Data());
317       if (index>=0 && index<fCounters.GetSize()) fCounters[index]++;
318     }
319     delete classEntries;
320   }
321 }
322
323 void AliHLTCTPData::Increment(AliHLTUInt64_t triggerPattern)
324 {
325   // see header file for function documentation
326   AliHLTUInt64_t pattern=triggerPattern&fMask;
327   for (int i=0; i<fCounters.GetSize(); i++) {
328     if ((pattern&((AliHLTUInt64_t)0x1<<i))==0) continue;
329     fCounters[i]++;    
330   }
331 }
332
333 void AliHLTCTPData::Increment(int classIdx)
334 {
335   // see header file for function documentation
336   if (classIdx<fCounters.GetSize() &&
337       (fMask&((AliHLTUInt64_t)0x1<<classIdx))) {
338     fCounters[classIdx]++;    
339   }
340   
341 }
342
343 int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
344 {
345   // see header file for function documentation
346   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
347     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
348     return -EBADF;
349   }
350
351   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
352   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
353   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
354   triggerMask<<=32;
355   triggerMask|=evtData->fCommonHeader[5];
356
357   if (fMask!=0 && (triggerMask & fMask)==0) {
358     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
359     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
360   }
361   Increment(triggerMask);
362   return 0;
363 }
364
365 AliHLTUInt64_t AliHLTCTPData::Counter(int index) const
366 {
367   // see header file for function documentation
368   if (index>=0 && index<Counters().GetSize()) return Counters()[index];
369   return 0;
370 }
371
372 AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const
373 {
374   // see header file for function documentation
375   return Counter(Index(classId));
376 }
377
378 const char* AliHLTCTPData::Name(int index) const
379 {
380   // see header file for function documentation
381   if (index>fClassIds.GetLast()) return NULL;
382   return fClassIds.At(index)->GetName();
383 }
384
385 AliHLTEventDDL AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const
386 {
387   // see header file for function documentation
388   if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
389     HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
390     AliHLTEventDDL dummy;
391     memset(&dummy, 0, sizeof(AliHLTEventDDL));
392     return dummy;
393   }
394
395   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
396   AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
397   AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff;
398   triggerMask<<=32;
399   triggerMask|=evtData->fCommonHeader[5];
400
401   if (fMask!=0 && (triggerMask & fMask)==0) {
402     HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask);
403     for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]);
404   }
405
406   return ReadoutList(triggerMask);
407 }
408
409 AliHLTEventDDL AliHLTCTPData::ReadoutList(AliHLTUInt64_t  triggerMask) const
410 {
411   // take an 'OR' of all active trigger classes 
412   AliHLTReadoutList list;
413   for (int i=0; i<gkNCTPTriggerClasses; i++) {
414     if (i>fClassIds.GetLast()) break;
415     if ((triggerMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
416     AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i);
417     list.OrEq(*tcrl);
418   }
419
420   return list;
421 }
422
423
424 void AliHLTCTPData::Print(Option_t* /*option*/) const
425 {
426   // see header file for function documentation
427   cout << GetTitle() << endl;
428   cout << "\tactive trigger mask: 0x" << hex << fTriggers << dec << endl;
429   int count=0;
430   for (int i=0; i<gkNCTPTriggerClasses; i++) {
431     if (i>=Counters().GetSize()) break;
432     if (i>fClassIds.GetLast()) break;
433     if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue;
434     count++;
435     cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl;
436   }
437   if (count==0) cout << "\t(none)" << endl;
438 }