]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/trigger/AliHLTGlobalTriggerWrapper.cxx
- fixes for bug 63765 - see for details the post
[u/mrichter/AliRoot.git] / HLT / trigger / AliHLTGlobalTriggerWrapper.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   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"
32 #include "TCint.h"
33
34 ClassImp(AliHLTGlobalTriggerWrapper)
35
36
37 namespace
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
54 AliHLTGlobalTriggerWrapper::AliHLTGlobalTriggerWrapper(const char* classname) :
55   AliHLTGlobalTrigger(),
56   AliHLTLogging(),
57   fClass(NULL),
58   fObject(NULL),
59   fFillFromMenuCall(),
60   fNewEventCall(),
61   fAddCall(),
62   fCalculateTriggerDecisionCall(),
63   fGetCountersCall(),
64   fSetCountersCall(),
65   fCallFailed(false)
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   }
116   
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   {
130     gInterpreter->SetErrmsgcallback(fPtr);
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   }
139 }
140
141
142 AliHLTGlobalTriggerWrapper::~AliHLTGlobalTriggerWrapper()
143 {
144   // Default destructor.
145   
146   fClass->Destructor(fObject);
147   G__set_errmsgcallback(NULL);
148 }
149
150
151 void AliHLTGlobalTriggerWrapper::FillFromMenu(const AliHLTTriggerMenu& menu)
152 {
153   // Fills internal values from the trigger menu.
154   
155   fCallFailed = false;
156   struct Params
157   {
158     const void* fMenu;
159   } params;
160   params.fMenu = &menu;
161   fFillFromMenuCall.SetParamPtrs(&params, 1);
162   gCINTErrorMessage = "";
163   fFillFromMenuCall.Execute(fObject);
164   if (gCINTErrorMessage != "")
165   {
166     fCallFailed = true;
167     HLTError(gCINTErrorMessage.Data());
168     HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
169   }
170 }
171
172
173 void AliHLTGlobalTriggerWrapper::NewEvent()
174 {
175   // Clears the internal buffers for a new event.
176
177   fCallFailed = false;
178   gCINTErrorMessage = "";
179   fNewEventCall.Execute(fObject);
180   if (gCINTErrorMessage != "")
181   {
182     fCallFailed = true;
183     HLTError(gCINTErrorMessage.Data());
184     HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
185   }
186 }
187
188
189 void 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   
196   fCallFailed = false;
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);
207   gCINTErrorMessage = "";
208   fAddCall.Execute(fObject);
209   if (gCINTErrorMessage != "")
210   {
211     fCallFailed = true;
212     HLTError(gCINTErrorMessage.Data());
213     HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
214   }
215 }
216
217
218 bool AliHLTGlobalTriggerWrapper::CalculateTriggerDecision(AliHLTTriggerDomain& domain, TString& description)
219 {
220   // Calculates the global trigger decision.
221
222   fCallFailed = false;
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;
232   gCINTErrorMessage = "";
233   fCalculateTriggerDecisionCall.Execute(fObject, retval);
234   if (gCINTErrorMessage != "")
235   {
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;
240   }
241   return bool(retval);
242 }
243
244
245 const TArrayL64& AliHLTGlobalTriggerWrapper::GetCounters() const
246 {
247   // Returns the internal counter array.
248
249   Long_t retval = 0x0;
250   gCINTErrorMessage = "";
251   fGetCountersCall.Execute(fObject, retval);
252   if (gCINTErrorMessage != "")
253   {
254     fCallFailed = true;
255     HLTError(gCINTErrorMessage.Data());
256     HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
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
265 void AliHLTGlobalTriggerWrapper::SetCounters(const TArrayL64& counters)
266 {
267   // Fills the internal counter array with new values.
268   
269   fCallFailed = false;
270   struct Params
271   {
272     const void* fCounters;
273   } params;
274   params.fCounters = &counters;
275   fSetCountersCall.SetParamPtrs(&params, 1);
276   gCINTErrorMessage = "";
277   fSetCountersCall.Execute(fObject);
278   if (gCINTErrorMessage != "")
279   {
280     fCallFailed = true;
281     HLTError(gCINTErrorMessage.Data());
282     HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
283   }
284 }
285
286
287 bool 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