]>
Commit | Line | Data |
---|---|---|
1dbbd625 | 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 | //* Timm Steinbeck <timm@kip.uni-heidelberg.de> * | |
9 | //* for The ALICE HLT Project. * | |
10 | //* * | |
11 | //* Permission to use, copy, modify and distribute this software and its * | |
12 | //* documentation strictly for non-commercial purposes is hereby granted * | |
13 | //* without fee, provided that the above copyright notice appears in all * | |
14 | //* copies and that both the copyright notice and this permission notice * | |
15 | //* appear in the supporting documentation. The authors make no claims * | |
16 | //* about the suitability of this software for any purpose. It is * | |
17 | //* provided "as is" without express or implied warranty. * | |
18 | //************************************************************************** | |
19 | ||
20 | /** @file AliHLTCTPData.cxx | |
21 | @author Matthias Richter | |
22 | @date 2009-08-20 | |
23 | @brief Container for CTP trigger classes and counters | |
24 | */ | |
25 | ||
26 | #include "AliHLTCTPData.h" | |
1462df14 | 27 | #include "AliHLTReadoutList.h" |
1dbbd625 | 28 | #include "TClass.h" |
1dbbd625 | 29 | #include "TObjString.h" |
30 | #include "TFormula.h" | |
31 | ||
32 | /** ROOT macro for the implementation of ROOT specific class methods */ | |
33 | ClassImp(AliHLTCTPData) | |
34 | ||
35 | AliHLTCTPData::AliHLTCTPData() | |
1462df14 | 36 | : TNamed("AliHLTCTPData", "HLT counters for the CTP") |
1dbbd625 | 37 | , AliHLTLogging() |
38 | , fMask(0) | |
1462df14 | 39 | , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses) |
1dbbd625 | 40 | , fCounters() |
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) | |
1462df14 | 53 | , fClassIds(AliHLTReadoutList::Class(), gkNCTPTriggerClasses) |
1dbbd625 | 54 | , fCounters() |
55 | { | |
56 | // see header file for class documentation | |
57 | InitCTPTriggerClasses(parameter); | |
58 | } | |
59 | ||
60 | AliHLTCTPData::~AliHLTCTPData() | |
61 | { | |
62 | // see header file for class documentation | |
63 | fClassIds.Delete(); | |
64 | } | |
65 | ||
66 | int AliHLTCTPData::InitCTPTriggerClasses(const char* ctpString) | |
67 | { | |
68 | // see header file for function documentation | |
69 | if (!ctpString) return -EINVAL; | |
70 | ||
5be104b8 | 71 | HLTImportant("Parameter: %s", ctpString); |
72 | ||
1dbbd625 | 73 | fMask=0; |
74 | fClassIds.Delete(); | |
75 | fClassIds.ExpandCreate(gkNCTPTriggerClasses); | |
76 | ||
77 | // general format of the CTP_TRIGGER_CLASS parameter | |
78 | // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,... | |
1dbbd625 | 79 | HLTDebug(": %s", ctpString); |
80 | TString string=ctpString; | |
1462df14 | 81 | if (string.BeginsWith("CTP_TRIGGER_CLASS=")) string.ReplaceAll("CTP_TRIGGER_CLASS=", ""); |
1dbbd625 | 82 | TObjArray* classEntries=string.Tokenize(","); |
83 | if (classEntries) { | |
1462df14 | 84 | enum {kBit=0, kName, kDetectors}; |
1dbbd625 | 85 | for (int i=0; i<classEntries->GetEntries(); i++) { |
86 | TString entry=((TObjString*)classEntries->At(i))->GetString(); | |
87 | TObjArray* entryParams=entry.Tokenize(":"); | |
88 | if (entryParams) { | |
89 | if (entryParams->GetEntries()==3 && | |
1462df14 | 90 | (((TObjString*)entryParams->At(kBit))->GetString()).IsDigit()) { |
91 | int index=(((TObjString*)entryParams->At(kBit))->GetString()).Atoi(); | |
1dbbd625 | 92 | if (index<gkNCTPTriggerClasses) { |
1462df14 | 93 | AliHLTReadoutList* pCTPClass=dynamic_cast<AliHLTReadoutList*>(fClassIds.At(index)); |
94 | if (pCTPClass) { | |
95 | fMask|=(AliHLTUInt64_t)0x1 << index; | |
96 | pCTPClass->SetTitle("CTP Class"); | |
97 | pCTPClass->SetName((((TObjString*)entryParams->At(kName))->GetString()).Data()); | |
98 | TObjArray* detectors=(((TObjString*)entryParams->At(kDetectors))->GetString()).Tokenize("-"); | |
99 | if (detectors) { | |
100 | for (int dix=0; dix<detectors->GetEntriesFast(); dix++) { | |
101 | if (!(((TObjString*)detectors->At(dix))->GetString()).IsDigit()) { | |
102 | HLTError("invalid detector list format: trigger class entry %s", entry.Data()); | |
103 | break; | |
104 | } | |
105 | // see AliHLTReadoutList::EDetectorId for defines of detectors | |
106 | pCTPClass->Enable(0x1<<(((TObjString*)detectors->At(dix))->GetString()).Atoi()); | |
107 | } | |
108 | delete detectors; | |
109 | } | |
110 | } else { | |
111 | } | |
1dbbd625 | 112 | } else { |
113 | // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses) | |
1462df14 | 114 | HLTError("invalid trigger class entry %s, index width of trigger bitfield exceeded (%d)", entry.Data(), gkNCTPTriggerClasses); |
1dbbd625 | 115 | } |
116 | } else { | |
117 | HLTError("invalid trigger class entry %s", entry.Data()); | |
118 | } | |
119 | delete entryParams; | |
120 | } | |
121 | } | |
122 | delete classEntries; | |
123 | } | |
124 | ||
125 | ResetCounters(); | |
126 | ||
127 | return 0; | |
128 | } | |
129 | ||
130 | bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, AliHLTComponentTriggerData& trigData) const | |
131 | { | |
132 | // see header file for function documentation | |
133 | if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) { | |
134 | HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData)); | |
135 | return false; | |
136 | } | |
137 | ||
138 | // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH | |
139 | AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData); | |
5be104b8 | 140 | AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff; |
1dbbd625 | 141 | triggerMask<<=32; |
142 | triggerMask|=evtData->fCommonHeader[5]; | |
143 | ||
144 | if (fMask!=0 && (triggerMask & fMask)==0) { | |
5be104b8 | 145 | HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask); |
146 | for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]); | |
1dbbd625 | 147 | return false; |
148 | } | |
149 | ||
150 | // use a TFormula to interprete the expression | |
151 | // all classname are replaced by '[n]' which means the n'th parameter in the formula | |
152 | // the parameters are set to 0 or 1 depending on the bit in the trigger mask | |
153 | // | |
154 | // TODO: this will most likely fail for class names like 'base', 'baseA', 'baseB' | |
155 | // the class names must be fully unique, none must be contained as substring in | |
156 | // another class name. Probably not needed for the moment but needs to be extended. | |
157 | vector<Double_t> par; | |
158 | TString condition=expression; | |
159 | for (int i=0; i<gkNCTPTriggerClasses; i++) { | |
160 | const char* className=Name(i); | |
161 | if (className && strlen(className)>0) { | |
162 | //HLTDebug("checking trigger class %s", className.Data()); | |
163 | if (condition.Contains(className)) { | |
164 | TString replace; replace.Form("[%d]", par.size()); | |
165 | //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data()); | |
166 | condition.ReplaceAll(className, replace); | |
167 | if (triggerMask&((AliHLTUInt64_t)0x1<<i)) par.push_back(1.0); | |
168 | else par.push_back(0.0); | |
169 | } | |
170 | } | |
171 | } | |
172 | ||
173 | TFormula form("trigger expression", condition); | |
174 | if (form.Compile()!=0) { | |
175 | HLTError("invalid expression %s", expression); | |
176 | return false; | |
177 | } | |
178 | if (form.EvalPar(&par[0], &par[0])>0.5) return true; | |
179 | return false; | |
180 | } | |
181 | ||
182 | void AliHLTCTPData::ResetCounters() | |
183 | { | |
184 | // see header file for function documentation | |
185 | fCounters.Set(gkNCTPTriggerClasses); | |
186 | fCounters.Reset(); | |
187 | } | |
188 | ||
189 | int AliHLTCTPData::Index(const char* name) const | |
190 | { | |
191 | // see header file for function documentation | |
192 | TObject* obj=fClassIds.FindObject(name); | |
193 | return obj!=NULL?fClassIds.IndexOf(obj):-1; | |
194 | } | |
195 | ||
196 | void AliHLTCTPData::Increment(const char* classIds) | |
197 | { | |
198 | // see header file for function documentation | |
199 | TString string=classIds; | |
200 | TObjArray* classEntries=string.Tokenize(","); | |
201 | if (classEntries) { | |
202 | for (int i=0; i<classEntries->GetEntries(); i++) { | |
203 | int index=Index(((TObjString*)classEntries->At(i))->GetString().Data()); | |
204 | if (index>=0 && index<fCounters.GetSize()) fCounters[index]++; | |
205 | } | |
206 | delete classEntries; | |
207 | } | |
208 | } | |
209 | ||
210 | void AliHLTCTPData::Increment(AliHLTUInt64_t triggerPattern) | |
211 | { | |
212 | // see header file for function documentation | |
213 | AliHLTUInt64_t pattern=triggerPattern&fMask; | |
214 | for (int i=0; i<fCounters.GetSize(); i++) { | |
215 | if ((pattern&((AliHLTUInt64_t)0x1<<i))==0) continue; | |
216 | fCounters[i]++; | |
217 | } | |
218 | } | |
219 | ||
220 | void AliHLTCTPData::Increment(int classIdx) | |
221 | { | |
222 | // see header file for function documentation | |
223 | if (classIdx<fCounters.GetSize() && | |
224 | (fMask&((AliHLTUInt64_t)0x1<<classIdx))) { | |
225 | fCounters[classIdx]++; | |
226 | } | |
227 | ||
228 | } | |
229 | ||
230 | int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData) | |
231 | { | |
232 | // see header file for function documentation | |
233 | if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) { | |
234 | HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData)); | |
235 | return -EBADF; | |
236 | } | |
237 | ||
238 | // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH | |
239 | AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData); | |
5be104b8 | 240 | AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff; |
1dbbd625 | 241 | triggerMask<<=32; |
242 | triggerMask|=evtData->fCommonHeader[5]; | |
243 | ||
244 | if (fMask!=0 && (triggerMask & fMask)==0) { | |
245 | HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask); | |
5be104b8 | 246 | for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]); |
1dbbd625 | 247 | } |
248 | Increment(triggerMask); | |
249 | return 0; | |
250 | } | |
251 | ||
252 | AliHLTUInt64_t AliHLTCTPData::Counter(int index) const | |
253 | { | |
254 | // see header file for function documentation | |
255 | if (index>=0 && index<Counters().GetSize()) return Counters()[index]; | |
256 | return 0; | |
257 | } | |
258 | ||
259 | AliHLTUInt64_t AliHLTCTPData::Counter(const char* classId) const | |
260 | { | |
261 | // see header file for function documentation | |
262 | return Counter(Index(classId)); | |
263 | } | |
264 | ||
265 | const char* AliHLTCTPData::Name(int index) const | |
266 | { | |
267 | // see header file for function documentation | |
268 | if (index>fClassIds.GetLast()) return NULL; | |
269 | return fClassIds.At(index)->GetName(); | |
270 | } | |
271 | ||
1462df14 | 272 | AliHLTEventDDL AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& trigData) const |
273 | { | |
274 | // see header file for function documentation | |
275 | if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) { | |
276 | HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData)); | |
277 | AliHLTEventDDL dummy; | |
278 | memset(&dummy, 0, sizeof(AliHLTEventDDL)); | |
279 | return dummy; | |
280 | } | |
281 | ||
282 | // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH | |
283 | AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData); | |
5be104b8 | 284 | AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6]&0x3ffff; |
1462df14 | 285 | triggerMask<<=32; |
286 | triggerMask|=evtData->fCommonHeader[5]; | |
287 | ||
5be104b8 | 288 | if (fMask!=0 && (triggerMask & fMask)==0) { |
289 | HLTWarning("invalid trigger mask 0x%llx, unknown CTP trigger, initialized 0x%llx", triggerMask, fMask); | |
290 | for (int i=0; i<8; i++) HLTWarning("\t CDH[%d]=0x%lx", i, evtData->fCommonHeader[i]); | |
291 | } | |
292 | ||
1462df14 | 293 | // take an 'OR' of all active trigger classes |
294 | AliHLTReadoutList list; | |
295 | for (int i=0; i<gkNCTPTriggerClasses; i++) { | |
296 | if (i>fClassIds.GetLast()) break; | |
297 | if ((triggerMask&((AliHLTUInt64_t)0x1<<i))==0) continue; | |
5be104b8 | 298 | AliHLTReadoutList* tcrl=(AliHLTReadoutList*)fClassIds.At(i); |
299 | // 2009-08-27: this is a temorary bugfix: | |
300 | // the operator functions of the AliHLTReadoutList class did not work | |
301 | // when running online on the HLT cluster. The fix for the moment is | |
302 | // to send out the readout list only for the first matching trigger | |
303 | // class instead of merging the list. This is sufficient for the | |
304 | // current trigger setups but needs to be corrected | |
305 | return *tcrl; | |
306 | list|=*tcrl; | |
1462df14 | 307 | } |
308 | ||
309 | return list; | |
310 | } | |
311 | ||
1dbbd625 | 312 | void AliHLTCTPData::Print(Option_t* /*option*/) const |
313 | { | |
314 | // see header file for function documentation | |
315 | cout << "CTP counters:" << endl; | |
316 | int count=0; | |
317 | for (int i=0; i<gkNCTPTriggerClasses; i++) { | |
318 | if (i>=Counters().GetSize()) break; | |
319 | if (i>fClassIds.GetLast()) break; | |
320 | if ((fMask&((AliHLTUInt64_t)0x1<<i))==0) continue; | |
321 | count++; | |
322 | cout << "\t" << i << "\t" << Name(i) << "\t" << Counter(i) << endl; | |
323 | } | |
324 | if (count==0) cout << "\t(none)" << endl; | |
325 | } |