ALIROOT-5600 - skip non-participating detector modules
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTConfiguration.cxx
1 // $Id$
2
3 ///**************************************************************************
4 ///* This file is property of and copyright by the                          * 
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   AliHLTConfiguration.cxx
20 /// @author Matthias Richter
21 /// @date   2007
22 /// @brief  HLT configuration description for a single component.
23 /// @note   The class is used in Offline (AliRoot) context
24
25 #include <cerrno>
26 #include "AliHLTConfiguration.h"
27 #include "AliHLTConfigurationHandler.h"
28 #include "AliHLTTask.h"
29 #include "AliHLTComponent.h"
30 #include "AliHLTComponentHandler.h"
31 #include <iostream>
32 #include <string>
33 #include "TList.h"
34
35 using std::vector;
36
37 /** ROOT macro for the implementation of ROOT specific class methods */
38 ClassImp(AliHLTConfiguration)
39
40 AliHLTConfiguration::AliHLTConfiguration()
41   :
42   fID(""),
43   fComponent(""),
44   fStringSources(""),
45   fNofSources(-1),
46   fListSources(),
47   fListSrcElementIdx(-1),
48   fArguments(""),
49   fArgc(-1),
50   fArgv(NULL),
51   fBufferSize(-1)
52
53   // This class describes a configuration for an HLT component by means of
54   // the following parameters:
55   // - configuration id:      a unique id string/name
56   // - component id:          id returned by AliHLTComponent::GetComponentID()
57   // - parent configuartions: ids of configurations it requires input from
58   // - component arguments:   passed to the component when it is initialized
59 }
60
61 AliHLTConfiguration::AliHLTConfiguration(const char* id, const char* component, const char* sources,
62                                          const char* arguments, const char* bufsize)
63   :
64   fID(id),
65   fComponent(component),
66   fStringSources(sources),
67   fNofSources(-1),
68   fListSources(),
69   fListSrcElementIdx(-1),
70   fArguments(arguments),
71   fArgc(-1),
72   fArgv(NULL),
73   fBufferSize(-1)
74 {
75   // constructor
76   if (bufsize) fBufferSize=ConvertSizeString(bufsize);
77   if (id && component) {
78     if (AliHLTConfigurationHandler::Instance()) {
79       AliHLTConfigurationHandler::Instance()->RegisterConfiguration(this);
80     } else {
81       AliHLTConfigurationHandler::MissedRegistration(id);
82     }
83   }
84 }
85
86 AliHLTConfiguration::AliHLTConfiguration(const AliHLTConfiguration& src)
87   :
88   TObject(),
89   AliHLTLogging(),
90   fID(src.fID),
91   fComponent(src.fComponent),
92   fStringSources(src.fStringSources),
93   fNofSources(-1),
94   fListSources(),
95   fListSrcElementIdx(-1),
96   fArguments(src.fArguments),
97   fArgc(-1),
98   fArgv(NULL),
99   fBufferSize(src.fBufferSize)
100
101   // copy constructor
102 }
103
104 AliHLTConfiguration& AliHLTConfiguration::operator=(const AliHLTConfiguration& src)
105
106   // assignment operator
107   if (this==&src) return *this;
108
109   fID=src.fID;
110   fComponent=src.fComponent;
111   fStringSources=src.fStringSources;
112   fNofSources=-1;
113   fArguments=src.fArguments;
114   fArgc=-1;
115   fArgv=NULL;
116   fBufferSize=src.fBufferSize;
117   return *this;
118 }
119
120 AliHLTConfiguration::~AliHLTConfiguration()
121 {
122   // destructor
123   if (AliHLTConfigurationHandler::Instance()) {
124     if (AliHLTConfigurationHandler::Instance()->FindConfiguration(fID.Data())!=NULL) {
125       // remove the configuration from the handler if it exists
126       // but DO NOT remove the clone configuration
127       AliHLTConfigurationHandler::Instance()->RemoveConfiguration(this);
128     }
129   }
130   if (fArgv != NULL) {
131     if (fArgc>0) {
132       for (int i=0; i<fArgc; i++) {
133         delete[] fArgv[i];
134       }
135     }
136     delete[] fArgv;
137     fArgv=NULL;
138   }
139
140   vector<AliHLTConfiguration*>::iterator element=fListSources.begin();
141   while (element!=fListSources.end()) {
142     fListSources.erase(element);
143     element=fListSources.begin();
144   }
145 }
146
147 const char* AliHLTConfiguration::GetName() const 
148 {
149   // get name
150   if (!fID.IsNull())
151     return fID.Data();
152   return TObject::GetName();
153 }
154
155 AliHLTConfiguration* AliHLTConfiguration::GetSource(const char* id)
156 {
157   // get source by id
158   AliHLTConfiguration* pSrc=NULL;
159   if (id) {
160     // first check the current element
161     if (fListSrcElementIdx>=0 && fListSrcElementIdx<(int)fListSources.size() &&
162         strcmp(id, (fListSources[fListSrcElementIdx])->GetName())==0) {
163       pSrc=fListSources[fListSrcElementIdx];
164       } else {
165       // check the list
166
167       pSrc=GetFirstSource();
168       while (pSrc) {
169         if (strcmp(id, pSrc->GetName())==0)
170           break;
171         pSrc=GetNextSource();
172       }
173     }
174   }
175   return pSrc;
176 }
177
178 AliHLTConfiguration* AliHLTConfiguration::GetFirstSource() const
179 {
180   // get first source in the list
181   // TODO: iterator class
182   AliHLTConfiguration* pSrc=NULL;
183   if (fNofSources>0) {
184     const_cast<AliHLTConfiguration*>(this)->fListSrcElementIdx=-1;
185     pSrc=GetNextSource();
186   } 
187   return pSrc;
188 }
189
190 AliHLTConfiguration* AliHLTConfiguration::GetNextSource() const
191 {
192   // get next source
193   AliHLTConfiguration* pSrc=NULL;
194   if (fNofSources>0) {
195     if (fListSrcElementIdx+1<(int)fListSources.size()) {
196       const_cast<AliHLTConfiguration*>(this)->fListSrcElementIdx++;
197       pSrc=fListSources[fListSrcElementIdx];
198     }
199   } 
200   return pSrc;
201 }
202
203 int AliHLTConfiguration::SourcesResolved() const
204 {
205   // check if all sources are resolved
206   int iResult=0;
207   if (fNofSources>=0) {
208     iResult=fNofSources==(int)fListSources.size();
209   }
210   return iResult;
211 }
212
213 int AliHLTConfiguration::InvalidateSource(AliHLTConfiguration* pConf)
214 {
215   // invalidate state of all sources
216   int iResult=0;
217   if (pConf) {
218     vector<AliHLTConfiguration*>::iterator element=fListSources.begin();
219     while (element!=fListSources.end()) {
220       if (*element==pConf) {
221         fListSources.erase(element);
222         fListSrcElementIdx=fListSources.size();
223         // there is no need to re-evaluate until there was a new configuration registered
224         // -> postpone the invalidation, its done in AliHLTConfigurationHandler::RegisterConfiguration
225         //InvalidateSources();
226         break;
227       }
228       element++;
229     }
230   } else {
231     iResult=-EINVAL;
232   }
233   return iResult;
234 }
235
236 void AliHLTConfiguration::PrintStatus() const
237 {
238   // print info
239   HLTLogKeyword("configuration status");
240   HLTMessage("status of configuration \"%s\" (%p)", GetName(), this);
241   if (!fComponent.IsNull()) HLTMessage("  - component: \"%s\"", fComponent.Data());
242   else HLTMessage("  - component string invalid");
243   if (!fStringSources.IsNull()) HLTMessage("  - sources: \"%s\"", fStringSources.Data());
244   else HLTMessage("  - no sources");
245   if (SourcesResolved()!=1)
246     HLTMessage("    there are unresolved sources");
247   AliHLTConfiguration* pSrc=GetFirstSource();
248   while (pSrc) {
249     HLTMessage("    source \"%s\" (%p) resolved", pSrc->GetName(), pSrc);
250     pSrc=GetNextSource();
251   }
252 }
253
254 void AliHLTConfiguration::Print(const char* option) const
255 {
256   // print information
257   if (option && strcmp(option, "status")==0) {
258     PrintStatus();
259     return;
260   }
261   HLTLogKeyword("configuration");
262   HLTMessage("configuration %s: component %s, sources %s, arguments %s",
263              GetName(),
264              GetComponentID(),
265              GetSourceSettings(),
266              GetArgumentSettings()
267              );
268 }
269
270 int AliHLTConfiguration::GetArguments(const char*** pArgv) const
271 {
272   // get argument array
273   int iResult=0;
274   if (pArgv) {
275     if (fArgc==-1) {
276       if ((iResult=const_cast<AliHLTConfiguration*>(this)->ExtractArguments())<0) {
277         HLTError("error extracting arguments for configuration %s", GetName());
278       }
279     } else if (fArgc<0) {
280       HLTError("previous argument extraction failed");
281     }
282     //HLTDebug("%s fArgc %d", GetName(), fArgc);
283     iResult=fArgc;
284     *pArgv=(const char**)fArgv;
285   } else {
286     HLTError("invalid parameter");
287     iResult=-EINVAL;
288   }
289   return iResult;
290 }
291
292
293 int AliHLTConfiguration::ExtractSources(AliHLTConfigurationHandler* pHandler)
294 {
295   // extract source configurations from the handler
296   // TODO: would be less confusing to use 'parent' instead of 'source'
297   // but this needs to be changed consistently throughout the class
298   int iResult=0;
299   fNofSources=0; // indicates that the function was called, there are either n or 0 sources
300   fListSources.clear();
301   if (!pHandler) {
302     HLTError("configuration handler missing, can not resolve sources");
303     return -EFAULT;
304   }
305   if (!fStringSources.IsNull()) {
306     vector<char*> tgtList;
307     if ((iResult=InterpreteString(fStringSources.Data(), tgtList))>=0) {
308       fNofSources=tgtList.size();
309       vector<char*>::iterator element=tgtList.begin();
310       while ((element=tgtList.begin())!=tgtList.end()) {
311           AliHLTConfiguration* pConf=pHandler->FindConfiguration(*element);
312           if (pConf) {
313             //HLTDebug("configuration %s (%p): source \"%s\" (%p) inserted", GetName(), this, pConf->GetName(), pConf);
314             fListSources.push_back(pConf);
315           } else {
316             HLTError("can not find source \"%s\"", (*element));
317             iResult=-ENOENT;
318           }
319         delete[] (*element);
320         tgtList.erase(element);
321       }
322     }
323   }
324   fListSrcElementIdx=-1;
325   return iResult<0?iResult:SourcesResolved();
326 }
327
328 int AliHLTConfiguration::ExtractArguments()
329 {
330   // extract argument list from string
331   int iResult=0;
332   if (!fArguments.IsNull()) {
333     vector<char*> tgtList;
334     if ((iResult=InterpreteString(fArguments, tgtList))>=0) {
335       fArgc=tgtList.size();
336       //HLTDebug("configuration %s: extracted %d arguments from \"%s\"", GetName(), fArgc, fArguments);
337       if (fArgc>0) {
338         fArgv = new char*[fArgc];
339         if (fArgv) {
340           vector<char*>::iterator element=tgtList.begin();
341           int i=0;
342           while (element!=tgtList.end()) {
343             //HLTDebug("assign arguments %d (%s)", i, *element);
344             fArgv[i++]=(*element);
345             element++;
346           }
347         } else {
348           iResult=-ENOMEM;
349         }
350       }
351     }
352   } else {
353     // there are zero arguments
354     fArgc=0;
355   }
356   if (iResult<0) fArgc=iResult;
357   return iResult;
358 }
359
360 int AliHLTConfiguration::InterpreteString(const char* arg, vector<char*>& argList)
361 {
362   // interprete a string
363   int iResult=0;
364   if (arg) {
365     //HLTDebug("interprete \"%s\"", arg);
366     int i=0;
367     int prec=-1;
368     int bQuote=0;
369     do {
370       //HLTDebug("%d %x", i, arg[i]);
371       if (arg[i]=='\'' && bQuote==0) {
372         bQuote=1;
373       } else if (arg[i]==0 || 
374                  (arg[i]==' ' && bQuote==0) ||
375                  (arg[i]=='\'' && bQuote==1)) {
376         bQuote=0;
377         if (prec>=0) {
378           char* pEntry= new char[i-prec+1];
379           if (pEntry) {
380             strncpy(pEntry, &arg[prec], i-prec);
381             pEntry[i-prec]=0; // terminate string
382             //HLTDebug("create string \"%s\", insert at %d", pEntry, argList.size());
383             argList.push_back(pEntry);
384           } else 
385             iResult=-ENOMEM;
386           prec=-1;
387         }
388       } else if (prec==-1) prec=i;
389     } while (arg[i++]!=0 && iResult>=0); 
390   } else {
391     iResult=-EINVAL;
392   }
393   return iResult;
394 }
395
396 int AliHLTConfiguration::ConvertSizeString(const char* strSize) const
397 {
398   // convert a size argument
399   int size=0;
400   if (!strSize) return -1;
401
402   char* endptr=NULL;
403   size=strtol(strSize, &endptr, 10);
404   if (size>=0) {
405     if (endptr) {
406       if (endptr==strSize) {
407         HLTWarning("ignoring unrecognized buffer size '%s'", strSize);
408         size=-1;
409       } else if (*endptr==0) {
410         // no unit specifier
411       } else if (*endptr=='k') {
412         size*=1014;
413       } else if (*endptr=='M') {
414         size*=1024*1024;
415       } else {
416         HLTWarning("ignoring buffer size of unknown unit '%c'", endptr[0]);
417       }
418     } else {
419       HLTWarning("ignoring negative buffer size specifier '%s'", strSize);
420       size=-1;
421     }
422   }
423   return size;
424 }
425
426 int AliHLTConfiguration::FollowDependency(const char* id, TList* pTgtList)
427 {
428   // follow dependencies
429   int iResult=0;
430   if (id) {
431     AliHLTConfiguration* pDep=NULL;
432     if ((pDep=GetSource(id))!=NULL) {
433       if (pTgtList) pTgtList->Add(pDep);
434       iResult++;
435     } else {
436       pDep=GetFirstSource();
437       while (pDep && iResult==0) {
438         if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
439           if (pTgtList) pTgtList->AddFirst(pDep);
440           iResult++;
441         }
442         pDep=GetNextSource();
443       }
444     }
445   } else {
446     iResult=-EINVAL;
447   }
448   return iResult;
449 }
450
451