]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTTask.cxx
Put back the doxygen comments in MUONTRGda.cxx
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTTask.cxx
1 // $Id$
2 //**************************************************************************
3 //* This file is property of and copyright by the                          * 
4 //* ALICE Experiment at CERN, All rights reserved.                         *
5 //*                                                                        *
6 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
7 //*                  for The ALICE HLT Project.                            *
8 //*                                                                        *
9 //* Permission to use, copy, modify and distribute this software and its   *
10 //* documentation strictly for non-commercial purposes is hereby granted   *
11 //* without fee, provided that the above copyright notice appears in all   *
12 //* copies and that both the copyright notice and this permission notice   *
13 //* appear in the supporting documentation. The authors make no claims     *
14 //* about the suitability of this software for any purpose. It is          *
15 //* provided "as is" without express or implied warranty.                  *
16 //**************************************************************************
17
18 /// @file   AliHLTTask.cxx
19 /// @author Matthias Richter
20 /// @date   
21 /// @brief  Implementation of HLT tasks.
22 ///
23
24 #include <cerrno>
25 #include <cassert>
26 #include <iostream>
27 #include <string>
28 #include <ctime>
29 #include "AliHLTTask.h"
30 #include "AliHLTConfiguration.h"
31 #include "AliHLTConfigurationHandler.h"
32 #include "AliHLTComponent.h"
33 #include "AliHLTComponentHandler.h"
34 #include "TList.h"
35 #include "AliHLTErrorGuard.h"
36
37 using std::cout;
38
39 /** ROOT macro for the implementation of ROOT specific class methods */
40 ClassImp(AliHLTTask)
41
42 AliHLTTask::AliHLTTask()
43   :
44   fpConfiguration(NULL),
45   fpComponent(NULL),
46   fpDataBuffer(NULL),
47   fListTargets(),
48   fListDependencies(),
49   fBlockDataArray()
50 {
51   // see header file for class documentation
52   // or
53   // refer to README to build package
54   // or
55   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
56 }
57
58 AliHLTTask::AliHLTTask(AliHLTConfiguration* pConf)
59   :
60   fpConfiguration(pConf),
61   fpComponent(NULL),
62   fpDataBuffer(NULL),
63   fListTargets(),
64   fListDependencies(),
65   fBlockDataArray()
66 {
67   // see header file for function documentation
68 }
69
70 AliHLTTask::~AliHLTTask()
71 {
72   // see header file for function documentation
73   TObjLink* lnk=fListDependencies.FirstLink();
74
75   while (lnk!=NULL) {
76     AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
77     pTask->UnsetTarget(this);
78     lnk=lnk->Next();
79   }
80   lnk=fListTargets.FirstLink();
81
82   while (lnk!=NULL) {
83     AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
84     pTask->UnsetDependency(this);
85     lnk=lnk->Next();
86   }
87
88   if (fpComponent) delete fpComponent;
89   fpComponent=NULL;
90 }
91
92 int AliHLTTask::Init(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH)
93 {
94   // see header file for function documentation
95   int iResult=0;
96   if (fpConfiguration!=NULL && pConf!=NULL && fpConfiguration!=pConf) {
97     HLTWarning("overriding existing reference to configuration object %p by %p",
98                fpConfiguration, pConf);
99   }
100   if (pConf!=NULL) fpConfiguration=pConf;
101   iResult=CreateComponent(fpConfiguration, pCH, fpComponent);
102   if (iResult>=0) {
103     iResult=CustomInit(pCH);
104   }
105   return iResult;
106 }
107
108 int AliHLTTask::CreateComponent(AliHLTConfiguration* pConfiguration, AliHLTComponentHandler* pCH, AliHLTComponent*& pComponent) const
109 {
110   // see header file for class documentation
111   int iResult=0;
112   if (!pConfiguration) return -EINVAL;
113
114   const AliHLTConfiguration* pConf=AliHLTConfigurationHandler::FindSubstitution(*pConfiguration);
115   if (!pConf) pConf=pConfiguration;
116   if (pConf) {
117     if (pCH) {
118       int argc=0;
119       const char** argv=NULL;
120       if ((iResult=pConf->GetArguments(&argv))>=0) {
121         argc=iResult; // just to make it clear
122         // TODO: we have to think about the optional environment parameter,
123         // currently just set to NULL.
124         iResult=pCH->CreateComponent(pConf->GetComponentID(), pComponent);
125         if (pComponent && iResult>=0) {
126           TString description;
127           description.Form("chainid=%s", GetName());
128           pComponent->SetComponentDescription(description.Data());
129           const AliHLTAnalysisEnvironment* pEnv=pCH->GetEnvironment();
130           if ((iResult=pComponent->Init(pEnv, NULL, argc, argv))>=0) {
131             //HLTDebug("component %s (%p) created", pComponent->GetComponentID(), pComponent); 
132           } else {
133             HLTError("Initialization of component \"%s\" failed with error %d", pComponent->GetComponentID(), iResult);
134           }
135         } else {
136           //HLTError("can not find component \"%s\" (%d)", pConf->GetComponentID(), iResult);
137         }
138       } else {
139         HLTError("can not get argument list for configuration %s (%s)", pConf->GetName(), pConf->GetComponentID());
140         iResult=-EINVAL;
141       }
142     } else {
143       HLTError("component handler instance needed for task initialization");
144       iResult=-EINVAL;
145     }
146   } else {
147     HLTError("configuration object instance needed for task initialization");
148     iResult=-EINVAL;
149   }
150   return iResult;
151 }
152
153 int AliHLTTask::Deinit()
154 {
155   // see header file for function documentation
156   int iResult=0;
157   CustomCleanup();
158   AliHLTComponent* pComponent=GetComponent();
159   fpComponent=NULL;
160   if (pComponent) {
161     //HLTDebug("delete component %s (%p)", pComponent->GetComponentID(), pComponent); 
162     pComponent->Deinit();
163     delete pComponent;
164   } else {
165     HLTWarning("task doesn't seem to be in initialized");
166   }
167   return iResult;
168 }
169
170 const char *AliHLTTask::GetName() const
171 {
172   // see header file for function documentation
173   if (fpConfiguration)
174     return fpConfiguration->GetName();
175   return TObject::GetName();
176 }
177
178 AliHLTConfiguration* AliHLTTask::GetConf() const
179 {
180   // see header file for function documentation
181   return fpConfiguration;
182 }
183
184 AliHLTComponent* AliHLTTask::GetComponent() const
185 {
186   // see header file for function documentation
187   return fpComponent;
188 }
189
190 AliHLTTask* AliHLTTask::FindDependency(const char* id)
191 {
192   // see header file for function documentation
193   AliHLTTask* pTask=NULL;
194   if (id) {
195     pTask=(AliHLTTask*)fListDependencies.FindObject(id);
196   }
197   return pTask;
198 }
199
200 int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
201 {
202   // see header file for function documentation
203   int iResult=0;
204   if (id) {
205     AliHLTTask* pDep=NULL;
206     if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
207       if (pTgtList) pTgtList->Add(pDep);
208       iResult++;
209     } else {
210       TObjLink* lnk=fListDependencies.FirstLink();
211       while (lnk && iResult==0) {
212         pDep=(AliHLTTask*)lnk->GetObject();
213         if (pDep) {
214           if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
215             if (pTgtList) pTgtList->AddFirst(pDep);
216             iResult++;
217           }
218         } else {
219           iResult=-EFAULT;
220         }
221         lnk=lnk->Next();
222       }
223     }
224   } else {
225     iResult=-EINVAL;
226   }
227   return iResult;
228 }
229
230 void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
231 {
232   // see header file for function documentation
233   HLTLogKeyword("task dependencies");
234   int iResult=0;
235   TList tgtList;
236   if (bFromConfiguration) {
237     if (fpConfiguration)
238       iResult=fpConfiguration->FollowDependency(id, &tgtList);
239     else
240       iResult=-EFAULT;
241   } else
242     iResult=FollowDependency(id, &tgtList);
243   if (iResult>0) {
244     HLTMessage("     dependency level %d ", iResult);
245     TObjLink* lnk=tgtList.FirstLink();
246     int i=iResult;
247     char* pSpace = new char[iResult+1];
248     if (pSpace) {
249       memset(pSpace, 32, iResult);
250       pSpace[i]=0;
251       while (lnk) {
252         TObject* obj=lnk->GetObject();
253         HLTMessage("     %s^-- %s ", &pSpace[i--], obj->GetName());
254         lnk=lnk->Next();
255       }
256       delete [] pSpace;
257     } else {
258       iResult=-ENOMEM;
259     }
260   }
261 }
262
263 int AliHLTTask::SetDependency(AliHLTTask* pDep)
264 {
265   // see header file for function documentation
266   int iResult=0;
267   if (pDep) {
268     if (FindDependency(pDep->GetName())==NULL) {
269       fListDependencies.Add(pDep);
270     } else {
271       iResult=-EEXIST;
272     }
273   } else {
274     iResult=-EINVAL;
275   }
276   return iResult;
277 }
278
279 int AliHLTTask::UnsetDependency(AliHLTTask* pDep)
280 {
281   // see header file for function documentation
282   fListDependencies.Remove(pDep);
283   if (fpConfiguration) {
284     fpConfiguration->InvalidateSources();
285   }
286   return 0;
287 }
288
289 int AliHLTTask::CheckDependencies()
290 {
291   // see header file for function documentation
292   int iResult=0;
293   AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
294   while (pSrc) {
295     if (FindDependency(pSrc->GetName())==NULL) {
296       //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
297       iResult++;
298     }
299     pSrc=fpConfiguration->GetNextSource();
300   }
301   return iResult;
302 }
303
304
305 int AliHLTTask::Depends(AliHLTTask* pTask)
306 {
307   // see header file for function documentation
308   int iResult=0;
309   if (pTask) {
310     if (fpConfiguration) {
311       iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
312       if (iResult>0) {
313         //HLTDebug("task  \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
314       } else {
315         //HLTDebug("task  \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
316       }
317     } else {
318       iResult=-EFAULT;
319     }
320   } else {
321     iResult=-EINVAL;
322   }
323   return iResult;
324 }
325
326 AliHLTTask* AliHLTTask::FindTarget(const char* id)
327 {
328   // see header file for function documentation
329   AliHLTTask* pTask=NULL;
330   if (id) {
331     pTask=(AliHLTTask*)fListTargets.FindObject(id);
332   }
333   return pTask;
334 }
335
336 int AliHLTTask::SetTarget(AliHLTTask* pTgt)
337 {
338   // see header file for function documentation
339   int iResult=0;
340   if (pTgt) {
341     if (FindTarget(pTgt->GetName())==NULL) {
342       fListTargets.Add(pTgt);
343     } else {
344       iResult=-EEXIST;
345     }
346   } else {
347     iResult=-EINVAL;
348   }
349   return iResult;
350 }
351
352 int AliHLTTask::UnsetTarget(AliHLTTask* pTarget)
353 {
354   // see header file for function documentation
355   fListTargets.Remove(pTarget);
356   return 0;
357 }
358
359 int AliHLTTask::StartRun()
360 {
361   // see header file for function documentation
362   int iResult=0;
363   int iNofInputDataBlocks=0;
364   AliHLTComponent* pComponent=GetComponent();
365   if (pComponent) {
366     // determine the number of input data blocks provided from the source tasks
367     { // set scope for lnk as a local variable
368     TObjLink* lnk=fListDependencies.FirstLink();
369     while (lnk && iResult>=0) {
370       AliHLTTask* pSrcTask=(AliHLTTask*)lnk->GetObject();
371       if (pSrcTask) {
372         if ((iResult=pSrcTask->GetNofMatchingDataTypes(this))>0) {
373           iNofInputDataBlocks+=iResult;
374         } else if (iResult==0) {
375           HLTWarning("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
376         } else {
377           HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
378           iResult=-EFAULT;
379         }
380       }
381       lnk=lnk->Next();
382     }
383     }
384     if (iResult>=0) {
385       if (fBlockDataArray.size()>0) {
386         HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
387         fBlockDataArray.clear();
388       }
389
390       // component init
391       // the initialization of the component is done by the ComponentHandler after creation
392       // of the component.
393       //iResult=Init( AliHLTAnalysisEnvironment* environ, void* environ_param, int argc, const char** argv );
394
395       // allocate the data buffer, which controls the output buffer and subscriptions
396       if (iResult>=0) {
397         fpDataBuffer=new AliHLTDataBuffer;
398         if (fpDataBuffer!=NULL) {
399           fpDataBuffer->SetLocalLoggingLevel(GetLocalLoggingLevel());
400           HLTDebug("created data buffer %p for task %s (%p)", fpDataBuffer, GetName(), this);
401           TObjLink* lnk=fListTargets.FirstLink();
402           while (lnk && iResult>=0) {
403             AliHLTTask* pTgtTask=(AliHLTTask*)lnk->GetObject();
404             if (pTgtTask) {
405               if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
406               }
407             } else {
408               iResult=-EFAULT;
409               break;
410             }
411             lnk=lnk->Next();
412           }
413         } else {
414           HLTFatal("can not create data buffer object, memory allocation failed");
415           iResult=-ENOMEM;
416         }
417       }
418     }
419     if (iResult>=0) {
420       // send the SOR event
421       
422     }
423   } else {
424     HLTError("task %s (%p) does not have a component", GetName(), this);
425     iResult=-EFAULT;
426   }
427   return iResult;
428 }
429
430 int AliHLTTask::EndRun()
431 {
432   // see header file for function documentation
433   int iResult=0;
434   if (fBlockDataArray.size()>0) {
435     fBlockDataArray.clear();
436   }
437   if (fpDataBuffer) {
438     AliHLTDataBuffer* pBuffer=fpDataBuffer;
439     fpDataBuffer=NULL;
440     delete pBuffer;
441   }
442   return iResult;
443 }
444
445 int AliHLTTask::ProcessTask(Int_t eventNo, AliHLTUInt32_t eventType, AliHLTTriggerMask_t trgMask,
446                             AliHLTUInt32_t timestamp, AliHLTUInt32_t participatingDetectors)
447 {
448   // see header file for function documentation
449   int iResult=0;
450   AliHLTComponent* pComponent=GetComponent();
451   if (pComponent && fpDataBuffer) {
452     HLTDebug("Processing task %s (%p) fpDataBuffer %p", GetName(), this, fpDataBuffer);
453     fpDataBuffer->Reset();
454     int iSourceDataBlock=0;
455     int iInputDataVolume=0;
456
457     AliHLTTask* pSrcTask=NULL;
458     AliHLTTaskPList subscribedTaskList;
459     TObjLink* lnk=fListDependencies.FirstLink();
460
461     // instances of SOR and EOR events to be kept
462     int iSOR=-1;
463     int iEOR=-1;
464     // TODO 2009-09-30
465     // generalize handling of the special blocks to be forwarded on SOR and EOR
466     // just adding a new specific handling for the ECS parameter block as a quick
467     // solution
468     int iECS=-1;
469
470     // subscribe to all source tasks
471     fBlockDataArray.clear();
472     while (lnk && iResult>=0) {
473       pSrcTask=(AliHLTTask*)lnk->GetObject();
474       if (pSrcTask) {
475         int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
476         if (iMatchingDB<0) {
477           HLTError("task %s (%p): error getting no of matching data blocks from task %s (%p), error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iMatchingDB);
478           iResult=iMatchingDB;
479           break;
480         } else if (iMatchingDB==0) {
481           HLTDebug("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
482         }
483         if ((iResult=pSrcTask->Subscribe(this, fBlockDataArray))>=0) {
484           iSOR=iEOR=iECS=-1;
485           AliHLTComponentBlockDataList::iterator block=fBlockDataArray.begin();
486           for (int i=0; block!=fBlockDataArray.end(); i++) {
487             bool bRemove=0;
488             bRemove|=(*block).fDataType==kAliHLTDataTypeSOR && !(iSOR<0 && (iSOR=i)>=0);
489             bRemove|=(*block).fDataType==kAliHLTDataTypeEOR && !(iEOR<0 && (iEOR=i)>=0);
490             bRemove|=(*block).fDataType==kAliHLTDataTypeECSParam && !(iECS<0 && (iECS=i)>=0);
491             //HLTInfo("block %d, iSOR=%d iEOR=%d remove=%d", i, iSOR, iEOR, bRemove);
492             if (i<iSourceDataBlock) {
493               assert(!bRemove);
494             } else if (bRemove) {
495               HLTDebug("remove duplicated event %s (%d)", AliHLTComponent::DataType2Text((*block).fDataType).c_str(), i);
496               pSrcTask->Release(&(*block), this);
497               block=fBlockDataArray.erase(block);
498               continue;
499             } else {
500             iInputDataVolume+=(*block).fSize;
501             // put the source task as many times into the list as it provides data blocks
502             // makes the bookkeeping for the data release easier
503             subscribedTaskList.push_back(pSrcTask);
504             }
505             block++;
506           }
507           HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask);
508           iSourceDataBlock=fBlockDataArray.size();        
509           iResult=0;
510         } else {
511           HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
512           iResult=-EFAULT;
513         }
514       } else {
515         HLTFatal("fatal internal error in ROOT list handling");
516         iResult=-EFAULT;
517       }
518       lnk=lnk->Next();
519     }    
520
521     // process the event
522     int iNofTrial=0; // repeat processing if component returns -ENOSPC
523     AliHLTUInt32_t iLastOutputDataSize=0;
524     if (iResult>=0) {
525     do {
526       long unsigned int iOutputDataSize=0;
527       AliHLTConfiguration* pConf=GetConf();
528       // check if there was a buffer size specified, query output size
529       // estimator from component otherwize
530       if (pConf && pConf->GetOutputBufferSize()>=0) {
531         iOutputDataSize=pConf->GetOutputBufferSize();
532       } else {
533       long unsigned int iConstBase=0;
534       double fInputMultiplier=0;
535       if (pComponent->GetComponentType()!=AliHLTComponent::kSink) {
536         pComponent->GetOutputDataSize(iConstBase, fInputMultiplier);
537         // add a small margin to the buffer to allow optional component
538         // statistics
539         iConstBase+=100;
540 #if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
541         for (AliHLTComponentBlockDataList::iterator element=fBlockDataArray.begin();
542              element!=fBlockDataArray.end(); element++) {
543           if (element->fDataType==kAliHLTDataTypeComponentStatistics) {
544             iConstBase+=element->fSize;
545           }
546         }
547 #endif
548       }
549       if (fInputMultiplier<0) {
550         HLTWarning("ignoring negative input multiplier");
551         fInputMultiplier=0;
552       }
553       iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
554       //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
555       }
556       if (iNofTrial == 0 && fpDataBuffer->GetMaxBufferSize() < iOutputDataSize) {
557         //If the estimated buffer size exceeds the maximum buffer size of AliHLTRawBuffer, decrease the buffer size.
558         //The estimation is often quite high, and GetMaxBufferSize should usually return a size that is sufficient.
559         HLTImportant("Reducing estimated output buffer size of %d to maximum output buffer size\n", iOutputDataSize);
560         iOutputDataSize = fpDataBuffer->GetMaxBufferSize();
561       }
562       if (iNofTrial>0) {
563         // dont process again if the buffer size is the same
564         if (iLastOutputDataSize>=iOutputDataSize) break;
565         HLTImportant("processing event %d again with buffer size %d", eventNo, iOutputDataSize);
566       }
567       AliHLTUInt8_t* pTgtBuffer=NULL;
568       if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
569       //HLTDebug("provided raw buffer %p", pTgtBuffer);
570       AliHLTComponentEventData evtData;
571       AliHLTComponent::FillEventData(evtData);
572       if (eventNo>=0)
573         evtData.fEventID=(AliHLTEventID_t)eventNo;
574       if (timestamp < kMaxUInt) evtData.fEventCreation_s=timestamp;
575       else
576       evtData.fEventCreation_s=static_cast<AliHLTUInt32_t>(time(NULL));
577       AliHLTComponentTriggerData trigData;
578       AliHLTEventTriggerData evtTrigData;
579       trigData.fStructSize=sizeof(trigData);
580       trigData.fDataSize=sizeof(AliHLTEventTriggerData);
581       memset(&evtTrigData, 0, trigData.fDataSize);
582       // Setup the CDH in the trigger data, based on the event type, CTP trigger
583       // mask and participating detectors.
584       evtTrigData.fCommonHeaderWordCnt=gkAliHLTCommonHeaderCount;
585       AliHLTUInt8_t l1msg = 0x0;
586       switch (eventType)
587       {
588       case gkAliEventTypeData:        l1msg = 0x00; break;
589       case gkAliEventTypeDataReplay:  l1msg = 0x00; break;
590       case gkAliEventTypeStartOfRun:  l1msg = (0xE << 2) | 0x01; break;
591       case gkAliEventTypeEndOfRun:    l1msg = (0xF << 2) | 0x01; break;
592       case gkAliEventTypeCalibration: l1msg = (0x1 << 6) | 0x01; break;
593       case gkAliEventTypeSoftware:    l1msg = 0x01; break;
594       }
595       evtTrigData.fCommonHeader[1] = AliHLTUInt32_t(l1msg) << 14;
596       evtTrigData.fCommonHeader[3] = ((l1msg & 0x1) == 0x1) ? (participatingDetectors & 0xFFFFFF) : 0x0;
597       evtTrigData.fCommonHeader[5] = (trgMask & AliHLTTriggerMask_t(0xffffffff)).to_ulong();
598       evtTrigData.fCommonHeader[6] = ((trgMask>>32) & AliHLTTriggerMask_t(0x3ffff)).to_ulong();
599       evtTrigData.fCommonHeader[7] = ((trgMask>>50) & AliHLTTriggerMask_t(0xffffffff)).to_ulong();
600       evtTrigData.fCommonHeader[8] = ((trgMask>>72) & AliHLTTriggerMask_t(0x3ffff)).to_ulong();
601
602       trigData.fData=&evtTrigData;
603       iLastOutputDataSize=iOutputDataSize;
604       AliHLTUInt32_t size=iOutputDataSize;
605       AliHLTUInt32_t outputBlockCnt=0;
606       AliHLTComponentBlockData* outputBlocks=NULL;
607       AliHLTComponentEventDoneData* edd=NULL;
608       if (pTgtBuffer!=NULL || iOutputDataSize==0) {
609         // add event type data block
610         // the block is removed immediately after processing from the list
611         AliHLTComponentBlockData eventTypeBlock;
612         AliHLTComponent::FillBlockData(eventTypeBlock);
613         // Note: no payload!
614         eventTypeBlock.fDataType=kAliHLTDataTypeEvent;
615         eventTypeBlock.fSpecification=eventType;
616         fBlockDataArray.push_back(eventTypeBlock);
617
618         if (CheckFilter(kHLTLogDebug)) Print("proc");
619
620         AliHLTUInt32_t iblock=0;
621         // check input and output buffers for consistency
622         // to be enabled after fixing bug with DataBuffer and forwarded SOR/EOR
623         //for (iblock=0; iblock<fBlockDataArray.size(); iblock++) {
624         //  if ((AliHLTUInt8_t*)fBlockDataArray[iblock].fPtr >= pTgtBuffer+size) continue;
625         //  if (pTgtBuffer >= (AliHLTUInt8_t*)fBlockDataArray[iblock].fPtr+fBlockDataArray[iblock].fSize) continue;
626         //  HLTFatal("input and output buffer overlap for block descriptor %d (ptr %p size %d): output buffer %p %d",
627         //         iblock, fBlockDataArray[iblock].fPtr, fBlockDataArray[iblock].fSize,
628         //         pTgtBuffer, size);
629         //}     
630
631         // process
632         evtData.fBlockCnt=fBlockDataArray.size();
633         iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
634         HLTDebug("component %s ProcessEvent finnished (%d): size=%d blocks=%d", pComponent->GetComponentID(), iResult, size, outputBlockCnt);
635
636         // EventDoneData is for the moment ignored in AliHLTSystem
637         if (edd) {
638           HLTDebug("got EventDoneData size %d", edd->fDataSize);
639           delete [] reinterpret_cast<char*>(edd);
640           edd=NULL;
641         }
642
643         // remove event data block
644         fBlockDataArray.pop_back();
645
646         // check for forwarded blocks.
647         // loop over all output blocks and check
648         // 1. for duplicate blocks (pointing to same location in output buffer
649         //    or to the same buffer)
650         // 2. for blocks forwarded from the input.
651         if (iResult>=0 && outputBlocks) {
652           if (fListTargets.First()!=NULL) {
653             AliHLTComponentBlockDataList segments;
654             for (AliHLTUInt32_t oblock=0; oblock<outputBlockCnt; oblock++) {
655               // consistency check for data reference
656               if (outputBlocks[oblock].fPtr!=NULL && outputBlocks[oblock].fPtr!=pTgtBuffer &&
657                   outputBlocks[oblock].fOffset!=0) {
658                 HLTWarning("output block %s 0x%08x has inconsistent data reference ptr=%p offset=0x%08x: "
659                            "for new blocks use offset only, forwarded blocks have fPtr set only",
660                            AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
661                            outputBlocks[oblock].fSpecification,
662                            outputBlocks[oblock].fPtr, outputBlocks[oblock].fOffset);
663               }
664
665               // check for duplicates in the output
666               // this check applies for forwarded data blocks where
667               // the ptr is not inside the target buffer
668               AliHLTUInt32_t checkblock=0;
669               for (; checkblock<oblock; checkblock++) {
670                 if (outputBlocks[oblock].fPtr!=NULL && outputBlocks[oblock].fPtr!=pTgtBuffer &&
671                     outputBlocks[checkblock].fPtr==outputBlocks[oblock].fPtr) {
672                   if (outputBlocks[checkblock].fSize!=outputBlocks[oblock].fSize ||
673                       outputBlocks[checkblock].fDataType!=outputBlocks[oblock].fDataType) {
674                     HLTWarning("output blocks %d (%s 0x%08x) and %d (%s 0x%08x) have identical data references ptr=%p "
675                                "but differ in data type and/or size: %d vs. %d, ignoring block %d",
676                                oblock,
677                                AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
678                                outputBlocks[oblock].fSpecification,
679                                checkblock,
680                                AliHLTComponent::DataType2Text(outputBlocks[checkblock].fDataType).c_str(),
681                                outputBlocks[checkblock].fSpecification,
682                                outputBlocks[oblock].fPtr,
683                                outputBlocks[oblock].fSize,
684                                outputBlocks[checkblock].fSize,
685                                checkblock);
686                   }
687                   // ignore from the second copy
688                   break;
689                 }
690               }
691               if (checkblock<oblock) continue;
692
693               // search for the forwarded data blocks
694               // new data blocks are announced to the data buffer, forwarded data blocks
695               // to the publisher task. The publisher task of a forwarded data block is
696               // removed from the list in order to keep the buffer open. It will be releases
697               // when the subscribing task releases it
698               iblock=0;
699               for (; iblock<fBlockDataArray.size(); iblock++) {
700                 if (outputBlocks[oblock].fDataType==kAliHLTDataTypeEvent) {
701                   // the event type data block is an artificial data block
702                   // ignore if it was forwarded
703                   break;
704                 }
705                 if (fBlockDataArray[iblock].fPtr==outputBlocks[oblock].fPtr) {
706                   assert(subscribedTaskList[iblock]!=NULL);
707                   if (subscribedTaskList[iblock]==NULL) {
708                     ALIHLTERRORGUARD(1, "missing parent task for forwarded data block %s 0x%08x, original data block %s 0x%08x, subsequent errors are suppressed",
709                                      AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
710                                      outputBlocks[oblock].fSpecification,
711                                      AliHLTComponent::DataType2Text(outputBlocks[iblock].fDataType).c_str(),
712                                      outputBlocks[iblock].fSpecification);
713                     continue;
714                   }
715                   HLTDebug("forward segment %d (source task %s %p) to data buffer %p", iblock, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
716                   fpDataBuffer->Forward(subscribedTaskList[iblock], &fBlockDataArray[iblock]);
717                   subscribedTaskList[iblock]=NULL; // not to be released in the loop further down
718                   break;
719                 }
720               }
721               if (iblock==fBlockDataArray.size()) segments.push_back(outputBlocks[oblock]);
722             }
723             if (pTgtBuffer && segments.size()>0) {
724               iResult=fpDataBuffer->SetSegments(pTgtBuffer, &segments[0], segments.size());
725             }
726           } else {
727             // no forwarding, actually we dont even need to keep the data, this is a
728             // dead end (fListTargets empty)
729             //iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt);
730           }
731           delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0;
732         } else {
733           fpDataBuffer->Reset();
734         }
735         if (fListTargets.First()!=NULL) {
736           if (iSOR>=0 && subscribedTaskList[iSOR]!=NULL) {
737             HLTDebug("forward SOR event segment %d (source task %s %p) to data buffer %p", iSOR, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
738             fpDataBuffer->Forward(subscribedTaskList[iSOR], &fBlockDataArray[iSOR]);
739             subscribedTaskList[iSOR]=NULL; // not to be released in the loop further down
740           }
741           if (iEOR>=0 && subscribedTaskList[iEOR]!=NULL) {
742             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);
743             fpDataBuffer->Forward(subscribedTaskList[iEOR], &fBlockDataArray[iEOR]);
744             subscribedTaskList[iEOR]=NULL; // not to be released in the loop further down
745           }
746           if (iECS>=0 && subscribedTaskList[iECS]!=NULL) {
747             HLTDebug("forward ECS event (%s) segment %d (source task %s %p) to data buffer %p", AliHLTComponent::DataType2Text(fBlockDataArray[iECS].fDataType).c_str(), iECS, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
748             fpDataBuffer->Forward(subscribedTaskList[iECS], &fBlockDataArray[iECS]);
749             subscribedTaskList[iECS]=NULL; // not to be released in the loop further down
750           }
751         }
752       } else {
753         HLTError("no target buffer available");
754         iResult=-EFAULT;
755       }
756     } while (iResult==-ENOSPC && iNofTrial++<1);
757     }
758
759     fBlockDataArray.clear();
760     if (CheckFilter(kHLTLogDebug)) Print("proc");
761
762     // now release all buffers which we have subscribed to
763     iSourceDataBlock=0;
764     AliHLTTaskPList::iterator element;
765     while ((element=subscribedTaskList.begin())!=subscribedTaskList.end()) {
766       pSrcTask=*element;
767       if (pSrcTask) {
768         int iTempRes=0;
769         if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
770           HLTDebug("successfully released segment of task %s (%p)", pSrcTask->GetName(), pSrcTask);
771         } else {
772           HLTError("realease of task %s (%p) failed with error %d", pSrcTask->GetName(), pSrcTask, iTempRes);
773         }
774       }
775       subscribedTaskList.erase(element);
776       iSourceDataBlock++;
777     }
778     if (subscribedTaskList.size()>0) {
779       HLTError("could not release all data buffers");
780     }
781   } else {
782     HLTError("internal failure (not initialized component %p, data buffer %p)", fpComponent, fpDataBuffer);
783     iResult=-EFAULT;
784   }
785   return iResult;
786 }
787
788 int AliHLTTask::SubscribeSourcesAndSkip()
789 {
790   // function carries out the proper cleanup of the source components
791   // by subscribing and releasing
792   int iResult=0;  
793   AliHLTTask* pSrcTask=NULL;
794   AliHLTTaskPList subscribedTaskList;
795
796   // cleanup the data buffer
797   if (fpDataBuffer) fpDataBuffer->Reset();
798
799   // subscribe to all source tasks
800   fBlockDataArray.clear();
801   for (TObjLink* lnk=fListDependencies.FirstLink(); lnk!=NULL; lnk=lnk->Next()) {
802     if (!lnk->GetObject()) continue;
803     pSrcTask=dynamic_cast<AliHLTTask*>(lnk->GetObject());
804     if (!pSrcTask) continue;
805     unsigned iPosition=fBlockDataArray.size();
806     if ((iResult=pSrcTask->Subscribe(this, fBlockDataArray))>0) {
807       for (unsigned i=iPosition; i<fBlockDataArray.size(); i++) {
808         subscribedTaskList.push_back(pSrcTask);
809       }
810       HLTDebug("subscribed to %d blocks of task %s (%p)", iResult, pSrcTask->GetName(), pSrcTask, iResult);
811     } else if (iResult<0) {
812       HLTError("failed to subscribe to task %s (%p) with error %d", pSrcTask->GetName(), pSrcTask, iResult);
813     }
814   }
815
816   unsigned iSourceDataBlock=0;
817   AliHLTTaskPList::iterator element;
818   while ((element=subscribedTaskList.begin())!=subscribedTaskList.end()) {
819     assert(iSourceDataBlock<fBlockDataArray.size());
820     pSrcTask=*element;
821     if (pSrcTask && iSourceDataBlock<fBlockDataArray.size()) {
822       if ((iResult=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
823         HLTDebug("successfully released segment of task %s (%p)", pSrcTask->GetName(), pSrcTask);
824       } else if (iSourceDataBlock>=fBlockDataArray.size()) {
825         HLTError("mismatch between list of subscribed tasks and block list in task %s (%p), can not release task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
826       } else {
827         HLTError("realease of task %s (%p) failed with error %d", pSrcTask->GetName(), pSrcTask, iResult);
828       }
829     }
830     subscribedTaskList.erase(element);
831     iSourceDataBlock++;
832   }
833   if (iSourceDataBlock<fBlockDataArray.size()) {
834     HLTWarning("not all subscriptions released for task %s (%p)", GetName(), this);
835   }
836
837   return 0;
838 }
839
840 int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
841 {
842   // see header file for function documentation
843   int iResult=0;
844   if (pConsumerTask) {
845     if (fpDataBuffer) {
846       iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
847     } else {
848       HLTFatal("internal data buffer missing");
849       iResult=-EFAULT;
850     }
851   } else {
852     iResult=-EINVAL;
853   }
854   return iResult;
855 }
856
857 int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
858 {
859   // see header file for function documentation
860   int iResult=0;
861   if (pConsumerTask) {
862     AliHLTComponent* pComponent=GetComponent();
863     if (!pComponent) {
864       // init ?
865       HLTError("component not initialized");
866       iResult=-EFAULT;
867     }
868     if (pComponent) {
869       iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
870     } else {
871       HLTFatal("task initialization failed");
872       iResult=-EFAULT;
873     }
874   } else {
875     iResult=-EINVAL;
876   }
877   return iResult;
878 }
879
880 int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockDataList& blockDescList)
881 {
882   // see header file for function documentation
883   int iResult=0;
884   if (pConsumerTask) {
885     if (fpDataBuffer) {
886       iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), blockDescList);
887     } else {
888       HLTFatal("internal data buffer missing");
889       iResult=-EFAULT;
890     }
891   } else {
892     iResult=-EINVAL;
893   }
894   return iResult;
895 }
896
897 int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
898 {
899   // see header file for function documentation
900   int iResult=0;
901   if (pConsumerTask && pBlockDesc) {
902     if (fpDataBuffer) {
903       iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent(), this);
904     } else {
905       HLTFatal("internal data buffer missing");
906       iResult=-EFAULT;
907     }
908   } else {
909     iResult=-EINVAL;
910   }
911   return iResult;
912 }
913
914 void AliHLTTask::PrintStatus()
915 {
916   // see header file for function documentation
917   HLTLogKeyword("task properties");
918   AliHLTComponent* pComponent=GetComponent();
919   if (pComponent) {
920     HLTMessage("     component: %s (%p)", pComponent->GetComponentID(), pComponent);
921   } else {
922     HLTMessage("     no component set!");
923   }
924   if (fpConfiguration) {
925     AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
926     while (pSrc) {
927       const char* pQualifier="unresolved";
928       if (FindDependency(pSrc->GetName()))
929         pQualifier="resolved";
930       HLTMessage("     source: %s (%s)", pSrc->GetName(), pQualifier);
931       pSrc=fpConfiguration->GetNextSource();
932     }
933     TObjLink* lnk = fListTargets.FirstLink();
934     while (lnk) {
935       TObject *obj = lnk->GetObject();
936       HLTMessage("     target: %s", obj->GetName());
937       lnk = lnk->Next();
938     }
939   } else {
940     HLTMessage("     task not initialized");
941   }
942 }
943
944 void AliHLTTask::Print(const char* options) const
945 {
946   // Overloaded from TObject
947   if (strcmp(options, "proc")==0) {
948     // print processing info
949     HLTMessage("**********************************************");
950     HLTMessage("******* AliHLTTask Processing info ***********");
951     HLTMessage(" component: %p %s", fpComponent, (fpComponent?fpComponent->GetComponentID():""));
952     HLTMessage(" data buffer: %p", fpDataBuffer);
953     if (fpDataBuffer) fpDataBuffer->Print("");
954     HLTMessage(" input block descriptors: %d", fBlockDataArray.size());
955     for (unsigned i=0; i<fBlockDataArray.size(); i++) {
956       HLTMessage("  %d: %s 0x%08x %p %d", i,
957                  AliHLTComponent::DataType2Text(fBlockDataArray[i].fDataType).c_str(),
958                  fBlockDataArray[i].fSpecification,
959                  fBlockDataArray[i].fPtr,
960                  fBlockDataArray[i].fSize
961                  );
962     }
963     HLTMessage("**** end of AliHLTTask Processing info *******");
964     HLTMessage("**********************************************");
965     return;
966   }
967
968   cout << "AliHLTTask " << GetName() << " " << this
969        << " component " << fpComponent << " "
970        << (fpComponent?fpComponent->GetComponentID():"")
971        << endl;
972 }
973
974
975 int AliHLTTask::CustomInit(AliHLTComponentHandler* /*pCH*/)
976 {
977   // default implementation nothing to do
978   return 0;
979 }
980
981 int AliHLTTask::CustomCleanup()
982 {
983   // default implementation nothing to do
984   return 0;
985 }
986
987 int AliHLTTask::LoggingVarargs(AliHLTComponentLogSeverity severity, 
988                                     const char* originClass, const char* originFunc,
989                                     const char* file, int line, ... ) const
990 {
991   // see header file for function documentation
992   int iResult=0;
993
994   va_list args;
995   va_start(args, line);
996
997   AliHLTLogging::SetLogString(this, " (%p)", "%s_pfmt_: ", GetName());
998   iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args, true /*append*/));
999   va_end(args);
1000
1001   return iResult;
1002 }