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. *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
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 **************************************************************************/
19 /** @file AliHLTTask.cxx
20 @author Matthias Richter
22 @brief Implementation of HLT tasks.
25 // see header file for class documentation
27 // refer to README to build package
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
39 #include "AliHLTTask.h"
40 #include "AliHLTConfiguration.h"
41 #include "AliHLTComponent.h"
42 #include "AliHLTComponentHandler.h"
45 /** ROOT macro for the implementation of ROOT specific class methods */
48 AliHLTTask::AliHLTTask()
50 fpConfiguration(NULL),
57 // see header file for class documentation
59 // refer to README to build package
61 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
64 AliHLTTask::AliHLTTask(AliHLTConfiguration* pConf)
66 fpConfiguration(pConf),
73 // see header file for function documentation
76 AliHLTTask::~AliHLTTask()
78 // see header file for function documentation
79 TObjLink* lnk=fListDependencies.FirstLink();
82 AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
83 pTask->UnsetTarget(this);
86 lnk=fListTargets.FirstLink();
89 AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
90 pTask->UnsetDependency(this);
94 if (fpComponent) delete fpComponent;
98 int AliHLTTask::Init(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH)
100 // see header file for function documentation
102 if (fpConfiguration!=NULL && pConf!=NULL && fpConfiguration!=pConf) {
103 HLTWarning("overriding existing reference to configuration object %p (%s) by %p",
104 fpConfiguration, GetName(), pConf);
106 if (pConf!=NULL) fpConfiguration=pConf;
107 if (fpConfiguration) {
110 const char** argv=NULL;
111 if ((iResult=fpConfiguration->GetArguments(&argv))>=0) {
112 argc=iResult; // just to make it clear
113 // TODO: we have to think about the optional environment parameter,
114 // currently just set to NULL.
115 iResult=pCH->CreateComponent(fpConfiguration->GetComponentID(), NULL, argc, argv, fpComponent);
116 if (fpComponent || iResult<=0) {
117 //HLTDebug("component %s (%p) created", fpComponent->GetComponentID(), fpComponent);
119 //HLTError("can not find component \"%s\" (%d)", fpConfiguration->GetComponentID(), iResult);
122 HLTError("can not get argument list for configuration %s (%s)", fpConfiguration->GetName(), fpConfiguration->GetComponentID());
126 HLTError("component handler instance needed for task initialization");
130 HLTError("configuration object instance needed for task initialization");
136 int AliHLTTask::Deinit()
138 // see header file for function documentation
140 AliHLTComponent* pComponent=GetComponent();
143 //HLTDebug("delete component %s (%p)", pComponent->GetComponentID(), pComponent);
144 pComponent->Deinit();
147 HLTWarning("task %s (%p) doesn't seem to be in initialized", GetName(), this);
152 const char *AliHLTTask::GetName() const
154 // see header file for function documentation
156 return fpConfiguration->GetName();
157 return TObject::GetName();
160 AliHLTConfiguration* AliHLTTask::GetConf() const
162 // see header file for function documentation
163 return fpConfiguration;
166 AliHLTComponent* AliHLTTask::GetComponent() const
168 // see header file for function documentation
172 AliHLTTask* AliHLTTask::FindDependency(const char* id)
174 // see header file for function documentation
175 AliHLTTask* pTask=NULL;
177 pTask=(AliHLTTask*)fListDependencies.FindObject(id);
182 int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
184 // see header file for function documentation
187 AliHLTTask* pDep=NULL;
188 if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
189 if (pTgtList) pTgtList->Add(pDep);
192 TObjLink* lnk=fListDependencies.FirstLink();
193 while (lnk && iResult==0) {
194 pDep=(AliHLTTask*)lnk->GetObject();
196 if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
197 if (pTgtList) pTgtList->AddFirst(pDep);
212 void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
214 // see header file for function documentation
215 HLTLogKeyword("task dependencies");
218 if (bFromConfiguration) {
220 iResult=fpConfiguration->FollowDependency(id, &tgtList);
224 iResult=FollowDependency(id, &tgtList);
226 HLTMessage(" task \"%s\": dependency level %d ", GetName(), iResult);
227 TObjLink* lnk=tgtList.FirstLink();
229 char* pSpace = new char[iResult+1];
231 memset(pSpace, 32, iResult);
234 TObject* obj=lnk->GetObject();
235 HLTMessage(" %s^-- %s ", &pSpace[i--], obj->GetName());
245 int AliHLTTask::SetDependency(AliHLTTask* pDep)
247 // see header file for function documentation
250 if (FindDependency(pDep->GetName())==NULL) {
251 fListDependencies.Add(pDep);
261 int AliHLTTask::UnsetDependency(AliHLTTask* pDep)
263 // see header file for function documentation
264 fListDependencies.Remove(pDep);
265 if (fpConfiguration) {
266 fpConfiguration->InvalidateSources();
271 int AliHLTTask::CheckDependencies()
273 // see header file for function documentation
275 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
277 if (FindDependency(pSrc->GetName())==NULL) {
278 //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
281 pSrc=fpConfiguration->GetNextSource();
287 int AliHLTTask::Depends(AliHLTTask* pTask)
289 // see header file for function documentation
292 if (fpConfiguration) {
293 iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
295 //HLTDebug("task \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
297 //HLTDebug("task \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
308 AliHLTTask* AliHLTTask::FindTarget(const char* id)
310 // see header file for function documentation
311 AliHLTTask* pTask=NULL;
313 pTask=(AliHLTTask*)fListTargets.FindObject(id);
318 int AliHLTTask::SetTarget(AliHLTTask* pTgt)
320 // see header file for function documentation
323 if (FindTarget(pTgt->GetName())==NULL) {
324 fListTargets.Add(pTgt);
334 int AliHLTTask::UnsetTarget(AliHLTTask* pTarget)
336 // see header file for function documentation
337 fListTargets.Remove(pTarget);
341 int AliHLTTask::StartRun()
343 // see header file for function documentation
345 int iNofInputDataBlocks=0;
346 AliHLTComponent* pComponent=GetComponent();
348 // determine the number of input data blocks provided from the source tasks
349 TObjLink* lnk=fListDependencies.FirstLink();
350 while (lnk && iResult>=0) {
351 AliHLTTask* pSrcTask=(AliHLTTask*)lnk->GetObject();
353 if ((iResult=pSrcTask->GetNofMatchingDataTypes(this))>0) {
354 iNofInputDataBlocks+=iResult;
355 } else if (iResult==0) {
356 HLTWarning("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
358 HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
365 if (fBlockDataArray.size()>0) {
366 HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
367 fBlockDataArray.resize(0);
371 // the initialization of the component is done by the ComponentHandler after creation
373 //iResult=Init( AliHLTComponentEnvironment* environ, void* environ_param, int argc, const char** argv );
375 // allocate internal task variables for bookkeeping aso.
376 // we allocate the BlockData array with at least one member
377 if (iNofInputDataBlocks==0) iNofInputDataBlocks=1;
378 AliHLTComponentBlockData init;
379 memset(&init, 0, sizeof(AliHLTComponentBlockData));
380 fBlockDataArray.resize(iNofInputDataBlocks, init);
382 // allocate the data buffer, which controls the output buffer and subscriptions
384 fpDataBuffer=new AliHLTDataBuffer;
385 if (fpDataBuffer!=NULL) {
386 fpDataBuffer->SetLocalLoggingLevel(GetLocalLoggingLevel());
387 HLTDebug("created data buffer %p for task %s (%p)", fpDataBuffer, GetName(), this);
388 TObjLink* lnk=fListTargets.FirstLink();
389 while (lnk && iResult>=0) {
390 AliHLTTask* pTgtTask=(AliHLTTask*)lnk->GetObject();
392 if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
401 HLTFatal("can not create data buffer object, memory allocation failed");
407 HLTError("task %s (%p) does not have a component", GetName(), this);
413 int AliHLTTask::EndRun()
415 // see header file for function documentation
417 if (fBlockDataArray.size()>0) {
418 fBlockDataArray.resize(0);
420 HLTWarning("task %s (%p) doesn't seem to be in running mode", GetName(), this);
423 AliHLTDataBuffer* pBuffer=fpDataBuffer;
430 int AliHLTTask::ProcessTask(Int_t eventNo)
432 // see header file for function documentation
434 AliHLTComponent* pComponent=GetComponent();
435 if (pComponent && fpDataBuffer) {
436 HLTDebug("Processing task %s (%p) fpDataBuffer %p", GetName(), this, fpDataBuffer);
437 fpDataBuffer->Reset();
438 int iSourceDataBlock=0;
439 int iInputDataVolume=0;
441 AliHLTTask* pSrcTask=NULL;
442 AliHLTTaskPList subscribedTaskList;
443 TObjLink* lnk=fListDependencies.FirstLink();
445 // subscribe to all source tasks
446 while (lnk && iResult>=0) {
447 pSrcTask=(AliHLTTask*)lnk->GetObject();
449 int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
450 if (iMatchingDB>=0 && static_cast<unsigned int>(iMatchingDB)>fBlockDataArray.size()-iSourceDataBlock) {
451 AliHLTComponentBlockData init;
452 memset(&init, 0, sizeof(AliHLTComponentBlockData));
453 fBlockDataArray.resize(iSourceDataBlock+iMatchingDB, init);
456 HLTError("task %s (%p): error getting no of matching data blocks from task %s (%p), error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iMatchingDB);
459 } else if (iMatchingDB==0) {
460 HLTDebug("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
463 if ((iResult=pSrcTask->Subscribe(this, &fBlockDataArray[iSourceDataBlock],fBlockDataArray.size()-iSourceDataBlock))>=0) {
464 for (int i=0; i<iResult; i++) {
465 iInputDataVolume+=fBlockDataArray[i+iSourceDataBlock].fSize;
466 // put the source task as many times into the list as it provides data blocks
467 // makes the bookkeeping for the data release easier
468 subscribedTaskList.push_back(pSrcTask);
470 HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask);
471 iSourceDataBlock+=iResult;
474 HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
478 HLTFatal("fatal internal error in ROOT list handling");
485 int iNofTrial=0; // repeat processing if component returns -ENOSPC
486 AliHLTUInt32_t size=0;
489 long unsigned int iConstBase=0;
490 double fInputMultiplier=0;
491 if (pComponent->GetComponentType()!=AliHLTComponent::kSink)
492 pComponent->GetOutputDataSize(iConstBase, fInputMultiplier);
493 if (fInputMultiplier<0) {
494 HLTWarning("ignoring negative input multiplier");
497 long unsigned int iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
498 //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
500 // dont process again if the buffer size is the same
501 if (size==iOutputDataSize) break;
502 HLTInfo("processing task %s again with buffer size %d", GetName(), iOutputDataSize);
504 AliHLTUInt8_t* pTgtBuffer=NULL;
505 if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
506 //HLTDebug("provided raw buffer %p", pTgtBuffer);
507 AliHLTComponentEventData evtData;
508 AliHLTComponent::FillEventData(evtData);
509 evtData.fEventID=(AliHLTEventID_t)eventNo;
510 evtData.fBlockCnt=iSourceDataBlock;
511 AliHLTComponentTriggerData trigData;
512 size=iOutputDataSize;
513 AliHLTUInt32_t outputBlockCnt=0;
514 AliHLTComponentBlockData* outputBlocks=NULL;
515 AliHLTComponentEventDoneData* edd;
516 if (pTgtBuffer!=NULL || iOutputDataSize==0) {
517 iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
518 HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt);
519 if (iResult>=0 && outputBlocks) {
520 AliHLTComponentBlockDataList segments;
521 for (AliHLTUInt32_t oblock=0; oblock<outputBlockCnt; oblock++) {
522 AliHLTUInt32_t iblock=0;
523 for (; iblock<evtData.fBlockCnt; iblock++) {
524 if (fBlockDataArray[iblock].fPtr==outputBlocks[oblock].fPtr) {
525 assert(subscribedTaskList[iblock]!=NULL);
526 if (subscribedTaskList[iblock]==NULL) continue;
527 HLTDebug("forward segment %d (source task %s %p) to data buffer %p", iblock, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
528 fpDataBuffer->Forward(subscribedTaskList[iblock], &fBlockDataArray[iblock]);
529 subscribedTaskList[iblock]=NULL; // not to be released in the loop further down
533 if (iblock==evtData.fBlockCnt) segments.push_back(outputBlocks[oblock]);
535 if (pTgtBuffer && segments.size()>0) {
536 iResult=fpDataBuffer->SetSegments(pTgtBuffer, &segments[0], segments.size());
538 delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0;
540 fpDataBuffer->Reset();
543 HLTError("task %s: no target buffer available", GetName());
546 } while (iResult==-ENOSPC && iNofTrial++<1);
549 // now release all buffers which we have subscribed to
551 AliHLTTaskPList::iterator element;
552 while ((element=subscribedTaskList.begin())!=subscribedTaskList.end()) {
556 if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
557 HLTDebug("Task %s (%p) successfully released segment of task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
559 HLTError("Task %s (%p): realease of task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iTempRes);
562 subscribedTaskList.erase(element);
565 if (subscribedTaskList.size()>0) {
566 HLTError("task %s (%p): could not release all data buffers", GetName(), this);
569 HLTError("task %s (%p): internal failure (not initialized component %p, data buffer %p)", GetName(), this, fpComponent, fpDataBuffer);
575 int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
577 // see header file for function documentation
581 iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
583 HLTFatal("internal data buffer missing");
592 int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
594 // see header file for function documentation
597 AliHLTComponent* pComponent=GetComponent();
600 HLTError("component not initialized");
604 iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
606 HLTFatal("task initialization failed");
615 int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockData* pBlockDesc, int iArraySize)
617 // see header file for function documentation
621 iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), pBlockDesc, iArraySize);
623 HLTFatal("internal data buffer missing");
632 int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
634 // see header file for function documentation
636 if (pConsumerTask && pBlockDesc) {
638 iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent(), this);
640 HLTFatal("internal data buffer missing");
649 void AliHLTTask::PrintStatus()
651 // see header file for function documentation
652 HLTLogKeyword("task properties");
653 AliHLTComponent* pComponent=GetComponent();
655 HLTMessage(" component: %s (%p)", pComponent->GetComponentID(), pComponent);
657 HLTMessage(" no component set!");
659 if (fpConfiguration) {
660 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
662 const char* pQualifier="unresolved";
663 if (FindDependency(pSrc->GetName()))
664 pQualifier="resolved";
665 HLTMessage(" source: %s (%s)", pSrc->GetName(), pQualifier);
666 pSrc=fpConfiguration->GetNextSource();
668 TObjLink* lnk = fListTargets.FirstLink();
670 TObject *obj = lnk->GetObject();
671 HLTMessage(" target: %s", obj->GetName());
675 HLTMessage(" task \"%s\" not initialized", GetName());