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 iResult=CreateComponent(fpConfiguration, pCH, fpComponent);
109 iResult=CustomInit(pCH);
114 int AliHLTTask::CreateComponent(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH, AliHLTComponent*& pComponent) const
116 // see header file for class documentation
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) {
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);
135 HLTError("Initialization of component \"%s\" failed with error %d", pComponent->GetComponentID(), iResult);
138 //HLTError("can not find component \"%s\" (%d)", pConf->GetComponentID(), iResult);
141 HLTError("can not get argument list for configuration %s (%s)", pConf->GetName(), pConf->GetComponentID());
145 HLTError("component handler instance needed for task initialization");
149 HLTError("configuration object instance needed for task initialization");
155 int AliHLTTask::Deinit()
157 // see header file for function documentation
160 AliHLTComponent* pComponent=GetComponent();
163 //HLTDebug("delete component %s (%p)", pComponent->GetComponentID(), pComponent);
164 pComponent->Deinit();
167 HLTWarning("task %s (%p) doesn't seem to be in initialized", GetName(), this);
172 const char *AliHLTTask::GetName() const
174 // see header file for function documentation
176 return fpConfiguration->GetName();
177 return TObject::GetName();
180 AliHLTConfiguration* AliHLTTask::GetConf() const
182 // see header file for function documentation
183 return fpConfiguration;
186 AliHLTComponent* AliHLTTask::GetComponent() const
188 // see header file for function documentation
192 AliHLTTask* AliHLTTask::FindDependency(const char* id)
194 // see header file for function documentation
195 AliHLTTask* pTask=NULL;
197 pTask=(AliHLTTask*)fListDependencies.FindObject(id);
202 int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
204 // see header file for function documentation
207 AliHLTTask* pDep=NULL;
208 if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
209 if (pTgtList) pTgtList->Add(pDep);
212 TObjLink* lnk=fListDependencies.FirstLink();
213 while (lnk && iResult==0) {
214 pDep=(AliHLTTask*)lnk->GetObject();
216 if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
217 if (pTgtList) pTgtList->AddFirst(pDep);
232 void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
234 // see header file for function documentation
235 HLTLogKeyword("task dependencies");
238 if (bFromConfiguration) {
240 iResult=fpConfiguration->FollowDependency(id, &tgtList);
244 iResult=FollowDependency(id, &tgtList);
246 HLTMessage(" task \"%s\": dependency level %d ", GetName(), iResult);
247 TObjLink* lnk=tgtList.FirstLink();
249 char* pSpace = new char[iResult+1];
251 memset(pSpace, 32, iResult);
254 TObject* obj=lnk->GetObject();
255 HLTMessage(" %s^-- %s ", &pSpace[i--], obj->GetName());
265 int AliHLTTask::SetDependency(AliHLTTask* pDep)
267 // see header file for function documentation
270 if (FindDependency(pDep->GetName())==NULL) {
271 fListDependencies.Add(pDep);
281 int AliHLTTask::UnsetDependency(AliHLTTask* pDep)
283 // see header file for function documentation
284 fListDependencies.Remove(pDep);
285 if (fpConfiguration) {
286 fpConfiguration->InvalidateSources();
291 int AliHLTTask::CheckDependencies()
293 // see header file for function documentation
295 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
297 if (FindDependency(pSrc->GetName())==NULL) {
298 //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
301 pSrc=fpConfiguration->GetNextSource();
307 int AliHLTTask::Depends(AliHLTTask* pTask)
309 // see header file for function documentation
312 if (fpConfiguration) {
313 iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
315 //HLTDebug("task \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
317 //HLTDebug("task \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
328 AliHLTTask* AliHLTTask::FindTarget(const char* id)
330 // see header file for function documentation
331 AliHLTTask* pTask=NULL;
333 pTask=(AliHLTTask*)fListTargets.FindObject(id);
338 int AliHLTTask::SetTarget(AliHLTTask* pTgt)
340 // see header file for function documentation
343 if (FindTarget(pTgt->GetName())==NULL) {
344 fListTargets.Add(pTgt);
354 int AliHLTTask::UnsetTarget(AliHLTTask* pTarget)
356 // see header file for function documentation
357 fListTargets.Remove(pTarget);
361 int AliHLTTask::StartRun()
363 // see header file for function documentation
365 int iNofInputDataBlocks=0;
366 AliHLTComponent* pComponent=GetComponent();
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();
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);
379 HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
387 if (fBlockDataArray.size()>0) {
388 HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
389 fBlockDataArray.clear();
393 // the initialization of the component is done by the ComponentHandler after creation
395 //iResult=Init( AliHLTAnalysisEnvironment* environ, void* environ_param, int argc, const char** argv );
397 // allocate the data buffer, which controls the output buffer and subscriptions
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();
407 if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
416 HLTFatal("can not create data buffer object, memory allocation failed");
422 // send the SOR event
426 HLTError("task %s (%p) does not have a component", GetName(), this);
432 int AliHLTTask::EndRun()
434 // see header file for function documentation
436 if (fBlockDataArray.size()>0) {
437 fBlockDataArray.clear();
440 AliHLTDataBuffer* pBuffer=fpDataBuffer;
447 int AliHLTTask::ProcessTask(Int_t eventNo, AliHLTUInt32_t eventType)
449 // see header file for function documentation
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;
458 AliHLTTask* pSrcTask=NULL;
459 AliHLTTaskPList subscribedTaskList;
460 TObjLink* lnk=fListDependencies.FirstLink();
462 // instances of SOR and EOR events to be kept
466 // subscribe to all source tasks
467 fBlockDataArray.clear();
468 while (lnk && iResult>=0) {
469 pSrcTask=(AliHLTTask*)lnk->GetObject();
471 int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
473 HLTError("task %s (%p): error getting no of matching data blocks from task %s (%p), error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iMatchingDB);
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);
479 if ((iResult=pSrcTask->Subscribe(this, fBlockDataArray))>=0) {
481 AliHLTComponentBlockDataList::iterator block=fBlockDataArray.begin();
482 for (int i=0; block!=fBlockDataArray.end(); i++) {
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) {
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);
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);
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();
506 HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
510 HLTFatal("fatal internal error in ROOT list handling");
517 int iNofTrial=0; // repeat processing if component returns -ENOSPC
518 AliHLTUInt32_t size=0;
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();
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
536 if (fInputMultiplier<0) {
537 HLTWarning("ignoring negative input multiplier");
540 iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
541 //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
544 // dont process again if the buffer size is the same
545 if (size==iOutputDataSize) break;
546 HLTInfo("processing task %s again with buffer size %d", GetName(), iOutputDataSize);
548 AliHLTUInt8_t* pTgtBuffer=NULL;
549 if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
550 //HLTDebug("provided raw buffer %p", pTgtBuffer);
551 AliHLTComponentEventData evtData;
552 AliHLTComponent::FillEventData(evtData);
554 evtData.fEventID=(AliHLTEventID_t)eventNo;
555 AliHLTComponentTriggerData trigData;
556 trigData.fStructSize=sizeof(trigData);
557 trigData.fDataSize=0;
559 size=iOutputDataSize;
560 AliHLTUInt32_t outputBlockCnt=0;
561 AliHLTComponentBlockData* outputBlocks=NULL;
562 AliHLTComponentEventDoneData* edd=NULL;
563 if (pTgtBuffer!=NULL || iOutputDataSize==0) {
564 // add event type data block
565 // the block is removed immediately after processing from the list
566 AliHLTComponentBlockData eventTypeBlock;
567 AliHLTComponent::FillBlockData(eventTypeBlock);
569 eventTypeBlock.fDataType=kAliHLTDataTypeEvent;
570 eventTypeBlock.fSpecification=eventType;
571 fBlockDataArray.push_back(eventTypeBlock);
574 evtData.fBlockCnt=fBlockDataArray.size();
575 iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
576 HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt);
578 // remove event data block
579 fBlockDataArray.pop_back();
581 // check for forwarded blocks.
582 // loop over all output blocks and check
583 // 1. for duplicate blocks (pointing to same location in output buffer
584 // or to the same buffer)
585 // 2. for blocks forwarded from the input.
586 if (iResult>=0 && outputBlocks) {
587 if (fListTargets.First()!=NULL) {
588 AliHLTComponentBlockDataList segments;
589 for (AliHLTUInt32_t oblock=0; oblock<outputBlockCnt; oblock++) {
590 // consistency check for data reference
591 if (outputBlocks[oblock].fPtr!=NULL && outputBlocks[oblock].fOffset!=0) {
592 HLTWarning("output block %s 0x%08x has inconsistent data reference ptr=%p offset=0x%08x: "
593 "for new blocks use offset only, forwarded blocks have fPtr set only",
594 AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
595 outputBlocks[oblock].fSpecification,
596 outputBlocks[oblock].fPtr, outputBlocks[oblock].fOffset);
599 // check for duplicates in the output
600 AliHLTUInt32_t checkblock=0;
601 for (; checkblock<oblock; checkblock++) {
602 if (outputBlocks[oblock].fPtr!=NULL && outputBlocks[checkblock].fPtr==outputBlocks[oblock].fPtr) {
603 if (outputBlocks[checkblock].fSize!=outputBlocks[oblock].fSize ||
604 outputBlocks[checkblock].fDataType!=outputBlocks[oblock].fDataType) {
605 HLTWarning("output blocks %d (%s 0x%08x) and %d (%s 0x%08x) have identical data references ptr=%p "
606 "but differ in data type and/or size: %d vs. %d",
608 AliHLTComponent::DataType2Text(outputBlocks[oblock].fDataType).c_str(),
609 outputBlocks[oblock].fSpecification,
611 AliHLTComponent::DataType2Text(outputBlocks[checkblock].fDataType).c_str(),
612 outputBlocks[checkblock].fSpecification,
613 outputBlocks[oblock].fPtr,
614 outputBlocks[oblock].fSize,
615 outputBlocks[checkblock].fSize);
617 // ignore from the second copy
621 if (checkblock<oblock) continue;
623 // search for the forwarded data blocks
624 // new data blocks are announced to the data buffer, forwarded data blocks
625 // to the publisher task. The publisher task of a forwarded data block is
626 // removed from the list in order to keep the buffer open. It will be releases
627 // when the subscribing task releases it
628 AliHLTUInt32_t iblock=0;
629 for (; iblock<fBlockDataArray.size(); iblock++) {
630 if (fBlockDataArray[iblock].fPtr==outputBlocks[oblock].fPtr) {
631 assert(subscribedTaskList[iblock]!=NULL);
632 if (subscribedTaskList[iblock]==NULL) continue;
633 HLTDebug("forward segment %d (source task %s %p) to data buffer %p", iblock, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
634 fpDataBuffer->Forward(subscribedTaskList[iblock], &fBlockDataArray[iblock]);
635 subscribedTaskList[iblock]=NULL; // not to be released in the loop further down
639 if (iblock==fBlockDataArray.size()) segments.push_back(outputBlocks[oblock]);
641 if (pTgtBuffer && segments.size()>0) {
642 iResult=fpDataBuffer->SetSegments(pTgtBuffer, &segments[0], segments.size());
645 // no forwarding, actually we dont even need to keep the data, this is a
646 // dead end (fListTargets empty)
647 //iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt);
649 delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0;
651 fpDataBuffer->Reset();
653 if (fListTargets.First()!=NULL) {
654 if (iSOR>=0 && subscribedTaskList[iSOR]!=NULL) {
655 HLTDebug("forward SOR event segment %d (source task %s %p) to data buffer %p", iSOR, pSrcTask->GetName(), pSrcTask, fpDataBuffer);
656 fpDataBuffer->Forward(subscribedTaskList[iSOR], &fBlockDataArray[iSOR]);
657 subscribedTaskList[iSOR]=NULL; // not to be released in the loop further down
659 if (iEOR>=0 && subscribedTaskList[iEOR]!=NULL) {
660 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);
661 fpDataBuffer->Forward(subscribedTaskList[iEOR], &fBlockDataArray[iEOR]);
662 subscribedTaskList[iEOR]=NULL; // not to be released in the loop further down
666 HLTError("task %s: no target buffer available", GetName());
669 } while (iResult==-ENOSPC && iNofTrial++<1);
672 // now release all buffers which we have subscribed to
674 AliHLTTaskPList::iterator element;
675 while ((element=subscribedTaskList.begin())!=subscribedTaskList.end()) {
679 if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
680 HLTDebug("Task %s (%p) successfully released segment of task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
682 HLTError("Task %s (%p): realease of task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iTempRes);
685 subscribedTaskList.erase(element);
688 if (subscribedTaskList.size()>0) {
689 HLTError("task %s (%p): could not release all data buffers", GetName(), this);
692 HLTError("task %s (%p): internal failure (not initialized component %p, data buffer %p)", GetName(), this, fpComponent, fpDataBuffer);
698 int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
700 // see header file for function documentation
704 iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
706 HLTFatal("internal data buffer missing");
715 int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
717 // see header file for function documentation
720 AliHLTComponent* pComponent=GetComponent();
723 HLTError("component not initialized");
727 iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
729 HLTFatal("task initialization failed");
738 int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockDataList& blockDescList)
740 // see header file for function documentation
744 iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), blockDescList);
746 HLTFatal("internal data buffer missing");
755 int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
757 // see header file for function documentation
759 if (pConsumerTask && pBlockDesc) {
761 iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent(), this);
763 HLTFatal("internal data buffer missing");
772 void AliHLTTask::PrintStatus()
774 // see header file for function documentation
775 HLTLogKeyword("task properties");
776 AliHLTComponent* pComponent=GetComponent();
778 HLTMessage(" component: %s (%p)", pComponent->GetComponentID(), pComponent);
780 HLTMessage(" no component set!");
782 if (fpConfiguration) {
783 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
785 const char* pQualifier="unresolved";
786 if (FindDependency(pSrc->GetName()))
787 pQualifier="resolved";
788 HLTMessage(" source: %s (%s)", pSrc->GetName(), pQualifier);
789 pSrc=fpConfiguration->GetNextSource();
791 TObjLink* lnk = fListTargets.FirstLink();
793 TObject *obj = lnk->GetObject();
794 HLTMessage(" target: %s", obj->GetName());
798 HLTMessage(" task \"%s\" not initialized", GetName());
802 int AliHLTTask::CustomInit(AliHLTComponentHandler* /*pCH*/)
804 // default implementation nothing to do
808 int AliHLTTask::CustomCleanup()
810 // default implementation nothing to do