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