minor bugfix regarding optional propagation of component statistics:
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTTask.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   AliHLTTask.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 <cassert>
37 #include <iostream>
38 #include <string>
39 #include "AliHLTTask.h"
40 #include "AliHLTConfiguration.h"
41 #include "AliHLTComponent.h"
42 #include "AliHLTComponentHandler.h"
43 #include "TList.h"
44
45 /** ROOT macro for the implementation of ROOT specific class methods */
46 ClassImp(AliHLTTask)
47
48 AliHLTTask::AliHLTTask()
49   :
50   fpConfiguration(NULL),
51   fpComponent(NULL),
52   fpDataBuffer(NULL),
53   fListTargets(),
54   fListDependencies(),
55   fBlockDataArray()
56 {
57   // see header file for class documentation
58   // or
59   // refer to README to build package
60   // or
61   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
62 }
63
64 AliHLTTask::AliHLTTask(AliHLTConfiguration* pConf)
65   :
66   fpConfiguration(pConf),
67   fpComponent(NULL),
68   fpDataBuffer(NULL),
69   fListTargets(),
70   fListDependencies(),
71   fBlockDataArray()
72 {
73   // see header file for function documentation
74 }
75
76 AliHLTTask::~AliHLTTask()
77 {
78   // see header file for function documentation
79   TObjLink* lnk=fListDependencies.FirstLink();
80
81   while (lnk!=NULL) {
82     AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
83     pTask->UnsetTarget(this);
84     lnk=lnk->Next();
85   }
86   lnk=fListTargets.FirstLink();
87
88   while (lnk!=NULL) {
89     AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
90     pTask->UnsetDependency(this);
91     lnk=lnk->Next();
92   }
93
94   if (fpComponent) delete fpComponent;
95   fpComponent=NULL;
96 }
97
98 int AliHLTTask::Init(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH)
99 {
100   // see header file for function documentation
101   int iResult=0;
102   if (fpConfiguration!=NULL && pConf!=NULL && fpConfiguration!=pConf) {
103     HLTWarning("overriding existing reference to configuration object %p by %p",
104                fpConfiguration, pConf);
105   }
106   if (pConf!=NULL) fpConfiguration=pConf;
107   iResult=CreateComponent(fpConfiguration, pCH, fpComponent);
108   if (iResult>=0) {
109     iResult=CustomInit(pCH);
110   }
111   return iResult;
112 }
113
114 int AliHLTTask::CreateComponent(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH, AliHLTComponent*& pComponent) const
115 {
116   // see header file for class documentation
117   int iResult=0;
118   if (pConf) {
119     if (pCH) {
120       int argc=0;
121       const char** argv=NULL;
122       if ((iResult=pConf->GetArguments(&argv))>=0) {
123         argc=iResult; // just to make it clear
124         // TODO: we have to think about the optional environment parameter,
125         // currently just set to NULL.
126         iResult=pCH->CreateComponent(pConf->GetComponentID(), pComponent);
127         if (pComponent && iResult>=0) {
128           TString description;
129           description.Form("chainid=%s", GetName());
130           pComponent->SetComponentDescription(description.Data());
131           const AliHLTAnalysisEnvironment* pEnv=pCH->GetEnvironment();
132           if ((iResult=pComponent->Init(pEnv, NULL, argc, argv))>=0) {
133             //HLTDebug("component %s (%p) created", pComponent->GetComponentID(), pComponent); 
134           } else {
135             HLTError("Initialization of component \"%s\" failed with error %d", pComponent->GetComponentID(), iResult);
136           }
137         } else {
138           //HLTError("can not find component \"%s\" (%d)", pConf->GetComponentID(), iResult);
139         }
140       } else {
141         HLTError("can not get argument list for configuration %s (%s)", pConf->GetName(), pConf->GetComponentID());
142         iResult=-EINVAL;
143       }
144     } else {
145       HLTError("component handler instance needed for task initialization");
146       iResult=-EINVAL;
147     }
148   } else {
149     HLTError("configuration object instance needed for task initialization");
150     iResult=-EINVAL;
151   }
152   return iResult;
153 }
154
155 int AliHLTTask::Deinit()
156 {
157   // see header file for function documentation
158   int iResult=0;
159   CustomCleanup();
160   AliHLTComponent* pComponent=GetComponent();
161   fpComponent=NULL;
162   if (pComponent) {
163     //HLTDebug("delete component %s (%p)", pComponent->GetComponentID(), pComponent); 
164     pComponent->Deinit();
165     delete pComponent;
166   } else {
167     HLTWarning("task doesn't seem to be in initialized");
168   }
169   return iResult;
170 }
171
172 const char *AliHLTTask::GetName() const
173 {
174   // see header file for function documentation
175   if (fpConfiguration)
176     return fpConfiguration->GetName();
177   return TObject::GetName();
178 }
179
180 AliHLTConfiguration* AliHLTTask::GetConf() const
181 {
182   // see header file for function documentation
183   return fpConfiguration;
184 }
185
186 AliHLTComponent* AliHLTTask::GetComponent() const
187 {
188   // see header file for function documentation
189   return fpComponent;
190 }
191
192 AliHLTTask* AliHLTTask::FindDependency(const char* id)
193 {
194   // see header file for function documentation
195   AliHLTTask* pTask=NULL;
196   if (id) {
197     pTask=(AliHLTTask*)fListDependencies.FindObject(id);
198   }
199   return pTask;
200 }
201
202 int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
203 {
204   // see header file for function documentation
205   int iResult=0;
206   if (id) {
207     AliHLTTask* pDep=NULL;
208     if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
209       if (pTgtList) pTgtList->Add(pDep);
210       iResult++;
211     } else {
212       TObjLink* lnk=fListDependencies.FirstLink();
213       while (lnk && iResult==0) {
214         pDep=(AliHLTTask*)lnk->GetObject();
215         if (pDep) {
216           if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
217             if (pTgtList) pTgtList->AddFirst(pDep);
218             iResult++;
219           }
220         } else {
221           iResult=-EFAULT;
222         }
223         lnk=lnk->Next();
224       }
225     }
226   } else {
227     iResult=-EINVAL;
228   }
229   return iResult;
230 }
231
232 void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
233 {
234   // see header file for function documentation
235   HLTLogKeyword("task dependencies");
236   int iResult=0;
237   TList tgtList;
238   if (bFromConfiguration) {
239     if (fpConfiguration)
240       iResult=fpConfiguration->FollowDependency(id, &tgtList);
241     else
242       iResult=-EFAULT;
243   } else
244     iResult=FollowDependency(id, &tgtList);
245   if (iResult>0) {
246     HLTMessage("     dependency level %d ", iResult);
247     TObjLink* lnk=tgtList.FirstLink();
248     int i=iResult;
249     char* pSpace = new char[iResult+1];
250     if (pSpace) {
251       memset(pSpace, 32, iResult);
252       pSpace[i]=0;
253       while (lnk) {
254         TObject* obj=lnk->GetObject();
255         HLTMessage("     %s^-- %s ", &pSpace[i--], obj->GetName());
256         lnk=lnk->Next();
257       }
258       delete [] pSpace;
259     } else {
260       iResult=-ENOMEM;
261     }
262   }
263 }
264
265 int AliHLTTask::SetDependency(AliHLTTask* pDep)
266 {
267   // see header file for function documentation
268   int iResult=0;
269   if (pDep) {
270     if (FindDependency(pDep->GetName())==NULL) {
271       fListDependencies.Add(pDep);
272     } else {
273       iResult=-EEXIST;
274     }
275   } else {
276     iResult=-EINVAL;
277   }
278   return iResult;
279 }
280
281 int AliHLTTask::UnsetDependency(AliHLTTask* pDep)
282 {
283   // see header file for function documentation
284   fListDependencies.Remove(pDep);
285   if (fpConfiguration) {
286     fpConfiguration->InvalidateSources();
287   }
288   return 0;
289 }
290
291 int AliHLTTask::CheckDependencies()
292 {
293   // see header file for function documentation
294   int iResult=0;
295   AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
296   while (pSrc) {
297     if (FindDependency(pSrc->GetName())==NULL) {
298       //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
299       iResult++;
300     }
301     pSrc=fpConfiguration->GetNextSource();
302   }
303   return iResult;
304 }
305
306
307 int AliHLTTask::Depends(AliHLTTask* pTask)
308 {
309   // see header file for function documentation
310   int iResult=0;
311   if (pTask) {
312     if (fpConfiguration) {
313       iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
314       if (iResult>0) {
315         //HLTDebug("task  \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
316       } else {
317         //HLTDebug("task  \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
318       }
319     } else {
320       iResult=-EFAULT;
321     }
322   } else {
323     iResult=-EINVAL;
324   }
325   return iResult;
326 }
327
328 AliHLTTask* AliHLTTask::FindTarget(const char* id)
329 {
330   // see header file for function documentation
331   AliHLTTask* pTask=NULL;
332   if (id) {
333     pTask=(AliHLTTask*)fListTargets.FindObject(id);
334   }
335   return pTask;
336 }
337
338 int AliHLTTask::SetTarget(AliHLTTask* pTgt)
339 {
340   // see header file for function documentation
341   int iResult=0;
342   if (pTgt) {
343     if (FindTarget(pTgt->GetName())==NULL) {
344       fListTargets.Add(pTgt);
345     } else {
346       iResult=-EEXIST;
347     }
348   } else {
349     iResult=-EINVAL;
350   }
351   return iResult;
352 }
353
354 int AliHLTTask::UnsetTarget(AliHLTTask* pTarget)
355 {
356   // see header file for function documentation
357   fListTargets.Remove(pTarget);
358   return 0;
359 }
360
361 int AliHLTTask::StartRun()
362 {
363   // see header file for function documentation
364   int iResult=0;
365   int iNofInputDataBlocks=0;
366   AliHLTComponent* pComponent=GetComponent();
367   if (pComponent) {
368     // determine the number of input data blocks provided from the source tasks
369     { // set scope for lnk as a local variable
370     TObjLink* lnk=fListDependencies.FirstLink();
371     while (lnk && iResult>=0) {
372       AliHLTTask* pSrcTask=(AliHLTTask*)lnk->GetObject();
373       if (pSrcTask) {
374         if ((iResult=pSrcTask->GetNofMatchingDataTypes(this))>0) {
375           iNofInputDataBlocks+=iResult;
376         } else if (iResult==0) {
377           HLTWarning("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
378         } else {
379           HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
380           iResult=-EFAULT;
381         }
382       }
383       lnk=lnk->Next();
384     }
385     }
386     if (iResult>=0) {
387       if (fBlockDataArray.size()>0) {
388         HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
389         fBlockDataArray.clear();
390       }
391
392       // component init
393       // the initialization of the component is done by the ComponentHandler after creation
394       // of the component.
395       //iResult=Init( AliHLTAnalysisEnvironment* environ, void* environ_param, int argc, const char** argv );
396
397       // allocate the data buffer, which controls the output buffer and subscriptions
398       if (iResult>=0) {
399         fpDataBuffer=new AliHLTDataBuffer;
400         if (fpDataBuffer!=NULL) {
401           fpDataBuffer->SetLocalLoggingLevel(GetLocalLoggingLevel());
402           HLTDebug("created data buffer %p for task %s (%p)", fpDataBuffer, GetName(), this);
403           TObjLink* lnk=fListTargets.FirstLink();
404           while (lnk && iResult>=0) {
405             AliHLTTask* pTgtTask=(AliHLTTask*)lnk->GetObject();
406             if (pTgtTask) {
407               if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
408               }
409             } else {
410               break;
411               iResult=-EFAULT;
412             }
413             lnk=lnk->Next();
414           }
415         } else {
416           HLTFatal("can not create data buffer object, memory allocation failed");
417           iResult=-ENOMEM;
418         }
419       }
420     }
421     if (iResult>=0) {
422       // send the SOR event
423       
424     }
425   } else {
426     HLTError("task %s (%p) does not have a component", GetName(), this);
427     iResult=-EFAULT;
428   }
429   return iResult;
430 }
431
432 int AliHLTTask::EndRun()
433 {
434   // see header file for function documentation
435   int iResult=0;
436   if (fBlockDataArray.size()>0) {
437     fBlockDataArray.clear();
438   }
439   if (fpDataBuffer) {
440     AliHLTDataBuffer* pBuffer=fpDataBuffer;
441     fpDataBuffer=NULL;
442     delete pBuffer;
443   }
444   return iResult;
445 }
446
447 int AliHLTTask::ProcessTask(Int_t eventNo, AliHLTUInt32_t eventType)
448 {
449   // see header file for function documentation
450   int iResult=0;
451   AliHLTComponent* pComponent=GetComponent();
452   if (pComponent && fpDataBuffer) {
453     HLTDebug("Processing task %s (%p) fpDataBuffer %p", GetName(), this, fpDataBuffer);
454     fpDataBuffer->Reset();
455     int iSourceDataBlock=0;
456     int iInputDataVolume=0;
457
458     AliHLTTask* pSrcTask=NULL;
459     AliHLTTaskPList subscribedTaskList;
460     TObjLink* lnk=fListDependencies.FirstLink();
461
462     // instances of SOR and EOR events to be kept
463     int iSOR=-1;
464     int iEOR=-1;
465
466     // subscribe to all source tasks
467     fBlockDataArray.clear();
468     while (lnk && iResult>=0) {
469       pSrcTask=(AliHLTTask*)lnk->GetObject();
470       if (pSrcTask) {
471         int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
472         if (iMatchingDB<0) {
473           HLTError("task %s (%p): error getting no of matching data blocks from task %s (%p), error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iMatchingDB);
474           iResult=iMatchingDB;
475           break;
476         } else if (iMatchingDB==0) {
477           HLTDebug("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
478         }
479         if ((iResult=pSrcTask->Subscribe(this, fBlockDataArray))>=0) {
480           iSOR=iEOR=-1;
481           AliHLTComponentBlockDataList::iterator block=fBlockDataArray.begin();
482           for (int i=0; block!=fBlockDataArray.end(); i++) {
483             bool bRemove=0;
484             bRemove|=(*block).fDataType==kAliHLTDataTypeSOR && !(iSOR<0 && (iSOR=i)>=0);
485             bRemove|=(*block).fDataType==kAliHLTDataTypeEOR && !(iEOR<0 && (iEOR=i)>=0);
486             //HLTInfo("block %d, iSOR=%d iEOR=%d remove=%d", i, iSOR, iEOR, bRemove);
487             if (i<iSourceDataBlock) {
488               assert(!bRemove);
489             } else if (bRemove) {
490               HLTDebug("remove duplicated event %s (%d)", AliHLTComponent::DataType2Text((*block).fDataType).c_str(), i);
491               pSrcTask->Release(&(*block), this);
492               block=fBlockDataArray.erase(block);
493               continue;
494             } else {
495             iInputDataVolume+=(*block).fSize;
496             // put the source task as many times into the list as it provides data blocks
497             // makes the bookkeeping for the data release easier
498             subscribedTaskList.push_back(pSrcTask);
499             }
500             block++;
501           }
502           HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask);
503           iSourceDataBlock=fBlockDataArray.size();        
504           iResult=0;
505         } else {
506           HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
507           iResult=-EFAULT;
508         }
509       } else {
510         HLTFatal("fatal internal error in ROOT list handling");
511         iResult=-EFAULT;
512       }
513       lnk=lnk->Next();
514     }    
515
516     // process the event
517     int iNofTrial=0; // repeat processing if component returns -ENOSPC
518     AliHLTUInt32_t iLastOutputDataSize=0;
519     if (iResult>=0) {
520     do {
521       long unsigned int iOutputDataSize=0;
522       AliHLTConfiguration* pConf=GetConf();
523       // check if there was a buffer size specified, query output size
524       // estimator from component otherwize
525       if (pConf && pConf->GetOutputBufferSize()>=0) {
526         iOutputDataSize=pConf->GetOutputBufferSize();
527       } else {
528       long unsigned int iConstBase=0;
529       double fInputMultiplier=0;
530       if (pComponent->GetComponentType()!=AliHLTComponent::kSink) {
531         pComponent->GetOutputDataSize(iConstBase, fInputMultiplier);
532         // add a small margin to the buffer to allow optional component
533         // statistics
534         iConstBase+=100;
535 #if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
536         for (AliHLTComponentBlockDataList::iterator element=fBlockDataArray.begin();
537              element!=fBlockDataArray.end(); element++) {
538           if (element->fDataType==kAliHLTDataTypeComponentStatistics) {
539             iConstBase+=element->fSize;
540           }
541         }
542 #endif
543       }
544       if (fInputMultiplier<0) {
545         HLTWarning("ignoring negative input multiplier");
546         fInputMultiplier=0;
547       }
548       iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
549       //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
550       }
551       if (iNofTrial>0) {
552         // dont process again if the buffer size is the same
553         if (iLastOutputDataSize==iOutputDataSize) break;
554         HLTImportant("processing event %d again with buffer size %d", eventNo, iOutputDataSize);
555       }
556       AliHLTUInt8_t* pTgtBuffer=NULL;
557       if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
558       //HLTDebug("provided raw buffer %p", pTgtBuffer);
559       AliHLTComponentEventData evtData;
560       AliHLTComponent::FillEventData(evtData);
561       if (eventNo>=0)
562         evtData.fEventID=(AliHLTEventID_t)eventNo;
563       AliHLTComponentTriggerData trigData;
564       trigData.fStructSize=sizeof(trigData);
565       trigData.fDataSize=0;
566       trigData.fData=NULL;
567       iLastOutputDataSize=iOutputDataSize;
568       AliHLTUInt32_t size=iOutputDataSize;
569       AliHLTUInt32_t outputBlockCnt=0;
570       AliHLTComponentBlockData* outputBlocks=NULL;
571       AliHLTComponentEventDoneData* edd=NULL;
572       if (pTgtBuffer!=NULL || iOutputDataSize==0) {
573         // add event type data block
574         // the block is removed immediately after processing from the list
575         AliHLTComponentBlockData eventTypeBlock;
576         AliHLTComponent::FillBlockData(eventTypeBlock);
577         // Note: no payload!
578         eventTypeBlock.fDataType=kAliHLTDataTypeEvent;
579         eventTypeBlock.fSpecification=eventType;
580         fBlockDataArray.push_back(eventTypeBlock);
581
582         // process
583         evtData.fBlockCnt=fBlockDataArray.size();
584         iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
585         HLTDebug("component %s ProcessEvent finnished (%d): size=%d blocks=%d", pComponent->GetComponentID(), iResult, size, outputBlockCnt);
586
587         // remove event data block
588         fBlockDataArray.pop_back();
589
590         // check for forwarded blocks.
591         // loop over all output blocks and check
592         // 1. for duplicate blocks (pointing to same location in output buffer
593         //    or to the same buffer)
594         // 2. for blocks forwarded from the input.
595         if (iResult>=0 && outputBlocks) {
596           if (fListTargets.First()!=NULL) {
597             AliHLTComponentBlockDataList segments;
598             for (AliHLTUInt32_t oblock=0; oblock<outputBlockCnt; oblock++) {
599               // consistency check for data reference
600               if (outputBlocks[oblock].fPtr!=NULL && outputBlocks[oblock].fPtr!=pTgtBuffer &&
601                   outputBlocks[oblock].fOffset!=0) {
602                 HLTWarning("output block %s 0x%08x has inconsistent data reference ptr=%p offset=0x%08x: "
603                            "for new blocks use offset only, forwarded blocks have fPtr set only",
604                            AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
605                            outputBlocks[oblock].fSpecification,
606                            outputBlocks[oblock].fPtr, outputBlocks[oblock].fOffset);
607               }
608
609               // check for duplicates in the output
610               AliHLTUInt32_t checkblock=0;
611               for (; checkblock<oblock; checkblock++) {
612                 if (outputBlocks[oblock].fPtr!=NULL && outputBlocks[oblock].fPtr!=pTgtBuffer &&
613                     outputBlocks[checkblock].fPtr==outputBlocks[oblock].fPtr) {
614                   if (outputBlocks[checkblock].fSize!=outputBlocks[oblock].fSize ||
615                       outputBlocks[checkblock].fDataType!=outputBlocks[oblock].fDataType) {
616                     HLTWarning("output blocks %d (%s 0x%08x) and %d (%s 0x%08x) have identical data references ptr=%p "
617                                "but differ in data type and/or size: %d vs. %d",
618                                oblock,
619                                AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
620                                outputBlocks[oblock].fSpecification,
621                                checkblock,
622                                AliHLTComponent::DataType2Text(outputBlocks[checkblock].fDataType).c_str(),
623                                outputBlocks[checkblock].fSpecification,
624                                outputBlocks[oblock].fPtr,
625                                outputBlocks[oblock].fSize,
626                                outputBlocks[checkblock].fSize);
627                   }
628                   // ignore from the second copy
629                   break;
630                 }
631               }
632               if (checkblock<oblock) continue;
633
634               // search for the forwarded data blocks
635               // new data blocks are announced to the data buffer, forwarded data blocks
636               // to the publisher task. The publisher task of a forwarded data block is
637               // removed from the list in order to keep the buffer open. It will be releases
638               // when the subscribing task releases it
639               AliHLTUInt32_t iblock=0;
640               for (; iblock<fBlockDataArray.size(); iblock++) {
641                 if (outputBlocks[oblock].fDataType==kAliHLTDataTypeEvent) {
642                   // the event type data block is ignored if it was forwarded
643                   break;
644                 }
645                 if (fBlockDataArray[iblock].fPtr==outputBlocks[oblock].fPtr) {
646                   assert(subscribedTaskList[iblock]!=NULL);
647                   if (subscribedTaskList[iblock]==NULL) continue;
648                   HLTDebug("forward segment %d (source task %s %p) to data buffer %p", iblock, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
649                   fpDataBuffer->Forward(subscribedTaskList[iblock], &fBlockDataArray[iblock]);
650                   subscribedTaskList[iblock]=NULL; // not to be released in the loop further down
651                   break;
652                 }
653               }
654               if (iblock==fBlockDataArray.size()) segments.push_back(outputBlocks[oblock]);
655             }
656             if (pTgtBuffer && segments.size()>0) {
657               iResult=fpDataBuffer->SetSegments(pTgtBuffer, &segments[0], segments.size());
658             }
659           } else {
660             // no forwarding, actually we dont even need to keep the data, this is a
661             // dead end (fListTargets empty)
662             //iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt);
663           }
664           delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0;
665         } else {
666           fpDataBuffer->Reset();
667         }
668         if (fListTargets.First()!=NULL) {
669           if (iSOR>=0 && subscribedTaskList[iSOR]!=NULL) {
670             HLTDebug("forward SOR event segment %d (source task %s %p) to data buffer %p", iSOR, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
671             fpDataBuffer->Forward(subscribedTaskList[iSOR], &fBlockDataArray[iSOR]);
672             subscribedTaskList[iSOR]=NULL; // not to be released in the loop further down
673           }
674           if (iEOR>=0 && subscribedTaskList[iEOR]!=NULL) {
675             HLTDebug("forward EOR event (%s) segment %d (source task %s %p) to data buffer %p", AliHLTComponent::DataType2Text(fBlockDataArray[iEOR].fDataType).c_str(), iEOR, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
676             fpDataBuffer->Forward(subscribedTaskList[iEOR], &fBlockDataArray[iEOR]);
677             subscribedTaskList[iEOR]=NULL; // not to be released in the loop further down
678           }
679         }
680       } else {
681         HLTError("no target buffer available");
682         iResult=-EFAULT;
683       }
684     } while (iResult==-ENOSPC && iNofTrial++<1);
685     }
686
687     // now release all buffers which we have subscribed to
688     iSourceDataBlock=0;
689     AliHLTTaskPList::iterator element;
690     while ((element=subscribedTaskList.begin())!=subscribedTaskList.end()) {
691       pSrcTask=*element;
692       if (pSrcTask) {
693         int iTempRes=0;
694         if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
695           HLTDebug("successfully released segment of task %s (%p)", pSrcTask->GetName(), pSrcTask);
696         } else {
697           HLTError("realease of task %s (%p) failed with error %d", pSrcTask->GetName(), pSrcTask, iTempRes);
698         }
699       }
700       subscribedTaskList.erase(element);
701       iSourceDataBlock++;
702     }
703     if (subscribedTaskList.size()>0) {
704       HLTError("could not release all data buffers");
705     }
706   } else {
707     HLTError("internal failure (not initialized component %p, data buffer %p)", fpComponent, fpDataBuffer);
708     iResult=-EFAULT;
709   }
710   return iResult;
711 }
712
713 int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
714 {
715   // see header file for function documentation
716   int iResult=0;
717   if (pConsumerTask) {
718     if (fpDataBuffer) {
719       iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
720     } else {
721       HLTFatal("internal data buffer missing");
722       iResult=-EFAULT;
723     }
724   } else {
725     iResult=-EINVAL;
726   }
727   return iResult;
728 }
729
730 int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
731 {
732   // see header file for function documentation
733   int iResult=0;
734   if (pConsumerTask) {
735     AliHLTComponent* pComponent=GetComponent();
736     if (!pComponent) {
737       // init ?
738       HLTError("component not initialized");
739       iResult=-EFAULT;
740     }
741     if (pComponent) {
742       iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
743     } else {
744       HLTFatal("task initialization failed");
745       iResult=-EFAULT;
746     }
747   } else {
748     iResult=-EINVAL;
749   }
750   return iResult;
751 }
752
753 int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockDataList& blockDescList)
754 {
755   // see header file for function documentation
756   int iResult=0;
757   if (pConsumerTask) {
758     if (fpDataBuffer) {
759       iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), blockDescList);
760     } else {
761       HLTFatal("internal data buffer missing");
762       iResult=-EFAULT;
763     }
764   } else {
765     iResult=-EINVAL;
766   }
767   return iResult;
768 }
769
770 int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
771 {
772   // see header file for function documentation
773   int iResult=0;
774   if (pConsumerTask && pBlockDesc) {
775     if (fpDataBuffer) {
776       iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent(), this);
777     } else {
778       HLTFatal("internal data buffer missing");
779       iResult=-EFAULT;
780     }
781   } else {
782     iResult=-EINVAL;
783   }
784   return iResult;
785 }
786
787 void AliHLTTask::PrintStatus()
788 {
789   // see header file for function documentation
790   HLTLogKeyword("task properties");
791   AliHLTComponent* pComponent=GetComponent();
792   if (pComponent) {
793     HLTMessage("     component: %s (%p)", pComponent->GetComponentID(), pComponent);
794   } else {
795     HLTMessage("     no component set!");
796   }
797   if (fpConfiguration) {
798     AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
799     while (pSrc) {
800       const char* pQualifier="unresolved";
801       if (FindDependency(pSrc->GetName()))
802         pQualifier="resolved";
803       HLTMessage("     source: %s (%s)", pSrc->GetName(), pQualifier);
804       pSrc=fpConfiguration->GetNextSource();
805     }
806     TObjLink* lnk = fListTargets.FirstLink();
807     while (lnk) {
808       TObject *obj = lnk->GetObject();
809       HLTMessage("     target: %s", obj->GetName());
810       lnk = lnk->Next();
811     }
812   } else {
813     HLTMessage("     task not initialized");
814   }
815 }
816
817 int AliHLTTask::CustomInit(AliHLTComponentHandler* /*pCH*/)
818 {
819   // default implementation nothing to do
820   return 0;
821 }
822
823 int AliHLTTask::CustomCleanup()
824 {
825   // default implementation nothing to do
826   return 0;
827 }
828
829 int AliHLTTask::LoggingVarargs(AliHLTComponentLogSeverity severity, 
830                                     const char* originClass, const char* originFunc,
831                                     const char* file, int line, ... ) const
832 {
833   // see header file for function documentation
834   int iResult=0;
835
836   va_list args;
837   va_start(args, line);
838
839   AliHLTLogging::SetLogString("%s (%p): ", GetName(), this);
840   iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args, true /*append*/));
841   va_end(args);
842
843   return iResult;
844 }