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 AliHLTSystem.cxx
20 @author Matthias Richter
22 @brief Implementation of HLT module management.
29 #include "AliHLTStdIncludes.h"
30 #include "AliHLTSystem.h"
31 #include "AliHLTComponentHandler.h"
32 #include "AliHLTComponent.h"
33 #include "AliHLTConfiguration.h"
34 #include "AliHLTConfigurationHandler.h"
35 #include "AliHLTTask.h"
36 #include "AliHLTModuleAgent.h"
37 #include "AliHLTOfflineInterface.h"
38 #include <TObjArray.h>
39 #include <TObjString.h>
40 #include <TStopwatch.h>
42 #include <TInterpreter.h>
44 /** HLT default component libraries */
45 const char* kHLTDefaultLibs[]= {
48 // "libAliHLTSample.so",
55 /** ROOT macro for the implementation of ROOT specific class methods */
56 ClassImp(AliHLTSystem)
58 AliHLTSystem::AliHLTSystem()
60 fpComponentHandler(new AliHLTComponentHandler()),
61 fpConfigurationHandler(new AliHLTConfigurationHandler()),
66 // see header file for class documentation
68 // refer to README to build package
70 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
72 if (fgNofInstances++>0)
73 HLTWarning("multiple instances of AliHLTSystem, you should not use more than one at a time");
75 SetGlobalLoggingLevel(kHLTLogDefault);
76 if (fpComponentHandler) {
77 AliHLTComponentEnvironment env;
78 memset(&env, 0, sizeof(AliHLTComponentEnvironment));
79 env.fAllocMemoryFunc=AliHLTSystem::AllocMemory;
80 env.fLoggingFunc=NULL;
81 AliHLTComponentLogSeverity loglevel=fpComponentHandler->GetLocalLoggingLevel();
82 fpComponentHandler->SetLocalLoggingLevel(kHLTLogError);
83 fpComponentHandler->SetEnvironment(&env);
84 fpComponentHandler->LoadLibrary("libAliHLTUtil.so");
85 fgAliLoggingFunc=(AliHLTLogging::AliHLTDynamicMessage)fpComponentHandler->FindSymbol("libAliHLTUtil.so", "AliDynamicMessage");
86 fpComponentHandler->SetLocalLoggingLevel(loglevel);
87 if (fgAliLoggingFunc==NULL) {
88 HLTError("symbol lookp failure: can not find AliDynamicMessage, switching to HLT logging system");
90 fpComponentHandler->AnnounceVersion();
92 HLTFatal("can not create Component Handler");
94 if (fpConfigurationHandler) {
95 AliHLTConfiguration::GlobalInit(fpConfigurationHandler);
97 HLTFatal("can not create Configuration Handler");
101 AliHLTSystem::~AliHLTSystem()
103 // see header file for class documentation
106 AliHLTConfiguration::GlobalDeinit(fpConfigurationHandler);
107 if (fpConfigurationHandler) {
108 delete fpConfigurationHandler;
110 fpConfigurationHandler=NULL;
112 if (fpComponentHandler) {
113 delete fpComponentHandler;
115 fpComponentHandler=NULL;
118 int AliHLTSystem::fgNofInstances=0;
120 int AliHLTSystem::AddConfiguration(AliHLTConfiguration* pConf)
122 // see header file for class documentation
131 int AliHLTSystem::InsertConfiguration(AliHLTConfiguration* pConf, AliHLTConfiguration* pPrec)
133 // see header file for class documentation
145 int AliHLTSystem::DeleteConfiguration(AliHLTConfiguration* pConf)
147 // see header file for class documentation
156 int AliHLTSystem::BuildTaskList(const char* id)
158 // see header file for class documentation
161 if (fpConfigurationHandler) {
162 AliHLTConfiguration* pConf=fpConfigurationHandler->FindConfiguration(id);
164 iResult=BuildTaskList(pConf);
166 HLTError("unknown configuration \"%s\"", id);
178 int AliHLTSystem::BuildTaskList(AliHLTConfiguration* pConf)
180 // see header file for class documentation
183 AliHLTTask* pTask=NULL;
184 if ((pTask=FindTask(pConf->GetName()))!=NULL) {
185 if (pTask->GetConf()!=pConf) {
186 HLTError("configuration missmatch, there is already a task with configuration name \"%s\", but it is different. Most likely configuration %p is not registered properly", pConf->GetName(), pConf);
189 // task for this configuration exists, terminate
191 } else if (pConf->SourcesResolved(1)!=1) {
192 HLTError("configuration \"%s\" has unresolved sources, aborting ...", pConf->GetName());
195 pTask=new AliHLTTask(pConf);
200 static int iterationLevel=0;
201 if (pTask && iResult>=0) {
202 // check for circular dependencies
203 if ((iResult=pConf->FollowDependency(pConf->GetName()))>0) {
204 HLTError("detected circular dependency for configuration \"%s\"", pTask->GetName());
205 pTask->PrintDependencyTree(pTask->GetName(), 1/*use the configuration list*/);
206 HLTError("aborted ...");
210 // check whether all dependencies are already in the task list
211 // create the missing ones
212 // this step is an iterative process which calls this function again for the missing
213 // configurations, in order to avoid the currently processed task to be created
214 // again it is added to the list temporarily and removed afterwards
215 // This is of high importance to preserve the order of the tasks. Furthermore, the
216 // InsertTask method has to be used in order to set all the cross links right
217 fTaskList.Add(pTask);
218 AliHLTConfiguration* pDep=pConf->GetFirstSource();
219 while (pDep!=NULL && iResult>=0) {
220 HLTDebug("iteration %d: checking dependency %s (%p)", iterationLevel, pDep->GetName(), pDep);
221 if (FindTask(pDep->GetName())==NULL) {
222 HLTDebug("iteration %d: building task list for configuration %s (%p)", iterationLevel, pDep->GetName(), pDep);
224 iResult=BuildTaskList(pDep);
227 pDep=pConf->GetNextSource();
229 // remove the temporarily added task
230 fTaskList.Remove(pTask);
232 // insert the task and set the cross-links
234 HLTDebug("iteration %d: inserting task %s (%p)", iterationLevel, pTask->GetName(), pTask);
235 iResult=InsertTask(pTask);
248 int AliHLTSystem::CleanTaskList()
250 // see header file for class documentation
253 while ((lnk=fTaskList.LastLink())!=NULL) {
254 delete (lnk->GetObject());
255 fTaskList.Remove(lnk);
260 int AliHLTSystem::InsertTask(AliHLTTask* pTask)
262 // see header file for class documentation
264 TObjLink *lnk = NULL;
265 if ((iResult=pTask->CheckDependencies())>0)
266 lnk=fTaskList.FirstLink();
267 while (lnk && iResult>0) {
268 AliHLTTask* pCurr = (AliHLTTask*)lnk->GetObject();
269 //HLTDebug("checking \"%s\"", pCurr->GetName());
270 iResult=pTask->Depends(pCurr);
272 iResult=pTask->SetDependency(pCurr);
273 pCurr->SetTarget(pTask);
274 HLTDebug("set dependency \"%s\" for configuration \"%s\"", pCurr->GetName(), pTask->GetName());
276 if (pCurr->Depends(pTask)) {
277 // circular dependency
278 HLTError("circular dependency: can not resolve dependencies for configuration \"%s\"", pTask->GetName());
280 } else if ((iResult=pTask->CheckDependencies())>0) {
286 fTaskList.AddAfter(lnk, pTask);
288 fTaskList.AddFirst(pTask);
290 HLTDebug("task \"%s\" (%p) inserted (size %d)", pTask->GetName(), pTask, sizeof(AliHLTTask));
291 } else if (iResult>0) {
292 HLTError("can not resolve dependencies for configuration \"%s\" (%d unresolved)", pTask->GetName(), iResult);
298 AliHLTTask* AliHLTSystem::FindTask(const char* id)
300 // see header file for class documentation
301 AliHLTTask* pTask=NULL;
303 pTask=(AliHLTTask*)fTaskList.FindObject(id);
308 void AliHLTSystem::PrintTaskList()
310 // see header file for class documentation
311 HLTLogKeyword("task list");
312 TObjLink *lnk = NULL;
313 HLTMessage("Task List");
314 lnk=fTaskList.FirstLink();
316 TObject* obj=lnk->GetObject();
318 HLTMessage(" %s - status:", obj->GetName());
319 AliHLTTask* pTask=(AliHLTTask*)obj;
320 pTask->PrintStatus();
327 int AliHLTSystem::Run(Int_t iNofEvents)
329 // see header file for class documentation
332 SetStatusFlags(kRunning);
333 TStopwatch StopwatchBase; StopwatchBase.Reset();
334 TStopwatch StopwatchDA; StopwatchDA.Reset();
335 TStopwatch StopwatchInput; StopwatchInput.Reset();
336 TStopwatch StopwatchOutput; StopwatchOutput.Reset();
337 TObjArray Stopwatches;
338 Stopwatches.AddAt(&StopwatchBase, (int)AliHLTComponent::kSWBase);
339 Stopwatches.AddAt(&StopwatchDA, (int)AliHLTComponent::kSWDA);
340 Stopwatches.AddAt(&StopwatchInput, (int)AliHLTComponent::kSWInput);
341 Stopwatches.AddAt(&StopwatchOutput, (int)AliHLTComponent::kSWOutput);
342 if ((iResult=InitTasks())>=0 && (iResult=InitBenchmarking(&Stopwatches))>=0) {
343 if ((iResult=StartTasks())>=0) {
344 for (int i=0; i<iNofEvents && iResult>=0; i++) {
345 iResult=ProcessTasks(i);
347 HLTInfo("Event %d successfully finished (%d)", i, iResult);
351 HLTError("Processing of event %d failed (%d)", i, iResult);
352 // TODO: define different running modes to either ignore errors in
353 // event processing or not
360 HLTError("can not start task list");
363 } else if (iResult!=-ENOENT) {
364 HLTError("can not initialize task list");
368 HLTInfo("HLT statistics:\n"
369 " base: R:%.3fs C:%.3fs\n"
370 " input: R:%.3fs C:%.3fs\n"
371 " output: R:%.3fs C:%.3fs\n"
372 " event processing : R:%.3fs C:%.3fs"
373 , StopwatchBase.RealTime(),StopwatchBase.CpuTime()
374 , StopwatchInput.RealTime(),StopwatchInput.CpuTime()
375 , StopwatchOutput.RealTime(),StopwatchOutput.CpuTime()
376 , StopwatchDA.RealTime(),StopwatchDA.CpuTime());
377 } else if (iResult==-ENOENT) {
378 iResult=0; // do not propagate the error
380 ClearStatusFlags(kRunning);
384 int AliHLTSystem::InitTasks()
386 // see header file for class documentation
388 TObjLink *lnk=fTaskList.FirstLink();
390 HLTWarning("Task list is empty, aborting ...");
393 while (lnk && iResult>=0) {
394 TObject* obj=lnk->GetObject();
396 AliHLTTask* pTask=(AliHLTTask*)obj;
397 iResult=pTask->Init(NULL, fpComponentHandler);
407 int AliHLTSystem::InitBenchmarking(TObjArray* pStopwatches)
409 // see header file for class documentation
410 if (pStopwatches==NULL) return -EINVAL;
413 TObjLink *lnk=fTaskList.FirstLink();
414 while (lnk && iResult>=0) {
415 TObject* obj=lnk->GetObject();
417 AliHLTTask* pTask=(AliHLTTask*)obj;
418 AliHLTComponent* pComp=NULL;
419 if (iResult>=0 && (pComp=pTask->GetComponent())!=NULL) {
420 switch (pComp->GetComponentType()) {
421 case AliHLTComponent::kProcessor:
422 pComp->SetStopwatches(pStopwatches);
424 case AliHLTComponent::kSource:
426 // this switch determines whether the time consumption of the
427 // AliHLTComponent base methods should be counted to the input
428 // stopwatch or base stopwatch.
429 //int inputBase=(int)AliHLTComponent::kSWBase;
430 int inputBase=(int)AliHLTComponent::kSWInput;
431 pComp->SetStopwatch(pStopwatches->At(inputBase), AliHLTComponent::kSWBase);
432 pComp->SetStopwatch(pStopwatches->At((int)AliHLTComponent::kSWInput), AliHLTComponent::kSWDA);
435 case AliHLTComponent::kSink:
437 // this switch determines whether the time consumption of the
438 // AliHLTComponent base methods should be counted to the output
439 // stopwatch or base stopwatch.
440 //int outputBase=(int)AliHLTComponent::kSWBase;
441 int outputBase=(int)AliHLTComponent::kSWOutput;
442 pComp->SetStopwatch(pStopwatches->At(outputBase), AliHLTComponent::kSWBase);
443 pComp->SetStopwatch(pStopwatches->At((int)AliHLTComponent::kSWOutput), AliHLTComponent::kSWDA);
447 HLTWarning("unknown component type %d", (int)pComp->GetComponentType());
457 int AliHLTSystem::StartTasks()
459 // see header file for class documentation
461 TObjLink *lnk=fTaskList.FirstLink();
462 while (lnk && iResult>=0) {
463 TObject* obj=lnk->GetObject();
465 AliHLTTask* pTask=(AliHLTTask*)obj;
466 iResult=pTask->StartRun();
476 int AliHLTSystem::ProcessTasks(Int_t eventNo)
478 // see header file for class documentation
480 HLTDebug("processing event no %d", eventNo);
481 TObjLink *lnk=fTaskList.FirstLink();
482 while (lnk && iResult>=0) {
483 TObject* obj=lnk->GetObject();
485 AliHLTTask* pTask=(AliHLTTask*)obj;
486 iResult=pTask->ProcessTask(eventNo);
487 HLTDebug("task %s finnished (%d)", pTask->GetName(), iResult);
495 int AliHLTSystem::StopTasks()
497 // see header file for class documentation
499 TObjLink *lnk=fTaskList.FirstLink();
500 while (lnk && iResult>=0) {
501 TObject* obj=lnk->GetObject();
503 AliHLTTask* pTask=(AliHLTTask*)obj;
504 iResult=pTask->EndRun();
512 int AliHLTSystem::DeinitTasks()
514 // see header file for class documentation
516 TObjLink *lnk=fTaskList.FirstLink();
517 while (lnk && iResult>=0) {
518 TObject* obj=lnk->GetObject();
520 AliHLTTask* pTask=(AliHLTTask*)obj;
521 iResult=pTask->Deinit();
529 void* AliHLTSystem::AllocMemory( void* /*param*/, unsigned long size )
531 // see header file for class documentation
534 p=(void*)new char[size];
538 log.LoggingVarargs(kHLTLogError, "AliHLTSystem" , "AllocMemory" , __FILE__ , __LINE__ , "exeption during memory allocation" );
543 int AliHLTSystem::Reconstruct(int nofEvents, AliRunLoader* runLoader,
544 AliRawReader* rawReader)
546 // see header file for class documentation
549 HLTInfo("Run Loader %p, Raw Reader %p , %d events", runLoader, rawReader, nofEvents);
550 if (CheckStatus(kReady)) {
551 if ((iResult=AliHLTOfflineInterface::SetParamsToComponents(runLoader, rawReader))>=0) {
552 iResult=Run(nofEvents);
555 HLTError("wrong state %#x, required flags %#x", GetStatusFlags(), kReady);
558 HLTError("missing run loader instance");
564 int AliHLTSystem::FillESD(int eventNo, AliRunLoader* runLoader, AliESDEvent* esd)
566 // see header file for class documentation
569 HLTInfo("Event %d: Run Loader %p, ESD %p", eventNo, runLoader, esd);
570 iResult=AliHLTOfflineInterface::FillComponentESDs(eventNo, runLoader, esd);
572 HLTError("missing run loader/ESD instance(s)");
578 int AliHLTSystem::LoadComponentLibraries(const char* libraries)
580 // see header file for class documentation
583 if (fpComponentHandler) {
584 TString libs(libraries);
585 TObjArray* pTokens=libs.Tokenize(" ");
587 int iEntries=pTokens->GetEntries();
588 for (int i=0; i<iEntries && iResult>=0; i++) {
589 iResult=fpComponentHandler->LoadLibrary((((TObjString*)pTokens->At(i))->GetString()).Data());
594 SetStatusFlags(kLibrariesLoaded);
596 // lets see if we need this, probably not
597 //fpComponentHandler->UnloadLibraries();
598 ClearStatusFlags(kLibrariesLoaded);
602 HLTFatal("no component handler available");
610 int AliHLTSystem::Configure(AliRunLoader* runloader)
612 // see header file for class documentation
614 if (CheckStatus(kRunning)) {
615 HLTError("HLT system in running state, can not configure");
618 ClearStatusFlags(kConfigurationLoaded|kTaskListCreated);
619 if (CheckFilter(kHLTLogDebug))
620 AliHLTModuleAgent::PrintStatus();
621 if (CheckStatus(kConfigurationLoaded)==0) {
622 iResult=LoadConfigurations(runloader);
624 if (fLocalRec.Length()==0) {
625 HLTError("custom configuration(s) specified, but no configuration to run in local reconstruction, use \'localrec=<conf>\' option");
630 SetStatusFlags(kConfigurationLoaded);
631 if (CheckFilter(kHLTLogDebug))
632 fpConfigurationHandler->PrintConfigurations();
633 iResult=BuildTaskListsFromTopConfigurations(runloader);
635 SetStatusFlags(kTaskListCreated);
638 if (iResult<0) SetStatusFlags(kError);
643 int AliHLTSystem::ScanOptions(const char* options)
645 // see header file for class documentation
649 TString alloptions(options);
650 TObjArray* pTokens=alloptions.Tokenize(" ");
652 int iEntries=pTokens->GetEntries();
653 for (int i=0; i<iEntries; i++) {
654 TString token=(((TObjString*)pTokens->At(i))->GetString());
655 if (token.Contains("loglevel=")) {
656 TString param=token.ReplaceAll("loglevel=", "");
657 if (param.IsDigit()) {
658 SetGlobalLoggingLevel((AliHLTComponentLogSeverity)param.Atoi());
659 } else if (param.BeginsWith("0x") &&
660 param.Replace(0,2,"",0).IsHex()) {
662 sscanf(param.Data(),"%x", &severity);
663 SetGlobalLoggingLevel((AliHLTComponentLogSeverity)severity);
665 HLTWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
667 } else if (token.Contains("alilog=off")) {
669 } else if (token.Contains("config=")) {
670 TString param=token.ReplaceAll("config=", "");
672 gROOT->Macro(param.Data(), &error);
674 SetStatusFlags(kConfigurationLoaded);
676 HLTError("can not execute macro \'%s\'", param.Data());
679 } else if (token.Contains("localrec=")) {
680 TString param=token.ReplaceAll("localrec=", "");
681 fLocalRec=param.ReplaceAll(",", " ");
682 } else if (token.BeginsWith("lib") && token.EndsWith(".so")) {
686 HLTWarning("unknown option \'%s\'", token.Data());
694 const char** deflib=kHLTDefaultLibs;
700 if ((!CheckStatus(AliHLTSystem::kLibrariesLoaded)) &&
701 (LoadComponentLibraries(libs.Data())<0)) {
702 HLTError("error while loading HLT libraries");
710 int AliHLTSystem::Reset(int bForce)
712 // see header file for class documentation
714 if (!bForce && CheckStatus(kRunning)) {
715 HLTError("HLT system in running state, can not configure");
719 ClearStatusFlags(~kUninitialized);
723 int AliHLTSystem::LoadConfigurations(AliRunLoader* runloader)
725 // see header file for class documentation
726 if (CheckStatus(kRunning)) {
727 HLTError("HLT system in running state, can not configure");
731 AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
732 while (pAgent && iResult>=0) {
733 const char* deplibs=pAgent->GetRequiredComponentLibraries();
735 HLTDebug("load libraries \'%s\' for agent %s (%p)", deplibs, pAgent->GetName(), pAgent);
736 iResult=LoadComponentLibraries(deplibs);
739 HLTDebug("load configurations for agent %s (%p)", pAgent->GetName(), pAgent);
740 pAgent->CreateConfigurations(fpConfigurationHandler, runloader);
741 pAgent=AliHLTModuleAgent::GetNextAgent();
747 int AliHLTSystem::BuildTaskListsFromTopConfigurations(AliRunLoader* runloader)
749 // see header file for class documentation
750 if (CheckStatus(kRunning)) {
751 HLTError("HLT system in running state, can not configure");
754 if (!CheckStatus(kConfigurationLoaded)) {
755 HLTWarning("configurations not yet loaded");
760 AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
761 while ((pAgent || fLocalRec.Length()>0) && iResult>=0) {
763 if (fLocalRec.Length()>0) {
765 HLTInfo("custom local reconstruction configurations: %s", tops.Data());
767 tops=pAgent->GetLocalRecConfigurations(runloader);
768 HLTInfo("local reconstruction configurations for agent %s (%p): %s", pAgent->GetName(), pAgent, tops.Data());
770 TObjArray* pTokens=tops.Tokenize(" ");
772 int iEntries=pTokens->GetEntries();
773 for (int i=0; i<iEntries && iResult>=0; i++) {
774 const char* pCID=((TObjString*)pTokens->At(i))->GetString().Data();
775 AliHLTConfiguration* pConf=fpConfigurationHandler->FindConfiguration(pCID);
777 iResult=BuildTaskList(pConf);
779 HLTWarning("can not find top configuration %s", pCID);
785 if (fLocalRec.Length()>0) {
786 break; // ignore the agents
788 pAgent=AliHLTModuleAgent::GetNextAgent();
790 if (iResult>=0) SetStatusFlags(kTaskListCreated);
795 int AliHLTSystem::CheckStatus(int flag)
797 // see header file for class documentation
798 if (flag==kUninitialized && flag==fState) return 1;
799 if ((fState&flag)==flag) return 1;
803 int AliHLTSystem::GetStatusFlags()
805 // see header file for class documentation
809 int AliHLTSystem::SetStatusFlags(int flags)
811 // see header file for class documentation
816 int AliHLTSystem::ClearStatusFlags(int flags)
818 // see header file for class documentation
823 void* AliHLTSystem::FindDynamicSymbol(const char* library, const char* symbol)
825 // see header file for class documentation
826 if (fpComponentHandler==NULL) return NULL;
827 return fpComponentHandler->FindSymbol(library, symbol);