- adapted to AliRoot logging system, messages printed out via AliRoot
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTConfiguration.cxx
1 // $Id$
2
3 /**************************************************************************
4  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5  *                                                                        *
6  * Authors: Matthias Richter <Matthias.Richter@ift.uib.no>                *
7  *          for The ALICE Off-line 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   AliHLTConfiguration.cxx
19     @author Matthias Richter
20     @date   
21     @brief  Implementation of HLT configuration handler.
22 */
23
24 #if __GNUC__>= 3
25 using namespace std;
26 #endif
27
28 #include <cerrno>
29 #include "AliHLTConfiguration.h"
30 #include "AliHLTConfigurationHandler.h"
31 #include "AliHLTTask.h"
32 #include "AliHLTComponent.h"
33 #include "AliHLTComponentHandler.h"
34 #include <iostream>
35 #include <string>
36 #include "TList.h"
37
38 /** ROOT macro for the implementation of ROOT specific class methods */
39 ClassImp(AliHLTConfiguration)
40
41 AliHLTConfiguration::AliHLTConfiguration()
42   :
43   fID(NULL),
44   fComponent(NULL),
45   fStringSources(NULL),
46   fNofSources(-1),
47   fListSources(),
48   fListSrcElement(),
49   fArguments(NULL),
50   fArgc(-1),
51   fArgv(NULL)
52
53   // see header file for function documentation
54   fListSrcElement=fListSources.begin();
55 }
56
57 AliHLTConfiguration::AliHLTConfiguration(const char* id, const char* component, const char* sources, const char* arguments)
58   :
59   fID(id),
60   fComponent(component),
61   fStringSources(sources),
62   fNofSources(-1),
63   fListSources(),
64   fListSrcElement(),
65   fArguments(arguments),
66   fArgc(-1),
67   fArgv(NULL)
68 {
69   // see header file for function documentation
70   fListSrcElement=fListSources.begin();
71   if (id && component) {
72     if (fgConfigurationHandler) {
73       fgConfigurationHandler->RegisterConfiguration(this);
74     } else {
75       HLTError("no configuration handler set, abort registration");
76     }
77   }
78 }
79
80 AliHLTConfiguration::AliHLTConfiguration(const AliHLTConfiguration& src)
81   :
82   TObject(),
83   AliHLTLogging(),
84   fID(src.fID),
85   fComponent(src.fComponent),
86   fStringSources(src.fStringSources),
87   fNofSources(-1),
88   fListSources(),
89   fListSrcElement(),
90   fArguments(src.fArguments),
91   fArgc(-1),
92   fArgv(NULL)
93
94   // see header file for function documentation
95   fListSrcElement=fListSources.begin();
96 }
97
98 AliHLTConfiguration& AliHLTConfiguration::operator=(const AliHLTConfiguration& src)
99
100   // see header file for function documentation
101   fID=src.fID;
102   fComponent=src.fComponent;
103   fStringSources=src.fStringSources;
104   fNofSources=-1;
105   fArguments=src.fArguments;
106   fArgc=-1;
107   fArgv=NULL;
108   return *this;
109 }
110
111 AliHLTConfiguration::~AliHLTConfiguration()
112 {
113   // see header file for function documentation
114   if (fgConfigurationHandler) {
115     if (fgConfigurationHandler->FindConfiguration(fID)!=NULL) {
116       fgConfigurationHandler->RemoveConfiguration(this);
117     }
118   }
119   if (fArgv != NULL) {
120     if (fArgc>0) {
121       for (int i=0; i<fArgc; i++) {
122         delete[] fArgv[i];
123       }
124     }
125     delete[] fArgv;
126     fArgv=NULL;
127   }
128 }
129
130 /* the global configuration handler which is used to automatically register the configuration
131  */
132 AliHLTConfigurationHandler* AliHLTConfiguration::fgConfigurationHandler=NULL;
133
134 int AliHLTConfiguration::GlobalInit(AliHLTConfigurationHandler* pHandler)
135 {
136   // see header file for function documentation
137   int iResult=0;
138   if (fgConfigurationHandler!=NULL) {
139     fgConfigurationHandler->Logging(kHLTLogWarning, "AliHLTConfiguration::GlobalInit", HLT_DEFAULT_LOG_KEYWORD, "configuration handler already initialized, overriding object %p with %p", fgConfigurationHandler, pHandler);
140   }
141   fgConfigurationHandler=pHandler;
142   return iResult;
143 }
144
145 int AliHLTConfiguration::GlobalDeinit(AliHLTConfigurationHandler* pHandler)
146 {
147   // see header file for function documentation
148   int iResult=0;
149   if (pHandler!=NULL && fgConfigurationHandler!=pHandler) {
150     fgConfigurationHandler->Logging(kHLTLogWarning, "AliHLTConfiguration::GlobalDeinit", HLT_DEFAULT_LOG_KEYWORD, "handler %p is not set, skip ...", pHandler);
151     return -EBADF;
152   }
153   fgConfigurationHandler=NULL;
154   return iResult;
155 }
156
157 const char* AliHLTConfiguration::GetName() const 
158 {
159   // see header file for function documentation
160   if (fID)
161     return fID;
162   return TObject::GetName();
163 }
164
165 AliHLTConfiguration* AliHLTConfiguration::GetSource(const char* id)
166 {
167   // see header file for function documentation
168   AliHLTConfiguration* pSrc=NULL;
169   if (id) {
170     // first check the current element
171     if (fListSrcElement!=fListSources.end() && strcmp(id, (*fListSrcElement)->GetName())==0) {
172       pSrc=*fListSrcElement;
173       } else {
174       // check the list
175
176       pSrc=GetFirstSource();
177       while (pSrc) {
178         if (strcmp(id, pSrc->GetName())==0)
179           break;
180         pSrc=GetNextSource();
181       }
182     }
183   }
184   return pSrc;
185 }
186
187 AliHLTConfiguration* AliHLTConfiguration::GetFirstSource()
188 {
189   // see header file for function documentation
190   AliHLTConfiguration* pSrc=NULL;
191   if (fNofSources>=0 || ExtractSources()) {
192     fListSrcElement=fListSources.begin();
193     if (fListSrcElement!=fListSources.end()) pSrc=*fListSrcElement;
194   } 
195   return pSrc;
196 }
197
198 AliHLTConfiguration* AliHLTConfiguration::GetNextSource()
199 {
200   // see header file for function documentation
201   AliHLTConfiguration* pSrc=NULL;
202   if (fNofSources>0) {
203     if (fListSrcElement!=fListSources.end() && (++fListSrcElement)!=fListSources.end()) 
204       pSrc=*fListSrcElement;
205   } 
206   return pSrc;
207 }
208
209 int AliHLTConfiguration::SourcesResolved(int bAuto) 
210 {
211   // see header file for function documentation
212   int iResult=0;
213   if (fNofSources>=0 || bAuto && (iResult=ExtractSources())>=0) {
214     //HLTDebug("fNofSources=%d", fNofSources);
215     //HLTDebug("list size = %d", fListSources.size());
216     iResult=fNofSources==(int)fListSources.size();
217   }
218   return iResult;
219 }
220
221 int AliHLTConfiguration::InvalidateSource(AliHLTConfiguration* pConf)
222 {
223   // see header file for function documentation
224   int iResult=0;
225   if (pConf) {
226     vector<AliHLTConfiguration*>::iterator element=fListSources.begin();
227     while (element!=fListSources.end()) {
228       if (*element==pConf) {
229         fListSources.erase(element);
230         fListSrcElement=fListSources.end();
231         // there is no need to re-evaluate until there was a new configuration registered
232         // -> postpone the invalidation, its done in AliHLTConfigurationHandler::RegisterConfiguration
233         //InvalidateSources();
234         break;
235       }
236       element++;
237     }
238   } else {
239     iResult=-EINVAL;
240   }
241   return iResult;
242 }
243
244 void AliHLTConfiguration::PrintStatus()
245 {
246   // see header file for function documentation
247   HLTLogKeyword("configuration status");
248   HLTMessage("status of configuration \"%s\" (%p)", GetName(), this);
249   if (fComponent) HLTMessage("  - component: \"%s\"", fComponent);
250   else HLTMessage("  - component string invalid");
251   if (fStringSources) HLTMessage("  - sources: \"%s\"", fStringSources);
252   else HLTMessage("  - no sources");
253   if (SourcesResolved(1)<=0)
254     HLTMessage("    there are unresolved sources");
255   AliHLTConfiguration* pSrc=GetFirstSource();
256   while (pSrc) {
257     HLTMessage("    source \"%s\" (%p) resolved", pSrc->GetName(), pSrc);
258     pSrc=GetNextSource();
259   }
260 }
261
262 int AliHLTConfiguration::GetArguments(const char*** pArgv)
263 {
264   // see header file for function documentation
265   int iResult=0;
266   if (pArgv) {
267     if (fArgc==-1) {
268       if ((iResult=ExtractArguments())<0) {
269         HLTError("error extracting arguments for configuration %s", GetName());
270         fArgc=-EINVAL;
271       }
272     } else if (fArgc<0) {
273       HLTError("previous argument extraction failed");
274     }
275     //HLTDebug("%s fArgc %d", GetName(), fArgc);
276     iResult=fArgc;
277     *pArgv=(const char**)fArgv;
278   } else {
279     HLTError("invalid parameter");
280     iResult=-EINVAL;
281   }
282   return iResult;
283 }
284
285
286 int AliHLTConfiguration::ExtractSources()
287 {
288   // see header file for function documentation
289   int iResult=0;
290   fNofSources=0;
291   if (fStringSources!=NULL) {
292     vector<char*> tgtList;
293     fListSources.clear();
294     if ((iResult=InterpreteString(fStringSources, tgtList))>=0) {
295       fNofSources=tgtList.size();
296       vector<char*>::iterator element=tgtList.begin();
297       while ((element=tgtList.begin())!=tgtList.end()) {
298         if (fgConfigurationHandler) {
299           AliHLTConfiguration* pConf=fgConfigurationHandler->FindConfiguration(*element);
300           if (pConf) {
301             HLTDebug("source \"%s\" inserted", pConf->GetName());
302             fListSources.push_back(pConf);
303           } else {
304             HLTError("can not find source \"%s\"", (*element));
305             iResult=-ENOENT;
306           }
307         } else if (iResult>=0) {
308           iResult=-EFAULT;
309           HLTFatal("global configuration handler not initialized, can not resolve sources");
310         }
311         delete[] (*element);
312         tgtList.erase(element);
313       }
314       fListSrcElement=fListSources.begin();
315     }
316   }
317   return iResult;
318 }
319
320 int AliHLTConfiguration::ExtractArguments()
321 {
322   // see header file for function documentation
323   int iResult=0;
324   if (fArguments!=NULL) {
325     vector<char*> tgtList;
326     if ((iResult=InterpreteString(fArguments, tgtList))>=0) {
327       fArgc=tgtList.size();
328       //HLTDebug("configuration %s: extracted %d arguments from \"%s\"", GetName(), fArgc, fArguments);
329       if (fArgc>0) {
330         fArgv = new char*[fArgc];
331         if (fArgv) {
332           vector<char*>::iterator element=tgtList.begin();
333           int i=0;
334           while (element!=tgtList.end()) {
335             //HLTDebug("assign arguments %d (%s)", i, *element);
336             fArgv[i++]=(*element);
337             element++;
338           }
339         } else {
340           iResult=-ENOMEM;
341         }
342       }
343     }
344   } else {
345     // there are zero arguments
346     fArgc=0;
347   }
348   return iResult;
349 }
350
351 int AliHLTConfiguration::InterpreteString(const char* arg, vector<char*>& argList)
352 {
353   // see header file for function documentation
354   int iResult=0;
355   if (arg) {
356     //HLTDebug("interprete \"%s\"", arg);
357     int i=0;
358     int prec=-1;
359     int bQuote=0;
360     do {
361       //HLTDebug("%d %x", i, arg[i]);
362       if (arg[i]=='\'' && bQuote==0) {
363         bQuote=1;
364       } else if (arg[i]==0 || 
365                  (arg[i]==' ' && bQuote==0) ||
366                  (arg[i]=='\'' && bQuote==1)) {
367         bQuote=0;
368         if (prec>=0) {
369           char* pEntry= new char[i-prec+1];
370           if (pEntry) {
371             strncpy(pEntry, &arg[prec], i-prec);
372             pEntry[i-prec]=0; // terminate string
373             //HLTDebug("create string \"%s\", insert at %d", pEntry, argList.size());
374             argList.push_back(pEntry);
375           } else 
376             iResult=-ENOMEM;
377           prec=-1;
378         }
379       } else if (prec==-1) prec=i;
380     } while (arg[i++]!=0 && iResult>=0); 
381   } else {
382     iResult=-EINVAL;
383   }
384   return iResult;
385 }
386
387 int AliHLTConfiguration::FollowDependency(const char* id, TList* pTgtList)
388 {
389   // see header file for function documentation
390   int iResult=0;
391   if (id) {
392     AliHLTConfiguration* pDep=NULL;
393     if ((pDep=GetSource(id))!=NULL) {
394       if (pTgtList) pTgtList->Add(pDep);
395       iResult++;
396     } else {
397       pDep=GetFirstSource();
398       while (pDep && iResult==0) {
399         if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
400           if (pTgtList) pTgtList->AddFirst(pDep);
401           iResult++;
402         }
403         pDep=GetNextSource();
404       }
405     }
406   } else {
407     iResult=-EINVAL;
408   }
409   return iResult;
410 }
411
412 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
413
414 /** ROOT macro for the implementation of ROOT specific class methods */
415 ClassImp(AliHLTTask)
416
417 AliHLTTask::AliHLTTask()
418   :
419   fpConfiguration(NULL),
420   fpComponent(NULL),
421   fpDataBuffer(NULL),
422   fListTargets(),
423   fListDependencies(),
424   fpBlockDataArray(NULL),
425   fBlockDataArraySize(0)
426 {
427   // see header file for function documentation
428 }
429
430 AliHLTTask::AliHLTTask(AliHLTConfiguration* pConf)
431   :
432   fpConfiguration(pConf),
433   fpComponent(NULL),
434   fpDataBuffer(NULL),
435   fListTargets(),
436   fListDependencies(),
437   fpBlockDataArray(NULL),
438   fBlockDataArraySize(0)
439 {
440   // see header file for function documentation
441 }
442
443 AliHLTTask::AliHLTTask(const AliHLTTask&)
444   :
445   TObject(),
446   AliHLTLogging(),
447   fpConfiguration(NULL),
448   fpComponent(NULL),
449   fpDataBuffer(NULL),
450   fListTargets(),
451   fListDependencies(),
452   fpBlockDataArray(NULL),
453   fBlockDataArraySize(0)
454 {
455   HLTFatal("copy constructor untested");
456 }
457
458 AliHLTTask& AliHLTTask::operator=(const AliHLTTask&)
459
460   // see header file for function documentation
461   HLTFatal("assignment operator untested");
462   return *this;
463 }
464
465 AliHLTTask::~AliHLTTask()
466 {
467   if (fpComponent) delete fpComponent;
468   fpComponent=NULL;
469   if (fpBlockDataArray) delete[] fpBlockDataArray;
470   fpBlockDataArray=NULL;
471 }
472
473 int AliHLTTask::Init(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH)
474 {
475   // see header file for function documentation
476   int iResult=0;
477   if (fpConfiguration!=NULL && pConf!=NULL && fpConfiguration!=pConf) {
478     HLTWarning("overriding existing reference to configuration object %p (%s) by %p",
479                fpConfiguration, GetName(), pConf);
480   }
481   if (pConf!=NULL) fpConfiguration=pConf;
482   if (fpConfiguration) {
483     if (pCH) {
484       int argc=0;
485       const char** argv=NULL;
486       if ((iResult=fpConfiguration->GetArguments(&argv))>=0) {
487         argc=iResult; // just to make it clear
488         // TODO: we have to think about the optional environment parameter,
489         // currently just set to NULL. 
490         iResult=pCH->CreateComponent(fpConfiguration->GetComponentID(), NULL, argc, argv, fpComponent);
491         if (fpComponent || iResult<=0) {
492         } else {
493           HLTError("can not find component \"%s\" (%d)", fpConfiguration->GetComponentID(), iResult);
494         }
495       } else {
496         HLTError("can not get argument list for configuration %s (%s)", fpConfiguration->GetName(), fpConfiguration->GetComponentID());
497         iResult=-EINVAL;
498       }
499     } else {
500       HLTError("component handler instance needed for task initialization");
501       iResult=-EINVAL;
502     }
503   } else {
504     HLTError("configuration object instance needed for task initialization");
505     iResult=-EINVAL;
506   }
507   return iResult;
508 }
509
510 int AliHLTTask::Deinit()
511 {
512   // see header file for function documentation
513   int iResult=0;
514   AliHLTComponent* pComponent=GetComponent();
515   fpComponent=NULL;
516   if (pComponent) {
517     pComponent->Deinit();
518     delete pComponent;
519   } else {
520     HLTWarning("task %s (%p) doesn't seem to be in initialized", GetName(), this);
521   }
522   return iResult;
523 }
524
525 const char *AliHLTTask::GetName() const
526 {
527   // see header file for function documentation
528   if (fpConfiguration)
529     return fpConfiguration->GetName();
530   return TObject::GetName();
531 }
532
533 AliHLTConfiguration* AliHLTTask::GetConf() const
534 {
535   // see header file for function documentation
536   return fpConfiguration;
537 }
538
539 AliHLTComponent* AliHLTTask::GetComponent() const
540 {
541   // see header file for function documentation
542   return fpComponent;
543 }
544
545 AliHLTTask* AliHLTTask::FindDependency(const char* id)
546 {
547   // see header file for function documentation
548   AliHLTTask* pTask=NULL;
549   if (id) {
550     pTask=(AliHLTTask*)fListDependencies.FindObject(id);
551   }
552   return pTask;
553 }
554
555 int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
556 {
557   // see header file for function documentation
558   int iResult=0;
559   if (id) {
560     AliHLTTask* pDep=NULL;
561     if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
562       if (pTgtList) pTgtList->Add(pDep);
563       iResult++;
564     } else {
565       TObjLink* lnk=fListDependencies.FirstLink();
566       while (lnk && iResult==0) {
567         pDep=(AliHLTTask*)lnk->GetObject();
568         if (pDep) {
569           if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
570             if (pTgtList) pTgtList->AddFirst(pDep);
571             iResult++;
572           }
573         } else {
574           iResult=-EFAULT;
575         }
576         lnk=lnk->Next();
577       }
578     }
579   } else {
580     iResult=-EINVAL;
581   }
582   return iResult;
583 }
584
585 void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
586 {
587   // see header file for function documentation
588   HLTLogKeyword("task dependencies");
589   int iResult=0;
590   TList tgtList;
591   if (bFromConfiguration) {
592     if (fpConfiguration)
593       iResult=fpConfiguration->FollowDependency(id, &tgtList);
594     else
595       iResult=-EFAULT;
596   } else
597     iResult=FollowDependency(id, &tgtList);
598   if (iResult>0) {
599     HLTMessage("     task \"%s\": dependency level %d ", GetName(), iResult);
600     TObjLink* lnk=tgtList.FirstLink();
601     int i=iResult;
602     char* pSpace = new char[iResult+1];
603     if (pSpace) {
604       memset(pSpace, 32, iResult);
605       pSpace[i]=0;
606       while (lnk) {
607         TObject* obj=lnk->GetObject();
608         HLTMessage("     %s^-- %s ", &pSpace[i--], obj->GetName());
609         lnk=lnk->Next();
610       }
611       delete [] pSpace;
612     } else {
613       iResult=-ENOMEM;
614     }
615   }
616 }
617
618 int AliHLTTask::SetDependency(AliHLTTask* pDep)
619 {
620   // see header file for function documentation
621   int iResult=0;
622   if (pDep) {
623     if (FindDependency(pDep->GetName())==NULL) {
624       fListDependencies.Add(pDep);
625     } else {
626       iResult=-EEXIST;
627     }
628   } else {
629     iResult=-EINVAL;
630   }
631   return iResult;
632 }
633
634 int AliHLTTask::CheckDependencies()
635 {
636   // see header file for function documentation
637   int iResult=0;
638   AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
639   while (pSrc) {
640     if (FindDependency(pSrc->GetName())==NULL) {
641       //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
642       iResult++;
643     }
644     pSrc=fpConfiguration->GetNextSource();
645   }
646   return iResult;
647 }
648
649
650 int AliHLTTask::Depends(AliHLTTask* pTask)
651 {
652   // see header file for function documentation
653   int iResult=0;
654   if (pTask) {
655     if (fpConfiguration) {
656       iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
657       if (iResult>0) {
658         //HLTDebug("task  \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
659       } else {
660         //HLTDebug("task  \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
661       }
662     } else {
663       iResult=-EFAULT;
664     }
665   } else {
666     iResult=-EINVAL;
667   }
668   return iResult;
669 }
670
671 AliHLTTask* AliHLTTask::FindTarget(const char* id)
672 {
673   // see header file for function documentation
674   AliHLTTask* pTask=NULL;
675   if (id) {
676     pTask=(AliHLTTask*)fListTargets.FindObject(id);
677   }
678   return pTask;
679 }
680
681 int AliHLTTask::SetTarget(AliHLTTask* pTgt)
682 {
683   // see header file for function documentation
684   int iResult=0;
685   if (pTgt) {
686     if (FindTarget(pTgt->GetName())==NULL) {
687       fListTargets.Add(pTgt);
688     } else {
689       iResult=-EEXIST;
690     }
691   } else {
692     iResult=-EINVAL;
693   }
694   return iResult;
695 }
696
697 int AliHLTTask::StartRun()
698 {
699   // see header file for function documentation
700   int iResult=0;
701   int iNofInputDataBlocks=0;
702   AliHLTComponent* pComponent=GetComponent();
703   if (pComponent) {
704     // determine the number of input data blocks provided from the source tasks
705     TObjLink* lnk=fListDependencies.FirstLink();
706     while (lnk && iResult>=0) {
707       AliHLTTask* pSrcTask=(AliHLTTask*)lnk->GetObject();
708       if (pSrcTask) {
709         if ((iResult=pSrcTask->GetNofMatchingDataTypes(this))>0) {
710           iNofInputDataBlocks+=iResult;
711         } else if (iResult==0) {
712           HLTWarning("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
713         } else {
714           HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
715           iResult=-EFAULT;
716         }
717       }
718       lnk=lnk->Next();
719     }
720     if (iResult>=0) {
721       if (fpBlockDataArray) {
722         HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
723         delete [] fpBlockDataArray;
724         fpBlockDataArray=NULL;
725         fBlockDataArraySize=0;
726       }
727
728       // component init
729       // the initialization of the component is done by the ComponentHandler after creation
730       // of the component.
731       //iResult=Init( AliHLTComponentEnvironment* environ, void* environ_param, int argc, const char** argv );
732
733       // allocate internal task variables for bookkeeping aso.
734       // we allocate the BlockData array with at least one member
735       if (iNofInputDataBlocks==0) iNofInputDataBlocks=1;
736       fpBlockDataArray=new AliHLTComponentBlockData[iNofInputDataBlocks];
737       if (fpBlockDataArray) {
738         fBlockDataArraySize=iNofInputDataBlocks;
739       } else {
740         HLTError("memory allocation failed");
741         iResult=-ENOMEM;
742       }
743
744       // allocate the data buffer, which controls the output buffer and subscriptions
745       if (iResult>=0) {
746         fpDataBuffer=new AliHLTDataBuffer;
747         if (fpDataBuffer!=NULL) {
748           HLTDebug("created data buffer %p for task %s (%p)", fpDataBuffer, GetName(), this);
749           TObjLink* lnk=fListTargets.FirstLink();
750           while (lnk && iResult>=0) {
751             AliHLTTask* pTgtTask=(AliHLTTask*)lnk->GetObject();
752             if (pTgtTask) {
753               if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
754               }
755             } else {
756               break;
757               iResult=-EFAULT;
758             }
759             lnk=lnk->Next();
760           }
761         } else {
762           HLTFatal("can not create data buffer object, memory allocation failed");
763           iResult=-ENOMEM;
764         }
765       }
766     }
767   } else {
768     HLTError("task %s (%p) does not have a component", GetName(), this);
769     iResult=-EFAULT;
770   }
771   return iResult;
772 }
773
774 int AliHLTTask::EndRun()
775 {
776   // see header file for function documentation
777   int iResult=0;
778   if (fpBlockDataArray) {
779     fBlockDataArraySize=0;
780     delete [] fpBlockDataArray;
781     fpBlockDataArray=0;
782   } else {
783     HLTWarning("task %s (%p) doesn't seem to be in running mode", GetName(), this);
784   }
785   if (fpDataBuffer) {
786     AliHLTDataBuffer* pBuffer=fpDataBuffer;
787     fpDataBuffer=NULL;
788     delete pBuffer;
789   }
790   return iResult;
791 }
792
793 int AliHLTTask::ProcessTask(Int_t eventNo)
794 {
795   // see header file for function documentation
796   int iResult=0;
797   AliHLTComponent* pComponent=GetComponent();
798   if (pComponent && fpDataBuffer) {
799     HLTDebug("Processing task %s (%p) fpDataBuffer %p", GetName(), this, fpDataBuffer);
800     fpDataBuffer->Reset();
801     int iSourceDataBlock=0;
802     int iInputDataVolume=0;
803
804     int iNofInputDataBlocks=0;
805     /* TODO: the assumption of only one output data type per component is the current constraint
806      * later it should be checked how many output blocks of the source component match the input
807      * data types of the consumer component (GetNofMatchingDataBlocks). If one assumes that a
808      * certain output block is always been produced, the initialization could be done in the
809      * StartRun. Otherwise the fpBlockDataArray has to be adapted each time.
810      */
811     iNofInputDataBlocks=fListDependencies.GetSize(); // one block per source
812     // is not been used since the allocation was done in StartRun, but check the size
813     if (iNofInputDataBlocks>fBlockDataArraySize) {
814       HLTError("block data array too small");
815     }
816
817     AliHLTTask* pSrcTask=NULL;
818     TList subscribedTaskList;
819     TObjLink* lnk=fListDependencies.FirstLink();
820
821     // subscribe to all source tasks
822     while (lnk && iResult>=0) {
823       pSrcTask=(AliHLTTask*)lnk->GetObject();
824       if (pSrcTask) {
825         int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
826         if (iMatchingDB<=fBlockDataArraySize-iSourceDataBlock) {
827           if (fpBlockDataArray) {
828           if ((iResult=pSrcTask->Subscribe(this, &fpBlockDataArray[iSourceDataBlock],fBlockDataArraySize-iSourceDataBlock))>0) {
829             for (int i=0; i<iResult; i++) {
830               iInputDataVolume+=fpBlockDataArray[i+iSourceDataBlock].fSize;
831               // put the source task as many times into the list as it provides data blocks
832               // makes the bookkeeping for the data release easier
833               subscribedTaskList.Add(pSrcTask);
834             }
835             iSourceDataBlock+=iResult;
836             HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask);
837             iResult=0;
838           } else {
839             HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
840             iResult=-EFAULT;
841           }
842           } else {
843             HLTFatal("Task %s (%p): BlockData array not allocated", GetName(), this);
844             iResult=-EFAULT;
845           }
846         } else {
847           HLTFatal("Task %s (%p): too little space in data block array for subscription to task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
848           HLTDebug("#data types=%d, array size=%d, current index=%d", iMatchingDB, fBlockDataArraySize, iSourceDataBlock);
849           iResult=-EFAULT;
850         }
851       } else {
852         HLTFatal("fatal internal error in ROOT list handling");
853         iResult=-EFAULT;
854       }
855       lnk=lnk->Next();
856     }
857
858     // process the event
859     if (iResult>=0) {
860       long unsigned int iConstBase=0;
861       double fInputMultiplier=0;
862       if (pComponent->GetComponentType()!=AliHLTComponent::kSink)
863         pComponent->GetOutputDataSize(iConstBase, fInputMultiplier);
864       int iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
865       //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
866       AliHLTUInt8_t* pTgtBuffer=NULL;
867       if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
868       //HLTDebug("provided raw buffer %p", pTgtBuffer);
869       AliHLTComponentEventData evtData;
870       AliHLTComponent::FillEventData(evtData);
871       evtData.fEventID=(AliHLTEventID_t)eventNo;
872       evtData.fBlockCnt=iSourceDataBlock;
873       AliHLTComponentTriggerData trigData;
874       AliHLTUInt32_t size=iOutputDataSize;
875       AliHLTUInt32_t outputBlockCnt=0;
876       AliHLTComponentBlockData* outputBlocks=NULL;
877       AliHLTComponentEventDoneData* edd;
878       if (pTgtBuffer!=NULL || iOutputDataSize==0) {
879         iResult=pComponent->ProcessEvent(evtData, fpBlockDataArray, trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
880         HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt);
881         if (iResult>=0 && pTgtBuffer) {
882           iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt);
883         }
884       } else {
885         HLTError("task %s: no target buffer available", GetName());
886         iResult=-EFAULT;
887       }
888     }
889
890     // now release all buffers which we have subscribed to
891     iSourceDataBlock=0;
892     lnk=subscribedTaskList.FirstLink();
893     while (lnk) {
894       pSrcTask=(AliHLTTask*)lnk->GetObject();
895       if (pSrcTask) {
896         int iTempRes=0;
897         if ((iTempRes=pSrcTask->Release(&fpBlockDataArray[iSourceDataBlock], this))>=0) {
898           HLTDebug("Task %s (%p) successfully released task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
899         } else {
900           HLTError("Task %s (%p): realease of task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iTempRes);
901         }
902       } else {
903         HLTFatal("task %s (%p): internal error in ROOT list handling", GetName(), this);
904         if (iResult>=0) iResult=-EFAULT;
905       }
906       subscribedTaskList.Remove(lnk);
907       lnk=subscribedTaskList.FirstLink();
908       iSourceDataBlock++;
909     }
910     if (subscribedTaskList.GetSize()>0) {
911       HLTError("task %s (%p): could not release all data buffers", GetName(), this);
912     }
913   } else {
914     HLTError("task %s (%p): internal failure (not initialized component %p, data buffer %p)", GetName(), this, fpComponent, fpDataBuffer);
915     iResult=-EFAULT;
916   }
917   return iResult;
918 }
919
920 int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
921 {
922   // see header file for function documentation
923   int iResult=0;
924   if (pConsumerTask) {
925     if (fpDataBuffer) {
926       iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
927     } else {
928       HLTFatal("internal data buffer missing");
929       iResult=-EFAULT;
930     }
931   } else {
932     iResult=-EINVAL;
933   }
934   return iResult;
935 }
936
937 int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
938 {
939   // see header file for function documentation
940   int iResult=0;
941   if (pConsumerTask) {
942     AliHLTComponent* pComponent=GetComponent();
943     if (!pComponent) {
944       // init ?
945       HLTError("component not initialized");
946       iResult=-EFAULT;
947     }
948     if (pComponent) {
949       iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
950     } else {
951       HLTFatal("task initialization failed");
952       iResult=-EFAULT;
953     }
954   } else {
955     iResult=-EINVAL;
956   }
957   return iResult;
958 }
959
960 int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockData* pBlockDesc, int iArraySize)
961 {
962   // see header file for function documentation
963   int iResult=0;
964   if (pConsumerTask) {
965     if (fpDataBuffer) {
966       iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), pBlockDesc, iArraySize);
967     } else {
968       HLTFatal("internal data buffer missing");
969       iResult=-EFAULT;
970     }
971   } else {
972     iResult=-EINVAL;
973   }
974   return iResult;
975 }
976
977 int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
978 {
979   // see header file for function documentation
980   int iResult=0;
981   if (pConsumerTask && pBlockDesc) {
982     if (fpDataBuffer) {
983       iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent());
984     } else {
985       HLTFatal("internal data buffer missing");
986       iResult=-EFAULT;
987     }
988   } else {
989     iResult=-EINVAL;
990   }
991   return iResult;
992 }
993
994 void AliHLTTask::PrintStatus()
995 {
996   // see header file for function documentation
997   HLTLogKeyword("task properties");
998   AliHLTComponent* pComponent=GetComponent();
999   if (pComponent) {
1000     HLTMessage("     component: %s (%p)", pComponent->GetComponentID(), pComponent);
1001   } else {
1002     HLTMessage("     no component set!");
1003   }
1004   if (fpConfiguration) {
1005     AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
1006     while (pSrc) {
1007       const char* pQualifier="unresolved";
1008       if (FindDependency(pSrc->GetName()))
1009         pQualifier="resolved";
1010       HLTMessage("     source: %s (%s)", pSrc->GetName(), pQualifier);
1011       pSrc=fpConfiguration->GetNextSource();
1012     }
1013     TObjLink* lnk = fListTargets.FirstLink();
1014     while (lnk) {
1015       TObject *obj = lnk->GetObject();
1016       HLTMessage("     target: %s", obj->GetName());
1017       lnk = lnk->Next();
1018     }
1019   } else {
1020     HLTMessage("     task \"%s\" not initialized", GetName());
1021   }
1022 }
1023
1024 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1025
1026 /** ROOT macro for the implementation of ROOT specific class methods */
1027 ClassImp(AliHLTConfigurationHandler)
1028
1029 AliHLTConfigurationHandler::AliHLTConfigurationHandler()
1030 {
1031   // see header file for function documentation
1032   SetLocalLogLevel(kHLTLogInfo);
1033 }
1034
1035 AliHLTConfigurationHandler::~AliHLTConfigurationHandler()
1036 {
1037   // see header file for function documentation
1038   TObjLink* lnk=fgListConfigurations.FirstLink();
1039   while (lnk) {
1040     TObject* obj=lnk->GetObject();
1041     if (fgListConfigurations.FindObject(obj->GetName())==NULL) {
1042       HLTDebug("delete configuration \"%s\"", obj->GetName());
1043       delete obj;
1044     }
1045     lnk=lnk->Next();
1046   }
1047 }
1048
1049 int AliHLTConfigurationHandler::RegisterConfiguration(AliHLTConfiguration* pConf)
1050 {
1051   // see header file for function documentation
1052   int iResult=0;
1053   if (pConf) {
1054     if (FindConfiguration(pConf->GetName()) == NULL) {
1055       AliHLTConfiguration* pClone=new AliHLTConfiguration(*pConf);
1056       fgListConfigurations.Add(pClone);
1057       HLTDebug("configuration \"%s\" registered", pClone->GetName());
1058
1059       // mark all configurations with unresolved dependencies for re-evaluation
1060       TObjLink* lnk=fgListConfigurations.FirstLink();
1061       while (lnk) {
1062         AliHLTConfiguration* pSrc=(AliHLTConfiguration*)lnk->GetObject();
1063         if (pSrc && pSrc!=pClone && pSrc->SourcesResolved()!=1) {
1064           pSrc->InvalidateSources();
1065         }
1066         lnk=lnk->Next();
1067       }
1068     } else {
1069       iResult=-EEXIST;
1070       HLTWarning("configuration \"%s\" already registered", pConf->GetName());
1071     }
1072   } else {
1073     iResult=-EINVAL;
1074   }
1075   return iResult;
1076 }
1077
1078 int AliHLTConfigurationHandler::CreateConfiguration(const char* id, const char* component, const char* sources, const char* arguments)
1079 {
1080   // see header file for function documentation
1081   int iResult=0;
1082   AliHLTConfiguration* pConf= new AliHLTConfiguration(id, component, sources, arguments);
1083   if (pConf) {
1084     // the configuration will be registered automatically, if this failes the configuration
1085     // is missing -> delete it
1086     if (FindConfiguration(id)==NULL) {
1087       delete pConf;
1088       pConf=NULL;
1089       iResult=-EEXIST;
1090     }
1091   } else {
1092     HLTError("system error: object allocation failed");
1093     iResult=-ENOMEM;
1094   }
1095   return iResult;
1096 }
1097
1098 void AliHLTConfigurationHandler::PrintConfigurations()
1099 {
1100   // see header file for function documentation
1101   HLTLogKeyword("configuration listing");
1102   HLTMessage("registered configurations:");
1103   TObjLink *lnk = fgListConfigurations.FirstLink();
1104   while (lnk) {
1105     TObject *obj = lnk->GetObject();
1106     HLTMessage("  %s", obj->GetName());
1107     lnk = lnk->Next();
1108   }
1109 }
1110
1111 int AliHLTConfigurationHandler::RemoveConfiguration(const char* id)
1112 {
1113   // see header file for function documentation
1114   int iResult=0;
1115   if (id) {
1116     AliHLTConfiguration* pConf=NULL;
1117     if ((pConf=FindConfiguration(id))!=NULL) {
1118       iResult=RemoveConfiguration(pConf);
1119       delete pConf;
1120       pConf=NULL;
1121     } else {
1122       HLTWarning("can not find configuration \"%s\"", id);
1123       iResult=-ENOENT;
1124     }
1125   } else {
1126     iResult=-EINVAL;
1127   }
1128   return iResult;
1129 }
1130
1131 int AliHLTConfigurationHandler::RemoveConfiguration(AliHLTConfiguration* pConf)
1132 {
1133   // see header file for function documentation
1134   int iResult=0;
1135   if (pConf) {
1136     // remove the configuration from the list
1137     HLTDebug("remove configuration \"%s\"", pConf->GetName());
1138     fgListConfigurations.Remove(pConf);
1139     // remove cross links in the remaining configurations
1140     TObjLink* lnk=fgListConfigurations.FirstLink();
1141     while (lnk && iResult>=0) {
1142       AliHLTConfiguration* pRem=(AliHLTConfiguration*)lnk->GetObject();
1143       if (pRem) {
1144         pRem->InvalidateSource(pConf);
1145       } else {
1146         iResult=-EFAULT;
1147       }
1148       lnk=lnk->Next();
1149     }
1150   }
1151   return iResult;
1152 }
1153
1154 AliHLTConfiguration* AliHLTConfigurationHandler::FindConfiguration(const char* id)
1155 {
1156   // see header file for function documentation
1157   AliHLTConfiguration* pConf=NULL;
1158   if (id) {
1159     pConf=(AliHLTConfiguration*)fgListConfigurations.FindObject(id); 
1160   }
1161   return pConf;
1162 }
1163