AliHLTConfiguration.cxx splitted to comply with coding rules
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTTask.cxx
CommitLineData
7a436c89 1// $Id$
2// splitted from AliHLTConfiguration.cxx,v 1.25 2007/10/12 13:24:47
3/**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
6 * *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
9 * *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
18
19/** @file AliHLTTask.cxx
20 @author Matthias Richter
21 @date
22 @brief Implementation of HLT tasks.
23*/
24
25// see header file for class documentation
26// or
27// refer to README to build package
28// or
29// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31#if __GNUC__>= 3
32using namespace std;
33#endif
34
35#include <cerrno>
36#include <iostream>
37#include <string>
38#include "AliHLTTask.h"
39#include "AliHLTConfiguration.h"
40#include "AliHLTComponent.h"
41#include "AliHLTComponentHandler.h"
42#include "TList.h"
43
44/** ROOT macro for the implementation of ROOT specific class methods */
45ClassImp(AliHLTTask)
46
47AliHLTTask::AliHLTTask()
48 :
49 fpConfiguration(NULL),
50 fpComponent(NULL),
51 fpDataBuffer(NULL),
52 fListTargets(),
53 fListDependencies(),
54 fBlockDataArray()
55{
56 // see header file for class documentation
57 // or
58 // refer to README to build package
59 // or
60 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
61}
62
63AliHLTTask::AliHLTTask(AliHLTConfiguration* pConf)
64 :
65 fpConfiguration(pConf),
66 fpComponent(NULL),
67 fpDataBuffer(NULL),
68 fListTargets(),
69 fListDependencies(),
70 fBlockDataArray()
71{
72 // see header file for function documentation
73}
74
75AliHLTTask::~AliHLTTask()
76{
77 // see header file for function documentation
78 TObjLink* lnk=fListDependencies.FirstLink();
79
80 while (lnk!=NULL) {
81 AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
82 pTask->UnsetTarget(this);
83 lnk=lnk->Next();
84 }
85 lnk=fListTargets.FirstLink();
86
87 while (lnk!=NULL) {
88 AliHLTTask* pTask=(AliHLTTask*)lnk->GetObject();
89 pTask->UnsetDependency(this);
90 lnk=lnk->Next();
91 }
92
93 if (fpComponent) delete fpComponent;
94 fpComponent=NULL;
95}
96
97int AliHLTTask::Init(AliHLTConfiguration* pConf, AliHLTComponentHandler* pCH)
98{
99 // see header file for function documentation
100 int iResult=0;
101 if (fpConfiguration!=NULL && pConf!=NULL && fpConfiguration!=pConf) {
102 HLTWarning("overriding existing reference to configuration object %p (%s) by %p",
103 fpConfiguration, GetName(), pConf);
104 }
105 if (pConf!=NULL) fpConfiguration=pConf;
106 if (fpConfiguration) {
107 if (pCH) {
108 int argc=0;
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);
117 } else {
118 HLTError("can not find component \"%s\" (%d)", fpConfiguration->GetComponentID(), iResult);
119 }
120 } else {
121 HLTError("can not get argument list for configuration %s (%s)", fpConfiguration->GetName(), fpConfiguration->GetComponentID());
122 iResult=-EINVAL;
123 }
124 } else {
125 HLTError("component handler instance needed for task initialization");
126 iResult=-EINVAL;
127 }
128 } else {
129 HLTError("configuration object instance needed for task initialization");
130 iResult=-EINVAL;
131 }
132 return iResult;
133}
134
135int AliHLTTask::Deinit()
136{
137 // see header file for function documentation
138 int iResult=0;
139 AliHLTComponent* pComponent=GetComponent();
140 fpComponent=NULL;
141 if (pComponent) {
142 //HLTDebug("delete component %s (%p)", pComponent->GetComponentID(), pComponent);
143 pComponent->Deinit();
144 delete pComponent;
145 } else {
146 HLTWarning("task %s (%p) doesn't seem to be in initialized", GetName(), this);
147 }
148 return iResult;
149}
150
151const char *AliHLTTask::GetName() const
152{
153 // see header file for function documentation
154 if (fpConfiguration)
155 return fpConfiguration->GetName();
156 return TObject::GetName();
157}
158
159AliHLTConfiguration* AliHLTTask::GetConf() const
160{
161 // see header file for function documentation
162 return fpConfiguration;
163}
164
165AliHLTComponent* AliHLTTask::GetComponent() const
166{
167 // see header file for function documentation
168 return fpComponent;
169}
170
171AliHLTTask* AliHLTTask::FindDependency(const char* id)
172{
173 // see header file for function documentation
174 AliHLTTask* pTask=NULL;
175 if (id) {
176 pTask=(AliHLTTask*)fListDependencies.FindObject(id);
177 }
178 return pTask;
179}
180
181int AliHLTTask::FollowDependency(const char* id, TList* pTgtList)
182{
183 // see header file for function documentation
184 int iResult=0;
185 if (id) {
186 AliHLTTask* pDep=NULL;
187 if ((pDep=(AliHLTTask*)fListDependencies.FindObject(id))!=NULL) {
188 if (pTgtList) pTgtList->Add(pDep);
189 iResult++;
190 } else {
191 TObjLink* lnk=fListDependencies.FirstLink();
192 while (lnk && iResult==0) {
193 pDep=(AliHLTTask*)lnk->GetObject();
194 if (pDep) {
195 if ((iResult=pDep->FollowDependency(id, pTgtList))>0) {
196 if (pTgtList) pTgtList->AddFirst(pDep);
197 iResult++;
198 }
199 } else {
200 iResult=-EFAULT;
201 }
202 lnk=lnk->Next();
203 }
204 }
205 } else {
206 iResult=-EINVAL;
207 }
208 return iResult;
209}
210
211void AliHLTTask::PrintDependencyTree(const char* id, int bFromConfiguration)
212{
213 // see header file for function documentation
214 HLTLogKeyword("task dependencies");
215 int iResult=0;
216 TList tgtList;
217 if (bFromConfiguration) {
218 if (fpConfiguration)
219 iResult=fpConfiguration->FollowDependency(id, &tgtList);
220 else
221 iResult=-EFAULT;
222 } else
223 iResult=FollowDependency(id, &tgtList);
224 if (iResult>0) {
225 HLTMessage(" task \"%s\": dependency level %d ", GetName(), iResult);
226 TObjLink* lnk=tgtList.FirstLink();
227 int i=iResult;
228 char* pSpace = new char[iResult+1];
229 if (pSpace) {
230 memset(pSpace, 32, iResult);
231 pSpace[i]=0;
232 while (lnk) {
233 TObject* obj=lnk->GetObject();
234 HLTMessage(" %s^-- %s ", &pSpace[i--], obj->GetName());
235 lnk=lnk->Next();
236 }
237 delete [] pSpace;
238 } else {
239 iResult=-ENOMEM;
240 }
241 }
242}
243
244int AliHLTTask::SetDependency(AliHLTTask* pDep)
245{
246 // see header file for function documentation
247 int iResult=0;
248 if (pDep) {
249 if (FindDependency(pDep->GetName())==NULL) {
250 fListDependencies.Add(pDep);
251 } else {
252 iResult=-EEXIST;
253 }
254 } else {
255 iResult=-EINVAL;
256 }
257 return iResult;
258}
259
260int AliHLTTask::UnsetDependency(AliHLTTask* pDep)
261{
262 // see header file for function documentation
263 fListDependencies.Remove(pDep);
264 if (fpConfiguration) {
265 fpConfiguration->InvalidateSources();
266 }
267 return 0;
268}
269
270int AliHLTTask::CheckDependencies()
271{
272 // see header file for function documentation
273 int iResult=0;
274 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
275 while (pSrc) {
276 if (FindDependency(pSrc->GetName())==NULL) {
277 //HLTDebug("dependency \"%s\" unresolved", pSrc->GetName());
278 iResult++;
279 }
280 pSrc=fpConfiguration->GetNextSource();
281 }
282 return iResult;
283}
284
285
286int AliHLTTask::Depends(AliHLTTask* pTask)
287{
288 // see header file for function documentation
289 int iResult=0;
290 if (pTask) {
291 if (fpConfiguration) {
292 iResult=fpConfiguration->GetSource(pTask->GetName())!=NULL;
293 if (iResult>0) {
294 //HLTDebug("task \"%s\" depends on \"%s\"", GetName(), pTask->GetName());
295 } else {
296 //HLTDebug("task \"%s\" independend of \"%s\"", GetName(), pTask->GetName());
297 }
298 } else {
299 iResult=-EFAULT;
300 }
301 } else {
302 iResult=-EINVAL;
303 }
304 return iResult;
305}
306
307AliHLTTask* AliHLTTask::FindTarget(const char* id)
308{
309 // see header file for function documentation
310 AliHLTTask* pTask=NULL;
311 if (id) {
312 pTask=(AliHLTTask*)fListTargets.FindObject(id);
313 }
314 return pTask;
315}
316
317int AliHLTTask::SetTarget(AliHLTTask* pTgt)
318{
319 // see header file for function documentation
320 int iResult=0;
321 if (pTgt) {
322 if (FindTarget(pTgt->GetName())==NULL) {
323 fListTargets.Add(pTgt);
324 } else {
325 iResult=-EEXIST;
326 }
327 } else {
328 iResult=-EINVAL;
329 }
330 return iResult;
331}
332
333int AliHLTTask::UnsetTarget(AliHLTTask* pTarget)
334{
335 // see header file for function documentation
336 fListTargets.Remove(pTarget);
337 return 0;
338}
339
340int AliHLTTask::StartRun()
341{
342 // see header file for function documentation
343 int iResult=0;
344 int iNofInputDataBlocks=0;
345 AliHLTComponent* pComponent=GetComponent();
346 if (pComponent) {
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();
351 if (pSrcTask) {
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);
356 } else {
357 HLTError("task %s (%p): error getting matching data types for source task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
358 iResult=-EFAULT;
359 }
360 }
361 lnk=lnk->Next();
362 }
363 if (iResult>=0) {
364 if (fBlockDataArray.size()>0) {
365 HLTWarning("block data array for task %s (%p) was not cleaned", GetName(), this);
366 fBlockDataArray.resize(0);
367 }
368
369 // component init
370 // the initialization of the component is done by the ComponentHandler after creation
371 // of the component.
372 //iResult=Init( AliHLTComponentEnvironment* environ, void* environ_param, int argc, const char** argv );
373
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);
380
381 // allocate the data buffer, which controls the output buffer and subscriptions
382 if (iResult>=0) {
383 fpDataBuffer=new AliHLTDataBuffer;
384 if (fpDataBuffer!=NULL) {
385 HLTDebug("created data buffer %p for task %s (%p)", fpDataBuffer, GetName(), this);
386 TObjLink* lnk=fListTargets.FirstLink();
387 while (lnk && iResult>=0) {
388 AliHLTTask* pTgtTask=(AliHLTTask*)lnk->GetObject();
389 if (pTgtTask) {
390 if ((iResult=fpDataBuffer->SetConsumer(pTgtTask->GetComponent()))>=0) {
391 }
392 } else {
393 break;
394 iResult=-EFAULT;
395 }
396 lnk=lnk->Next();
397 }
398 } else {
399 HLTFatal("can not create data buffer object, memory allocation failed");
400 iResult=-ENOMEM;
401 }
402 }
403 }
404 } else {
405 HLTError("task %s (%p) does not have a component", GetName(), this);
406 iResult=-EFAULT;
407 }
408 return iResult;
409}
410
411int AliHLTTask::EndRun()
412{
413 // see header file for function documentation
414 int iResult=0;
415 if (fBlockDataArray.size()>0) {
416 fBlockDataArray.resize(0);
417 } else {
418 HLTWarning("task %s (%p) doesn't seem to be in running mode", GetName(), this);
419 }
420 if (fpDataBuffer) {
421 AliHLTDataBuffer* pBuffer=fpDataBuffer;
422 fpDataBuffer=NULL;
423 delete pBuffer;
424 }
425 return iResult;
426}
427
428int AliHLTTask::ProcessTask(Int_t eventNo)
429{
430 // see header file for function documentation
431 int iResult=0;
432 AliHLTComponent* pComponent=GetComponent();
433 if (pComponent && fpDataBuffer) {
434 HLTDebug("Processing task %s (%p) fpDataBuffer %p", GetName(), this, fpDataBuffer);
435 fpDataBuffer->Reset();
436 int iSourceDataBlock=0;
437 int iInputDataVolume=0;
438
439 AliHLTTask* pSrcTask=NULL;
440 TList subscribedTaskList;
441 TObjLink* lnk=fListDependencies.FirstLink();
442
443 // subscribe to all source tasks
444 while (lnk && iResult>=0) {
445 pSrcTask=(AliHLTTask*)lnk->GetObject();
446 if (pSrcTask) {
447 int iMatchingDB=pSrcTask->GetNofMatchingDataBlocks(this);
448 if (iMatchingDB>=0 && static_cast<unsigned int>(iMatchingDB)>fBlockDataArray.size()-iSourceDataBlock) {
449 AliHLTComponentBlockData init;
450 memset(&init, 0, sizeof(AliHLTComponentBlockData));
451 fBlockDataArray.resize(iSourceDataBlock+iMatchingDB, init);
452 } else {
453 if (iMatchingDB<0) {
454 HLTError("task %s (%p): error getting no of matching data blocks from task %s (%p), error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iMatchingDB);
455 iResult=iMatchingDB;
456 break;
457 } else if (iMatchingDB==0) {
458 HLTDebug("source task %s (%p) does not provide any matching data type for task %s (%p)", pSrcTask->GetName(), pSrcTask, GetName(), this);
459 }
460 }
461 if ((iResult=pSrcTask->Subscribe(this, &fBlockDataArray[iSourceDataBlock],fBlockDataArray.size()-iSourceDataBlock))>=0) {
462 for (int i=0; i<iResult; i++) {
463 iInputDataVolume+=fBlockDataArray[i+iSourceDataBlock].fSize;
464 // put the source task as many times into the list as it provides data blocks
465 // makes the bookkeeping for the data release easier
466 subscribedTaskList.Add(pSrcTask);
467 }
468 HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask);
469 iSourceDataBlock+=iResult;
470 iResult=0;
471 } else {
472 HLTError("Task %s (%p): subscription to task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iResult);
473 iResult=-EFAULT;
474 }
475 } else {
476 HLTFatal("fatal internal error in ROOT list handling");
477 iResult=-EFAULT;
478 }
479 lnk=lnk->Next();
480 }
481
482 // process the event
483 int iNofTrial=0; // repeat processing if component returns -ENOSPC
484 AliHLTUInt32_t size=0;
485 if (iResult>=0) {
486 do {
487 long unsigned int iConstBase=0;
488 double fInputMultiplier=0;
489 if (pComponent->GetComponentType()!=AliHLTComponent::kSink)
490 pComponent->GetOutputDataSize(iConstBase, fInputMultiplier);
491 if (fInputMultiplier<0) {
492 HLTWarning("ignoring negative input multiplier");
493 fInputMultiplier=0;
494 }
495 long unsigned int iOutputDataSize=int(fInputMultiplier*iInputDataVolume) + iConstBase;
496 //HLTDebug("task %s: reqired output size %d", GetName(), iOutputDataSize);
497 if (iNofTrial>0) {
498 // dont process again if the buffer size is the same
499 if (size==iOutputDataSize) break;
500 HLTInfo("processing task %s again with buffer size %d", GetName(), iOutputDataSize);
501 }
502 AliHLTUInt8_t* pTgtBuffer=NULL;
503 if (iOutputDataSize>0) pTgtBuffer=fpDataBuffer->GetTargetBuffer(iOutputDataSize);
504 //HLTDebug("provided raw buffer %p", pTgtBuffer);
505 AliHLTComponentEventData evtData;
506 AliHLTComponent::FillEventData(evtData);
507 evtData.fEventID=(AliHLTEventID_t)eventNo;
508 evtData.fBlockCnt=iSourceDataBlock;
509 AliHLTComponentTriggerData trigData;
510 size=iOutputDataSize;
511 AliHLTUInt32_t outputBlockCnt=0;
512 AliHLTComponentBlockData* outputBlocks=NULL;
513 AliHLTComponentEventDoneData* edd;
514 if (pTgtBuffer!=NULL || iOutputDataSize==0) {
515 iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
516 HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt);
517 if (iResult>=0 && pTgtBuffer && outputBlocks) {
518 iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt);
519 delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0;
520 } else {
521 fpDataBuffer->Reset();
522 }
523 } else {
524 HLTError("task %s: no target buffer available", GetName());
525 iResult=-EFAULT;
526 }
527 } while (iResult==-ENOSPC && iNofTrial++<1);
528 }
529
530 // now release all buffers which we have subscribed to
531 iSourceDataBlock=0;
532 lnk=subscribedTaskList.FirstLink();
533 while (lnk) {
534 pSrcTask=(AliHLTTask*)lnk->GetObject();
535 if (pSrcTask) {
536 int iTempRes=0;
537 if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) {
538 HLTDebug("Task %s (%p) successfully released segment of task %s (%p)", GetName(), this, pSrcTask->GetName(), pSrcTask);
539 } else {
540 HLTError("Task %s (%p): realease of task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iTempRes);
541 }
542 } else {
543 HLTFatal("task %s (%p): internal error in ROOT list handling", GetName(), this);
544 if (iResult>=0) iResult=-EFAULT;
545 }
546 subscribedTaskList.Remove(lnk);
547 lnk=subscribedTaskList.FirstLink();
548 iSourceDataBlock++;
549 }
550 if (subscribedTaskList.GetSize()>0) {
551 HLTError("task %s (%p): could not release all data buffers", GetName(), this);
552 }
553 } else {
554 HLTError("task %s (%p): internal failure (not initialized component %p, data buffer %p)", GetName(), this, fpComponent, fpDataBuffer);
555 iResult=-EFAULT;
556 }
557 return iResult;
558}
559
560int AliHLTTask::GetNofMatchingDataBlocks(const AliHLTTask* pConsumerTask) const
561{
562 // see header file for function documentation
563 int iResult=0;
564 if (pConsumerTask) {
565 if (fpDataBuffer) {
566 iResult=fpDataBuffer->FindMatchingDataBlocks(pConsumerTask->GetComponent(), NULL);
567 } else {
568 HLTFatal("internal data buffer missing");
569 iResult=-EFAULT;
570 }
571 } else {
572 iResult=-EINVAL;
573 }
574 return iResult;
575}
576
577int AliHLTTask::GetNofMatchingDataTypes(const AliHLTTask* pConsumerTask) const
578{
579 // see header file for function documentation
580 int iResult=0;
581 if (pConsumerTask) {
582 AliHLTComponent* pComponent=GetComponent();
583 if (!pComponent) {
584 // init ?
585 HLTError("component not initialized");
586 iResult=-EFAULT;
587 }
588 if (pComponent) {
589 iResult=pComponent->FindMatchingDataTypes(pConsumerTask->GetComponent(), NULL);
590 } else {
591 HLTFatal("task initialization failed");
592 iResult=-EFAULT;
593 }
594 } else {
595 iResult=-EINVAL;
596 }
597 return iResult;
598}
599
600int AliHLTTask::Subscribe(const AliHLTTask* pConsumerTask, AliHLTComponentBlockData* pBlockDesc, int iArraySize)
601{
602 // see header file for function documentation
603 int iResult=0;
604 if (pConsumerTask) {
605 if (fpDataBuffer) {
606 iResult=fpDataBuffer->Subscribe(pConsumerTask->GetComponent(), pBlockDesc, iArraySize);
607 } else {
608 HLTFatal("internal data buffer missing");
609 iResult=-EFAULT;
610 }
611 } else {
612 iResult=-EINVAL;
613 }
614 return iResult;
615}
616
617int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* pConsumerTask)
618{
619 // see header file for function documentation
620 int iResult=0;
621 if (pConsumerTask && pBlockDesc) {
622 if (fpDataBuffer) {
623 iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent());
624 } else {
625 HLTFatal("internal data buffer missing");
626 iResult=-EFAULT;
627 }
628 } else {
629 iResult=-EINVAL;
630 }
631 return iResult;
632}
633
634void AliHLTTask::PrintStatus()
635{
636 // see header file for function documentation
637 HLTLogKeyword("task properties");
638 AliHLTComponent* pComponent=GetComponent();
639 if (pComponent) {
640 HLTMessage(" component: %s (%p)", pComponent->GetComponentID(), pComponent);
641 } else {
642 HLTMessage(" no component set!");
643 }
644 if (fpConfiguration) {
645 AliHLTConfiguration* pSrc=fpConfiguration->GetFirstSource();
646 while (pSrc) {
647 const char* pQualifier="unresolved";
648 if (FindDependency(pSrc->GetName()))
649 pQualifier="resolved";
650 HLTMessage(" source: %s (%s)", pSrc->GetName(), pQualifier);
651 pSrc=fpConfiguration->GetNextSource();
652 }
653 TObjLink* lnk = fListTargets.FirstLink();
654 while (lnk) {
655 TObject *obj = lnk->GetObject();
656 HLTMessage(" target: %s", obj->GetName());
657 lnk = lnk->Next();
658 }
659 } else {
660 HLTMessage(" task \"%s\" not initialized", GetName());
661 }
662}