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