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
38 #include "AliHLTTask.h"
39 #include "AliHLTConfiguration.h"
40 #include "AliHLTComponent.h"
41 #include "AliHLTComponentHandler.h"
44 /** ROOT macro for the implementation of ROOT specific class methods */
47 AliHLTTask::AliHLTTask()
49 fpConfiguration(NULL),
56 // see header file for class documentation
58 // refer to README to build package
60 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
63 AliHLTTask::AliHLTTask(AliHLTConfiguration* pConf)
65 fpConfiguration(pConf),
72 // see header file for function documentation
75 AliHLTTask::~AliHLTTask()
77 // see header file for function documentation
78 TObjLink* lnk=fListDependencies.FirstLink();
81 AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
82 pTask->UnsetTarget(this);
85 lnk=fListTargets.FirstLink();
88 AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
89 pTask->UnsetDependency(this);
93 if (fpComponent) delete fpComponent;
97 int AliHLTTask::Init(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH)
99 // see header file for function documentation
101 if (fpConfiguration!=NULL && pConf!=NULL && fpConfiguration!=pConf) {
102 HLTWarning("overriding existing reference to configuration object %p (%s) by %p",
103 fpConfiguration, GetName(), pConf);
105 if (pConf!=NULL) fpConfiguration=pConf;
106 if (fpConfiguration) {
109 const char** argv=NULL;
110 if ((iResult=fpConfiguration->GetArguments(&argv))>=0) {
111 argc=iResult; // just to make it clear
112 // TODO: we have to think about the optional environment parameter,
113 // currently just set to NULL.
114 iResult=pCH->CreateComponent(fpConfiguration->GetComponentID(), NULL, argc, argv, fpComponent);
115 if (fpComponent || iResult<=0) {
116 //HLTDebug("component %s (%p) created", fpComponent->GetComponentID(), fpComponent);
118 HLTError("can not find component \"%s\" (%d)", fpConfiguration->GetComponentID(), iResult);
121 HLTError("can not get argument list for configuration %s (%s)", fpConfiguration->GetName(), fpConfiguration->GetComponentID());
125 HLTError("component handler instance needed for task initialization");
129 HLTError("configuration object instance needed for task initialization");
135 int AliHLTTask::Deinit()
137 // see header file for function documentation
139 AliHLTComponent* pComponent=GetComponent();
142 //HLTDebug("delete component %s (%p)", pComponent->GetComponentID(), pComponent);
143 pComponent->Deinit();
146 HLTWarning("task %s (%p) doesn't seem to be in initialized", GetName(), this);
151 const char *AliHLTTask::GetName() const
153 // see header file for function documentation
155 return fpConfiguration->GetName();
156 return TObject::GetName();
159 AliHLTConfiguration* AliHLTTask::GetConf() const
161 // see header file for function documentation
162 return fpConfiguration;
165 AliHLTComponent* AliHLTTask::GetComponent() const
167 // see header file for function documentation
171 AliHLTTask* AliHLTTask::FindDependency(const char* id)
173 // see header file for function documentation
174 AliHLTTask* pTask=NULL;
176 pTask=(AliHLTTask*)fListDependencies.FindObject(id);
181 int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
183 // see header file for function documentation
186 AliHLTTask* pDep=NULL;
187 if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
188 if (pTgtList) pTgtList->Add(pDep);
191 TObjLink* lnk=fListDependencies.FirstLink();
192 while (lnk && iResult==0) {
193 pDep=(AliHLTTask*)lnk->GetObject();
195 if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
196 if (pTgtList) pTgtList->AddFirst(pDep);
211 void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
213 // see header file for function documentation
214 HLTLogKeyword("task dependencies");
217 if (bFromConfiguration) {
219 iResult=fpConfiguration->FollowDependency(id, &tgtList);
223 iResult=FollowDependency(id, &tgtList);
225 HLTMessage(" task \"%s\": dependency level %d ", GetName(), iResult);
226 TObjLink* lnk=tgtList.FirstLink();
228 char* pSpace = new char[iResult+1];
230 memset(pSpace, 32, iResult);
233 TObject* obj=lnk->GetObject();
234 HLTMessage(" %s^-- %s ", &pSpace[i--], obj->GetName());
244 int AliHLTTask::SetDependency(AliHLTTask* pDep)
246 // see header file for function documentation
249 if (FindDependency(pDep->GetName())==NULL) {
250 fListDependencies.Add(pDep);
260 int AliHLTTask::UnsetDependency(AliHLTTask* pDep)
262 // see header file for function documentation
263 fListDependencies.Remove(pDep);
264 if (fpConfiguration) {
265 fpConfiguration->InvalidateSources();
270 int AliHLTTask::CheckDependencies()
272 // see header file for function documentation
274 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
276 if (FindDependency(pSrc->GetName())==NULL) {
277 //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
280 pSrc=fpConfiguration->GetNextSource();
286 int AliHLTTask::Depends(AliHLTTask* pTask)
288 // see header file for function documentation
291 if (fpConfiguration) {
292 iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
294 //HLTDebug("task \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
296 //HLTDebug("task \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
307 AliHLTTask* AliHLTTask::FindTarget(const char* id)
309 // see header file for function documentation
310 AliHLTTask* pTask=NULL;
312 pTask=(AliHLTTask*)fListTargets.FindObject(id);
317 int AliHLTTask::SetTarget(AliHLTTask* pTgt)
319 // see header file for function documentation
322 if (FindTarget(pTgt->GetName())==NULL) {
323 fListTargets.Add(pTgt);
333 int AliHLTTask::UnsetTarget(AliHLTTask* pTarget)
335 // see header file for function documentation
336 fListTargets.Remove(pTarget);
340 int AliHLTTask::StartRun()
342 // see header file for function documentation
344 int iNofInputDataBlocks=0;
345 AliHLTComponent* pComponent=GetComponent();
347 // determine the number of input data blocks provided from the source tasks
348 TObjLink* lnk=fListDependencies.FirstLink();
349 while (lnk && iResult>=0) {
350 AliHLTTask* pSrcTask=(AliHLTTask*)lnk->GetObject();
352 if ((iResult=pSrcTask->GetNofMatchingDataTypes(this))>0) {
353 iNofInputDataBlocks+=iResult;
354 } else if (iResult==0) {
355 HLTWarning("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
357 HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
364 if (fBlockDataArray.size()>0) {
365 HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
366 fBlockDataArray.resize(0);
370 // the initialization of the component is done by the ComponentHandler after creation
372 //iResult=Init( AliHLTComponentEnvironment* environ, void* environ_param, int argc, const char** argv );
374 // allocate internal task variables for bookkeeping aso.
375 // we allocate the BlockData array with at least one member
376 if (iNofInputDataBlocks==0) iNofInputDataBlocks=1;
377 AliHLTComponentBlockData init;
378 memset(&init, 0, sizeof(AliHLTComponentBlockData));
379 fBlockDataArray.resize(iNofInputDataBlocks, init);
381 // allocate the data buffer, which controls the output buffer and subscriptions
383 fpDataBuffer=new AliHLTDataBuffer;
384 if (fpDataBuffer!=NULL) {
385 fpDataBuffer->SetLocalLoggingLevel(GetLocalLoggingLevel());
386 HLTDebug("created data buffer %p for task %s (%p)", fpDataBuffer, GetName(), this);
387 TObjLink* lnk=fListTargets.FirstLink();
388 while (lnk && iResult>=0) {
389 AliHLTTask* pTgtTask=(AliHLTTask*)lnk->GetObject();
391 if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
400 HLTFatal("can not create data buffer object, memory allocation failed");
406 HLTError("task %s (%p) does not have a component", GetName(), this);
412 int AliHLTTask::EndRun()
414 // see header file for function documentation
416 if (fBlockDataArray.size()>0) {
417 fBlockDataArray.resize(0);
419 HLTWarning("task %s (%p) doesn't seem to be in running mode", GetName(), this);
422 AliHLTDataBuffer* pBuffer=fpDataBuffer;
429 int AliHLTTask::ProcessTask(Int_t eventNo)
431 // see header file for function documentation
433 AliHLTComponent* pComponent=GetComponent();
434 if (pComponent && fpDataBuffer) {
435 HLTDebug("Processing task %s (%p) fpDataBuffer %p", GetName(), this, fpDataBuffer);
436 fpDataBuffer->Reset();
437 int iSourceDataBlock=0;
438 int iInputDataVolume=0;
440 AliHLTTask* pSrcTask=NULL;
441 TList subscribedTaskList;
442 TObjLink* lnk=fListDependencies.FirstLink();
444 // subscribe to all source tasks
445 while (lnk && iResult>=0) {
446 pSrcTask=(AliHLTTask*)lnk->GetObject();
448 int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
449 if (iMatchingDB>=0 && static_cast<unsigned int>(iMatchingDB)>fBlockDataArray.size()-iSourceDataBlock) {
450 AliHLTComponentBlockData init;
451 memset(&init, 0, sizeof(AliHLTComponentBlockData));
452 fBlockDataArray.resize(iSourceDataBlock+iMatchingDB, init);
455 HLTError("task %s (%p): error getting no of matching data blocks from task %s (%p), error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iMatchingDB);
458 } else if (iMatchingDB==0) {
459 HLTDebug("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
462 if ((iResult=pSrcTask->Subscribe(this, &fBlockDataArray[iSourceDataBlock],fBlockDataArray.size()-iSourceDataBlock))>=0) {
463 for (int i=0; i<iResult; i++) {
464 iInputDataVolume+=fBlockDataArray[i+iSourceDataBlock].fSize;
465 // put the source task as many times into the list as it provides data blocks
466 // makes the bookkeeping for the data release easier
467 subscribedTaskList.Add(pSrcTask);
469 HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask);
470 iSourceDataBlock+=iResult;
473 HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
477 HLTFatal("fatal internal error in ROOT list handling");
484 int iNofTrial=0; // repeat processing if component returns -ENOSPC
485 AliHLTUInt32_t size=0;
488 long unsigned int iConstBase=0;
489 double fInputMultiplier=0;
490 if (pComponent->GetComponentType()!=AliHLTComponent::kSink)
491 pComponent->GetOutputDataSize(iConstBase, fInputMultiplier);
492 if (fInputMultiplier<0) {
493 HLTWarning("ignoring negative input multiplier");
496 long unsigned int iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
497 //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
499 // dont process again if the buffer size is the same
500 if (size==iOutputDataSize) break;
501 HLTInfo("processing task %s again with buffer size %d", GetName(), iOutputDataSize);
503 AliHLTUInt8_t* pTgtBuffer=NULL;
504 if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
505 //HLTDebug("provided raw buffer %p", pTgtBuffer);
506 AliHLTComponentEventData evtData;
507 AliHLTComponent::FillEventData(evtData);
508 evtData.fEventID=(AliHLTEventID_t)eventNo;
509 evtData.fBlockCnt=iSourceDataBlock;
510 AliHLTComponentTriggerData trigData;
511 size=iOutputDataSize;
512 AliHLTUInt32_t outputBlockCnt=0;
513 AliHLTComponentBlockData* outputBlocks=NULL;
514 AliHLTComponentEventDoneData* edd;
515 if (pTgtBuffer!=NULL || iOutputDataSize==0) {
516 iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
517 HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt);
518 if (iResult>=0 && pTgtBuffer && outputBlocks) {
519 iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt);
520 delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0;
522 fpDataBuffer->Reset();
525 HLTError("task %s: no target buffer available", GetName());
528 } while (iResult==-ENOSPC && iNofTrial++<1);
531 // now release all buffers which we have subscribed to
533 lnk=subscribedTaskList.FirstLink();
535 pSrcTask=(AliHLTTask*)lnk->GetObject();
538 if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
539 HLTDebug("Task %s (%p) successfully released segment of task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
541 HLTError("Task %s (%p): realease of task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iTempRes);
544 HLTFatal("task %s (%p): internal error in ROOT list handling", GetName(), this);
545 if (iResult>=0) iResult=-EFAULT;
547 subscribedTaskList.Remove(lnk);
548 lnk=subscribedTaskList.FirstLink();
551 if (subscribedTaskList.GetSize()>0) {
552 HLTError("task %s (%p): could not release all data buffers", GetName(), this);
555 HLTError("task %s (%p): internal failure (not initialized component %p, data buffer %p)", GetName(), this, fpComponent, fpDataBuffer);
561 int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
563 // see header file for function documentation
567 iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
569 HLTFatal("internal data buffer missing");
578 int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
580 // see header file for function documentation
583 AliHLTComponent* pComponent=GetComponent();
586 HLTError("component not initialized");
590 iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
592 HLTFatal("task initialization failed");
601 int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockData* pBlockDesc, int iArraySize)
603 // see header file for function documentation
607 iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), pBlockDesc, iArraySize);
609 HLTFatal("internal data buffer missing");
618 int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
620 // see header file for function documentation
622 if (pConsumerTask && pBlockDesc) {
624 iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent());
626 HLTFatal("internal data buffer missing");
635 void AliHLTTask::PrintStatus()
637 // see header file for function documentation
638 HLTLogKeyword("task properties");
639 AliHLTComponent* pComponent=GetComponent();
641 HLTMessage(" component: %s (%p)", pComponent->GetComponentID(), pComponent);
643 HLTMessage(" no component set!");
645 if (fpConfiguration) {
646 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
648 const char* pQualifier="unresolved";
649 if (FindDependency(pSrc->GetName()))
650 pQualifier="resolved";
651 HLTMessage(" source: %s (%s)", pSrc->GetName(), pQualifier);
652 pSrc=fpConfiguration->GetNextSource();
654 TObjLink* lnk = fListTargets.FirstLink();
656 TObject *obj = lnk->GetObject();
657 HLTMessage(" target: %s", obj->GetName());
661 HLTMessage(" task \"%s\" not initialized", GetName());