bugfix #83123: registration of configurations in multiple handlers. The bug caused...
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTConfigurationHandler.cxx
1 // $Id$
2 // splitted from AliHLTConfiguration.cxx,v 1.25 2007/10/12 13:24:47
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  *                  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   AliHLTConfigurationHandler.cxx
20     @author Matthias Richter
21     @date   
22     @brief  Implementation of HLT tasks.
23 */
24
25 // see header file for class documentation
26 // or
27 // refer to README to build package
28 // or
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31 #if __GNUC__>= 3
32 using namespace std;
33 #endif
34
35 #include <cerrno>
36 #include <iostream>
37 #include <string>
38 #include "AliHLTConfigurationHandler.h"
39 #include "AliHLTConfiguration.h"
40 #include "AliHLTErrorGuard.h"
41 #include "TMap.h"
42 #include "TObjString.h"
43
44 /** ROOT macro for the implementation of ROOT specific class methods */
45 ClassImp(AliHLTConfigurationHandler)
46
47 AliHLTConfigurationHandler::AliHLTConfigurationHandler()
48   : AliHLTLogging()
49   , fgListConfigurations()
50   , fgListScheduledRegistrations()
51   , fFlags(0)
52 {
53   // see header file for class documentation
54   // or
55   // refer to README to build package
56   // or
57   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
58   SetLocalLoggingLevel(kHLTLogInfo);
59 }
60
61 AliHLTConfigurationHandler::~AliHLTConfigurationHandler()
62 {
63   // see header file for function documentation
64   TObjLink* lnk=NULL;
65   while ((lnk=fgListConfigurations.FirstLink())!=NULL) {
66     AliHLTConfiguration* pConf=(AliHLTConfiguration*)lnk->GetObject();
67     HLTDebug("delete configuration \"%s\"", pConf->GetName());
68     fgListConfigurations.Remove(lnk);
69     delete pConf;
70   }
71   fgListScheduledRegistrations.Delete();
72 }
73
74 AliHLTConfigurationHandler* AliHLTConfigurationHandler::fgpInstance=NULL;
75 int AliHLTConfigurationHandler::fgNofInstances=0;
76 TMap* AliHLTConfigurationHandler::fgpSubstitutions=NULL;
77
78 AliHLTConfigurationHandler* AliHLTConfigurationHandler::CreateHandler()
79 {
80   // see header file for class documentation
81   if (!fgpInstance) fgpInstance=new AliHLTConfigurationHandler;
82   fgNofInstances++;
83   return fgpInstance;
84 }
85
86 int AliHLTConfigurationHandler::Destroy()
87 {
88   // see header file for class documentation
89   int nofInstances=0;
90   if (fgpInstance==this) {
91     nofInstances=--fgNofInstances;
92   }
93   if (fgNofInstances==0) {
94     fgpInstance = NULL;
95     if (fgpSubstitutions) delete fgpSubstitutions;
96     fgpSubstitutions=NULL;
97   }
98   if (nofInstances==0) delete this;
99   return nofInstances;
100 }
101
102
103 int AliHLTConfigurationHandler::RegisterConfiguration(AliHLTConfiguration* pConf)
104 {
105   // see header file for function documentation
106   int iResult=0;
107   if (pConf) {
108     AliHLTConfiguration* pClone=new AliHLTConfiguration(*pConf);
109     if (IsActive()) {      
110       AliHLTConfiguration* pExisting=NULL;
111       if ((pExisting=FindConfiguration(pConf->GetName())) == NULL) {
112         fgListConfigurations.Add(pClone);
113         HLTDebug("configuration \"%s\" (%p) registered from %p", pClone->GetName(), pClone, pConf);
114
115         // mark all configurations with unresolved dependencies for re-evaluation
116         TObjLink* lnk=fgListConfigurations.FirstLink();
117         while (lnk) {
118           AliHLTConfiguration* pSrc=(AliHLTConfiguration*)lnk->GetObject();
119           if (pSrc && pSrc!=pClone && pSrc->SourcesResolved()!=1) {
120             pSrc->InvalidateSources();
121           }
122           lnk=lnk->Next();
123         }
124       } else {
125         if ((*pExisting)!=(*pConf)) {
126           iResult=-EEXIST;
127           HLTWarning("configuration \"%s\" already registered with different properties", pConf->GetName());
128         }
129       }
130     } else if (IsScheduling()) {
131       fgListScheduledRegistrations.Add(pClone);
132     }
133   } else {
134     iResult=-EINVAL;
135   }
136   return iResult;
137 }
138
139 int AliHLTConfigurationHandler::CreateConfiguration(const char* id, const char* component, const char* sources, const char* arguments)
140 {
141   // see header file for function documentation
142   int iResult=0;
143   // if this handler is the global instance the configuration is added
144   // automatically in the creation of the AliHLTConfiguration object
145   // the global instance must be deactivated otherwise in order to just create
146   // the object and then add it to THIS handler
147   bool bIamGlobal=fgpInstance==this;
148   if (!bIamGlobal && fgpInstance) {
149     // deactivate the automatic registration in the global handler
150     fgpInstance->Deactivate(false);
151   }
152   AliHLTConfiguration* pConf= new AliHLTConfiguration(id, component, sources, arguments);
153   if (pConf) {
154     if (bIamGlobal) {
155     // the configuration will be registered automatically, if this failes the configuration
156     // is missing -> delete it
157     if (FindConfiguration(id)==NULL) {
158       delete pConf;
159       pConf=NULL;
160       iResult=-EEXIST;
161     }
162     } else {
163       RegisterConfiguration(pConf);
164     }
165   } else {
166     HLTError("system error: object allocation failed");
167     iResult=-ENOMEM;
168   }
169   if (!bIamGlobal && fgpInstance) {
170     // deactivate the automatic registration in the global handler
171     fgpInstance->Activate();
172   }
173   return iResult;
174 }
175
176 void AliHLTConfigurationHandler::PrintConfigurations()
177 {
178   // see header file for function documentation
179   HLTLogKeyword("configuration listing");
180   HLTMessage("registered configurations:");
181   TObjLink *lnk = fgListConfigurations.FirstLink();
182   while (lnk) {
183     TObject *obj = lnk->GetObject();
184     HLTMessage("  %s", obj->GetName());
185     lnk = lnk->Next();
186   }
187 }
188
189 void AliHLTConfigurationHandler::Print(const char* option)
190 {
191   // print info
192   TString argument(option);
193   if (argument.BeginsWith("treeroot=")) {
194     argument.ReplaceAll("treeroot=", "");
195     if (argument.IsNull()) {
196       cout << "invalid argument to option 'treeroot=', please specify configuration" << endl;
197       return;
198     }
199     // TODO: add functionality to print a dependency tree beginning from a root configuration
200     // add also option to limit the depth
201     cout << "need to implement option 'treeview', argument " << argument << endl;
202     return;
203   }
204
205   // default: print all
206   PrintConfigurations();
207 }
208
209 int AliHLTConfigurationHandler::RemoveConfiguration(const char* id)
210 {
211   // see header file for function documentation
212   int iResult=0;
213   if (id) {
214     AliHLTConfiguration* pConf=NULL;
215     if ((pConf=FindConfiguration(id))!=NULL) {
216       iResult=RemoveConfiguration(pConf);
217       delete pConf;
218       pConf=NULL;
219     } else {
220       HLTWarning("can not find configuration \"%s\"", id);
221       iResult=-ENOENT;
222     }
223   } else {
224     iResult=-EINVAL;
225   }
226   return iResult;
227 }
228
229 int AliHLTConfigurationHandler::RemoveConfiguration(AliHLTConfiguration* pConf)
230 {
231   // see header file for function documentation
232   int iResult=0;
233   if (pConf) {
234     // remove the configuration from the list
235     HLTDebug("remove configuration \"%s\"", pConf->GetName());
236     fgListConfigurations.Remove(pConf);
237     // remove cross links in the remaining configurations
238     TObjLink* lnk=fgListConfigurations.FirstLink();
239     while (lnk && iResult>=0) {
240       AliHLTConfiguration* pRem=(AliHLTConfiguration*)lnk->GetObject();
241       if (pRem) {
242         pRem->InvalidateSource(pConf);
243       } else {
244         iResult=-EFAULT;
245       }
246       lnk=lnk->Next();
247     }
248   }
249   return iResult;
250 }
251
252 AliHLTConfiguration* AliHLTConfigurationHandler::FindConfiguration(const char* id)
253 {
254   // see header file for function documentation
255   AliHLTConfiguration* pConf=NULL;
256   if (id) {
257     pConf=(AliHLTConfiguration*)fgListConfigurations.FindObject(id); 
258   }
259   return pConf;
260 }
261
262 int AliHLTConfigurationHandler::Deactivate(bool schedule) {
263   // see header file for function documentation
264   fFlags|=kInactive;
265   if (schedule)
266     fFlags|=kScheduling;
267   return 0;
268 }
269
270 int AliHLTConfigurationHandler::Activate() {
271   // see header file for function documentation
272   fFlags&=~kInactive;
273   if (IsScheduling()) {
274     fFlags&=~kScheduling;
275     TObjLink *lnk = fgListScheduledRegistrations.FirstLink();
276     while (lnk) {
277       RegisterConfiguration((AliHLTConfiguration*)lnk->GetObject());
278       lnk = lnk->Next();
279     }
280     ClearScheduledRegistrations();
281   }
282   return 0;
283 }
284
285 int AliHLTConfigurationHandler::MissedRegistration(const char* name)
286 {
287   /// indicate a failed attempt to register because of unavailable global instance
288
289   /// everything fine if global instance is inactive
290   if (fgpInstance) {
291     if (fgpInstance->IsActive()) {
292       static AliHLTErrorGuard g("AliHLTConfigurationHandler", "MissedRegistration",
293                                 "internal error, global instance available but registration of configuration failed");
294       (++g).Throw(1);
295     }
296     return 0;
297   }
298   TString message("Missing configuration handler, failed to register configuration");
299   if (name) {message+=" '"; message+=name;}
300   message+="'\n AliHLTSystem and configuration handler can be initialized by adding the line";
301   message+="\n    AliHLTSystem* pHLT=AliHLTPluginBase::GetInstance();";
302   message+="\n to the macro before the first AliHLTConfiguration definition. Suppressing further messages.\n";
303   static AliHLTErrorGuard g("AliHLTConfigurationHandler", "MissedRegistration", message.Data());
304   (++g).Throw(1);
305   return 1;
306 }
307
308 int AliHLTConfigurationHandler::AddSubstitution(const char* componentId, const AliHLTConfiguration& subst)
309 {
310   /// add component substitution for components of specified id
311   if (!componentId) return -EINVAL;
312   if (!fgpSubstitutions) fgpSubstitutions=new TMap;
313   if (!fgpSubstitutions) return -ENOMEM;
314   fgpSubstitutions->SetOwnerKeyValue(kTRUE);
315
316   fgpSubstitutions->Add(new TObjString(componentId), new AliHLTConfiguration(subst));
317
318   return 0;  
319 }
320
321 int AliHLTConfigurationHandler::AddSubstitution(const AliHLTConfiguration& conf , const AliHLTConfiguration& subst)
322 {
323   /// add component substitution for components of specified id
324   if (!fgpSubstitutions) fgpSubstitutions=new TMap;
325   if (!fgpSubstitutions) return -ENOMEM;
326   fgpSubstitutions->SetOwnerKeyValue(kTRUE);
327
328   fgpSubstitutions->Add(new AliHLTConfiguration(conf), new AliHLTConfiguration(subst));
329
330   return 0;  
331 }
332
333 const AliHLTConfiguration* AliHLTConfigurationHandler::FindSubstitution(const AliHLTConfiguration& conf)
334 {
335   /// find component substitution for a configuration
336   if (!fgpSubstitutions) return NULL;
337   TObject* value=NULL;
338
339   // check for specific configuration
340   value=fgpSubstitutions->GetValue(conf.GetName());
341   if (value) return dynamic_cast<AliHLTConfiguration*>(value);
342
343   // check for component Id
344   value=fgpSubstitutions->GetValue(conf.GetComponentID());
345   if (value) return dynamic_cast<AliHLTConfiguration*>(value);
346
347   return NULL;
348 }