]>
Commit | Line | Data |
---|---|---|
81d62bb4 | 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 AliHLTGlobalTriggerWrapper.cxx | |
19 | /// @author Artur Szostak <artursz@iafrica.com> | |
20 | /// @date 28 Oct 2009 | |
21 | /// @brief Implementation of the AliHLTGlobalTriggerWrapper interface class. | |
22 | /// | |
23 | /// The AliHLTGlobalTriggerWrapper class is used to interface with an interpreted | |
24 | /// class deriving from AliHLTGlobalTrigger. This is used when the global trigger | |
25 | /// component is using CINT to interpret the trigger logic. The wrapper is necessary | |
26 | /// to be able to call interpreted code from compiled code. | |
27 | ||
28 | #include "AliHLTGlobalTriggerWrapper.h" | |
29 | #include "TArrayL64.h" | |
30 | #include "TClass.h" | |
31 | #include "TInterpreter.h" | |
faf00b0d | 32 | #if ROOT_VERSION_CODE < ROOT_VERSION(5,99,0) |
1b820a65 | 33 | #include "TCint.h" |
faf00b0d | 34 | # define LAST_ERR_LINENO G__lasterror_linenum() |
35 | #else | |
36 | # define LAST_ERR_LINENO 0 | |
37 | #endif | |
81d62bb4 | 38 | |
39 | ClassImp(AliHLTGlobalTriggerWrapper) | |
40 | ||
41 | ||
325e5e42 | 42 | namespace |
43 | { | |
44 | /// Variable to store the error message if an error occured in CINT when interpreting code. | |
45 | TString gCINTErrorMessage = ""; | |
46 | ||
47 | /** | |
48 | * This routine is the callback for the CINT interpreter when it finds a syntax error | |
49 | * in the source code generated by the AliHLTGlobalTriggerComponent class. | |
50 | */ | |
51 | void AliHLTOnErrorInCINT(char* message) | |
52 | { | |
53 | gCINTErrorMessage += message; | |
54 | } | |
55 | ||
56 | } // end of namespace | |
57 | ||
58 | ||
81d62bb4 | 59 | AliHLTGlobalTriggerWrapper::AliHLTGlobalTriggerWrapper(const char* classname) : |
60 | AliHLTGlobalTrigger(), | |
61 | AliHLTLogging(), | |
62 | fClass(NULL), | |
63 | fObject(NULL), | |
64 | fFillFromMenuCall(), | |
65 | fNewEventCall(), | |
66 | fAddCall(), | |
67 | fCalculateTriggerDecisionCall(), | |
68 | fGetCountersCall(), | |
325e5e42 | 69 | fSetCountersCall(), |
70 | fCallFailed(false) | |
81d62bb4 | 71 | { |
72 | // The default constructor. | |
73 | ||
74 | fClass = TClass::GetClass(classname); | |
75 | if (fClass == NULL) | |
76 | { | |
77 | HLTError("Could not find class information for '%s'.", classname); | |
78 | return; | |
79 | } | |
80 | fFillFromMenuCall.InitWithPrototype(fClass, "FillFromMenu", "const AliHLTTriggerMenu&"); | |
81 | if (not fFillFromMenuCall.IsValid()) | |
82 | { | |
83 | HLTError("Could not initialise method call object for class '%s' and method FillFromMenu.", classname); | |
84 | return; | |
85 | } | |
86 | fNewEventCall.InitWithPrototype(fClass, "NewEvent", " "); // Must have single whitespace in last parameter or we get a segfault in G__interpret_func. | |
87 | if (not fNewEventCall.IsValid()) | |
88 | { | |
89 | HLTError("Could not initialise method call object for class '%s' and method NewEvent.", classname); | |
90 | return; | |
91 | } | |
92 | fAddCall.InitWithPrototype(fClass, "Add", "const TObject*, const AliHLTComponentDataType&, AliHLTUInt32_t"); | |
93 | if (not fAddCall.IsValid()) | |
94 | { | |
95 | HLTError("Could not initialise method call object for class '%s' and method Add.", classname); | |
96 | return; | |
97 | } | |
f925a066 | 98 | fCalculateTriggerDecisionCall.InitWithPrototype(fClass, "CalculateTriggerDecision", "bool&, AliHLTTriggerDomain&, TString&"); |
81d62bb4 | 99 | if (not fCalculateTriggerDecisionCall.IsValid()) |
100 | { | |
101 | HLTError("Could not initialise method call object for class '%s' and method CalculateTriggerDecision.", classname); | |
102 | return; | |
103 | } | |
104 | fGetCountersCall.InitWithPrototype(fClass, "GetCounters", " "); // Must have single whitespace in last parameter or we get a segfault in G__interpret_func. | |
105 | if (not fGetCountersCall.IsValid()) | |
106 | { | |
107 | HLTError("Could not initialise method call object for class '%s' and method GetCounters.", classname); | |
108 | return; | |
109 | } | |
110 | fSetCountersCall.InitWithPrototype(fClass, "SetCounters", "TArrayL64&"); | |
111 | if (not fSetCountersCall.IsValid()) | |
112 | { | |
113 | HLTError("Could not initialise method call object for class '%s' and method SetCounters.", classname); | |
114 | return; | |
115 | } | |
116 | fObject = fClass->New(); | |
117 | if (fObject == NULL) | |
118 | { | |
119 | HLTError("Could not create a new object of type '%s'.", classname); | |
120 | } | |
325e5e42 | 121 | |
f2655396 | 122 | // The following is a workaround for casting void* to void (*)(), i.e. a pointer to object to |
123 | // a pointer to function. Unfortunately the G__set_errmsgcallback routine interface is defined | |
124 | // using a pointer to object so this workaround is necessary. | |
125 | // We check that the two types are the same size. If they are not then such an operation is | |
126 | // unsafe on the platform on which we are running and will not be performed. | |
127 | union | |
128 | { | |
129 | void* fPtr; | |
130 | void (*fFuncPtr)(char*); | |
131 | }; | |
132 | fFuncPtr = AliHLTOnErrorInCINT; | |
133 | if (sizeof(fPtr) == sizeof(fFuncPtr)) | |
134 | { | |
1b820a65 | 135 | gInterpreter->SetErrmsgcallback(fPtr); |
f2655396 | 136 | } |
137 | else | |
138 | { | |
139 | HLTWarning("On this platform a pointer to function and pointer to object are different sizes." | |
140 | " For this reason we cannot use the G__set_errmsgcallback CINT API call in a safe way so all" | |
141 | " error messages generated by CINT will not be captured or logged in the HLT system." | |
142 | ); | |
143 | } | |
81d62bb4 | 144 | } |
145 | ||
146 | ||
147 | AliHLTGlobalTriggerWrapper::~AliHLTGlobalTriggerWrapper() | |
148 | { | |
149 | // Default destructor. | |
150 | ||
151 | fClass->Destructor(fObject); | |
faf00b0d | 152 | #if ROOT_VERSION_CODE < ROOT_VERSION(5,99,0) |
f0da6a36 | 153 | G__set_errmsgcallback(NULL); |
faf00b0d | 154 | #endif |
81d62bb4 | 155 | } |
156 | ||
157 | ||
158 | void AliHLTGlobalTriggerWrapper::FillFromMenu(const AliHLTTriggerMenu& menu) | |
159 | { | |
160 | // Fills internal values from the trigger menu. | |
161 | ||
325e5e42 | 162 | fCallFailed = false; |
81d62bb4 | 163 | struct Params |
164 | { | |
165 | const void* fMenu; | |
166 | } params; | |
167 | params.fMenu = &menu; | |
168 | fFillFromMenuCall.SetParamPtrs(¶ms, 1); | |
325e5e42 | 169 | gCINTErrorMessage = ""; |
81d62bb4 | 170 | fFillFromMenuCall.Execute(fObject); |
325e5e42 | 171 | if (gCINTErrorMessage != "") |
81d62bb4 | 172 | { |
325e5e42 | 173 | fCallFailed = true; |
174 | HLTError(gCINTErrorMessage.Data()); | |
faf00b0d | 175 | HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), LAST_ERR_LINENO); |
81d62bb4 | 176 | } |
177 | } | |
178 | ||
179 | ||
180 | void AliHLTGlobalTriggerWrapper::NewEvent() | |
181 | { | |
182 | // Clears the internal buffers for a new event. | |
183 | ||
325e5e42 | 184 | fCallFailed = false; |
185 | gCINTErrorMessage = ""; | |
81d62bb4 | 186 | fNewEventCall.Execute(fObject); |
325e5e42 | 187 | if (gCINTErrorMessage != "") |
81d62bb4 | 188 | { |
325e5e42 | 189 | fCallFailed = true; |
190 | HLTError(gCINTErrorMessage.Data()); | |
faf00b0d | 191 | HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), LAST_ERR_LINENO); |
81d62bb4 | 192 | } |
193 | } | |
194 | ||
195 | ||
196 | void AliHLTGlobalTriggerWrapper::Add( | |
197 | const TObject* object, const AliHLTComponentDataType& type, | |
198 | AliHLTUInt32_t spec | |
199 | ) | |
200 | { | |
201 | // Adds parameters from the object to the internal buffers and variables. | |
202 | ||
325e5e42 | 203 | fCallFailed = false; |
81d62bb4 | 204 | struct Params |
205 | { | |
206 | const void* fObj; | |
207 | const void* fType; | |
208 | long fSpec; | |
209 | } params; | |
210 | params.fObj = object; | |
211 | params.fType = &type; | |
212 | params.fSpec = spec; | |
213 | fAddCall.SetParamPtrs(¶ms, 3); | |
325e5e42 | 214 | gCINTErrorMessage = ""; |
81d62bb4 | 215 | fAddCall.Execute(fObject); |
325e5e42 | 216 | if (gCINTErrorMessage != "") |
81d62bb4 | 217 | { |
325e5e42 | 218 | fCallFailed = true; |
219 | HLTError(gCINTErrorMessage.Data()); | |
faf00b0d | 220 | HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), LAST_ERR_LINENO); |
81d62bb4 | 221 | } |
222 | } | |
223 | ||
224 | ||
f925a066 | 225 | bool AliHLTGlobalTriggerWrapper::CalculateTriggerDecision(bool& triggerResult, AliHLTTriggerDomain& domain, TString& description) |
81d62bb4 | 226 | { |
227 | // Calculates the global trigger decision. | |
228 | ||
325e5e42 | 229 | fCallFailed = false; |
81d62bb4 | 230 | struct Params |
231 | { | |
f925a066 | 232 | const void* fResult; |
81d62bb4 | 233 | const void* fDomain; |
234 | const void* fDesc; | |
235 | } params; | |
f925a066 | 236 | params.fResult = &triggerResult; |
81d62bb4 | 237 | params.fDomain = &domain; |
238 | params.fDesc = &description; | |
f925a066 | 239 | fCalculateTriggerDecisionCall.SetParamPtrs(¶ms, 3); |
81d62bb4 | 240 | Long_t retval; |
325e5e42 | 241 | gCINTErrorMessage = ""; |
81d62bb4 | 242 | fCalculateTriggerDecisionCall.Execute(fObject, retval); |
325e5e42 | 243 | if (gCINTErrorMessage != "") |
81d62bb4 | 244 | { |
325e5e42 | 245 | fCallFailed = true; |
246 | HLTError(gCINTErrorMessage.Data()); | |
faf00b0d | 247 | HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), LAST_ERR_LINENO); |
325e5e42 | 248 | return false; |
81d62bb4 | 249 | } |
250 | return bool(retval); | |
251 | } | |
252 | ||
253 | ||
254 | const TArrayL64& AliHLTGlobalTriggerWrapper::GetCounters() const | |
255 | { | |
256 | // Returns the internal counter array. | |
257 | ||
258 | Long_t retval = 0x0; | |
325e5e42 | 259 | gCINTErrorMessage = ""; |
81d62bb4 | 260 | fGetCountersCall.Execute(fObject, retval); |
325e5e42 | 261 | if (gCINTErrorMessage != "") |
81d62bb4 | 262 | { |
325e5e42 | 263 | fCallFailed = true; |
264 | HLTError(gCINTErrorMessage.Data()); | |
faf00b0d | 265 | HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), LAST_ERR_LINENO); |
81d62bb4 | 266 | } |
267 | static const TArrayL64 emptyArray; | |
268 | const TArrayL64* ptr = &emptyArray; // Make sure we do not return a NULL pointer. | |
269 | if (retval != 0x0) ptr = reinterpret_cast<const TArrayL64*>(retval); | |
270 | return *ptr; | |
271 | } | |
272 | ||
273 | ||
274 | void AliHLTGlobalTriggerWrapper::SetCounters(const TArrayL64& counters) | |
275 | { | |
276 | // Fills the internal counter array with new values. | |
277 | ||
325e5e42 | 278 | fCallFailed = false; |
81d62bb4 | 279 | struct Params |
280 | { | |
281 | const void* fCounters; | |
282 | } params; | |
283 | params.fCounters = &counters; | |
284 | fSetCountersCall.SetParamPtrs(¶ms, 1); | |
325e5e42 | 285 | gCINTErrorMessage = ""; |
81d62bb4 | 286 | fSetCountersCall.Execute(fObject); |
325e5e42 | 287 | if (gCINTErrorMessage != "") |
81d62bb4 | 288 | { |
325e5e42 | 289 | fCallFailed = true; |
290 | HLTError(gCINTErrorMessage.Data()); | |
faf00b0d | 291 | HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), LAST_ERR_LINENO); |
81d62bb4 | 292 | } |
293 | } | |
294 | ||
295 | ||
296 | bool AliHLTGlobalTriggerWrapper::IsValid() const | |
297 | { | |
298 | // Checks if the wrapper class was initialised correctly. | |
299 | ||
300 | return fClass != NULL and fObject != NULL and fFillFromMenuCall.IsValid() | |
301 | and fNewEventCall.IsValid() and fAddCall.IsValid() | |
302 | and fCalculateTriggerDecisionCall.IsValid(); | |
303 | } | |
304 |