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