]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTSystem.cxx
reverting r45444 to disentangle modules and make porting possible
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTSystem.cxx
1 // $Id$
2 //**************************************************************************
3 //* This file is property of and copyright by the ALICE HLT Project        * 
4 //* ALICE Experiment at CERN, All rights reserved.                         *
5 //*                                                                        *
6 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
7 //*                  for The ALICE HLT Project.                            *
8 //*                                                                        *
9 //* Permission to use, copy, modify and distribute this software and its   *
10 //* documentation strictly for non-commercial purposes is hereby granted   *
11 //* without fee, provided that the above copyright notice appears in all   *
12 //* copies and that both the copyright notice and this permission notice   *
13 //* appear in the supporting documentation. The authors make no claims     *
14 //* about the suitability of this software for any purpose. It is          *
15 //* provided "as is" without express or implied warranty.                  *
16 //**************************************************************************
17
18 /** @file   AliHLTSystem.cxx
19     @author Matthias Richter
20     @date   
21     @brief  Implementation of HLT module management.
22 */
23
24 #if __GNUC__>= 3
25 using namespace std;
26 #endif
27
28 #include <cassert>
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 "AliHLTDataSource.h"
39 #include "AliHLTOUT.h"
40 #include "AliHLTOUTHandler.h"
41 #include "AliHLTOUTTask.h"
42 #include "AliHLTControlTask.h"
43 #include "AliHLTDataBuffer.h"
44 #include "AliHLTMisc.h"
45 #include <TObjArray.h>
46 #include <TObjString.h>
47 #include <TStopwatch.h>
48 #include <TList.h>
49 //#include <TSystem.h>
50 #include <TROOT.h>
51 //#include <TInterpreter.h>
52
53 /** HLT default component libraries */
54 const char* AliHLTSystem::fgkHLTDefaultLibs[]= {
55   "libAliHLTUtil.so", 
56   "libAliHLTRCU.so", 
57   "libAliHLTTPC.so", 
58   //  "libAliHLTSample.so",
59   //  "libAliHLTPHOS.so",
60   "libAliHLTMUON.so",
61   "libAliHLTTRD.so",
62   "libAliHLTITS.so",
63   "libAliHLTVZERO.so",
64   "libAliHLTZDC.so",
65   "libAliHLTGlobal.so",
66   "libAliHLTTrigger.so",
67   NULL
68 };
69
70 /** ROOT macro for the implementation of ROOT specific class methods */
71 ClassImp(AliHLTSystem)
72
73 AliHLTSystem::AliHLTSystem(AliHLTComponentLogSeverity loglevel, const char* name)
74   :
75   fpComponentHandler(AliHLTComponentHandler::CreateHandler()),
76   fpConfigurationHandler(AliHLTConfigurationHandler::CreateHandler()),
77   fTaskList(),
78   fState(0),
79   fChains(),
80   fStopwatches(new TObjArray),
81   fEventCount(-1),
82   fGoodEvents(-1),
83   fpChainHandlers(NULL),
84   fpEsdHandlers(NULL),
85   fpProprietaryHandlers(NULL),
86   fpHLTOUTTask(NULL),
87   fpControlTask(NULL),
88   fName(name)
89   , fECSParams()
90 {
91   // see header file for class documentation
92   // or
93   // refer to README to build package
94   // or
95   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
96
97   if (fgNofInstances++>0) {
98     // July 2008: multiple instances are now allowed
99     // AliHLTSystem is used in multiple instances for the kChain HLTOUT handler
100     //HLTWarning("multiple instances of AliHLTSystem, you should not use more than one at a time");
101   }
102
103   SetGlobalLoggingLevel(loglevel);
104   SetFrameworkLog(loglevel);
105   if (fpComponentHandler) {
106     AliHLTAnalysisEnvironment env;
107     memset(&env, 0, sizeof(AliHLTAnalysisEnvironment));
108     env.fStructSize=sizeof(AliHLTAnalysisEnvironment);
109     env.fAllocMemoryFunc=AliHLTSystem::AllocMemory;
110     env.fGetEventDoneDataFunc=AliHLTSystem::AllocEventDoneData;
111     env.fLoggingFunc=NULL;
112     fpComponentHandler->SetEnvironment(&env);
113     InitAliLogFunc(fpComponentHandler);
114     if (fgNofInstances==1) {
115     fpComponentHandler->AnnounceVersion();
116     }
117   } else {
118     HLTFatal("can not create Component Handler");
119   }
120   if (fpConfigurationHandler) {
121     AliHLTConfiguration::GlobalInit(fpConfigurationHandler);
122   } else {
123     HLTFatal("can not create Configuration Handler");
124   }
125 }
126
127 AliHLTSystem::~AliHLTSystem()
128 {
129   // see header file for class documentation
130   fgNofInstances--;
131   CleanHLTOUT();
132   CleanTaskList();
133   AliHLTConfiguration::GlobalDeinit(fpConfigurationHandler);
134   if (fpConfigurationHandler) {
135     fpConfigurationHandler->Destroy();
136   }
137   fpConfigurationHandler=NULL;
138   
139   if (fpComponentHandler) {
140     fpComponentHandler->Destroy();
141   }
142   fpComponentHandler=NULL;
143   delete fStopwatches;
144
145   // note: fpHLTOUTTask and fpControlTask are deleted by
146   // CleanTaskList
147 }
148
149 int AliHLTSystem::fgNofInstances=0;
150
151 int AliHLTSystem::BuildTaskList(const char* id)
152 {
153   // see header file for class documentation
154   int iResult=0;
155   if (id) {
156     if (fpConfigurationHandler) {
157       AliHLTConfiguration* pConf=fpConfigurationHandler->FindConfiguration(id);
158       if (pConf) {
159         iResult=BuildTaskList(pConf);
160       } else {
161         HLTError("unknown configuration \"%s\"", id);
162         iResult=-EEXIST;
163       }
164     } else {
165       iResult=-EFAULT;
166     }
167   } else {
168     iResult=-EINVAL;
169   }
170   return iResult;
171 }
172
173 int AliHLTSystem::BuildTaskList(AliHLTConfiguration* pConf)
174 {
175   // see header file for class documentation
176   int iResult=0;
177   if (pConf) {
178     AliHLTTask* pTask=NULL;
179     if ((pTask=FindTask(pConf->GetName()))!=NULL) {
180       if (pTask->GetConf()!=pConf) {
181         HLTError("configuration mismatch, there is already a task with configuration name \"%s\", but it is different. Most likely configuration %p is not registered properly", pConf->GetName(), pConf);
182         iResult=-EEXIST;
183       }
184       // task for this configuration exists, terminate
185       pTask=NULL;
186     } else if (pConf->SourcesResolved(1)!=1) {
187         HLTError("configuration \"%s\" has unresolved sources, aborting ...", pConf->GetName());
188         iResult=-ENOLINK;
189     } else {
190       pTask=new AliHLTTask(pConf);
191       if (pTask==NULL) {
192         iResult=-ENOMEM;
193       } else {
194         pTask->SetLocalLoggingLevel(GetLocalLoggingLevel());
195       }
196     }
197     static int iterationLevel=0;
198     if (pTask && iResult>=0) {
199       // check for circular dependencies
200       if ((iResult=pConf->FollowDependency(pConf->GetName()))>0) {
201         HLTError("detected circular dependency for configuration \"%s\"", pTask->GetName());
202         pTask->PrintDependencyTree(pTask->GetName(), 1/*use the configuration list*/);
203         HLTError("aborted ...");
204         iResult=-ELOOP;
205       }
206       if (iResult>=0) {
207         // check whether all dependencies are already in the task list
208         // create the missing ones
209         // this step is an iterative process which calls this function again for the missing
210         // configurations, in order to avoid the currently processed task to be created
211         // again it is added to the list temporarily and removed afterwards
212         // This is of high importance to preserve the order of the tasks. Furthermore, the
213         // InsertTask method has to be used in order to set all the cross links right 
214         fTaskList.Add(pTask);
215         AliHLTConfiguration* pDep=pConf->GetFirstSource();
216         while (pDep!=NULL && iResult>=0) {
217           HLTDebug("iteration %d: checking dependency %s (%p)", iterationLevel, pDep->GetName(), pDep);
218           if (FindTask(pDep->GetName())==NULL) {
219             HLTDebug("iteration %d: building task list for configuration %s (%p)", iterationLevel, pDep->GetName(), pDep);
220             iterationLevel++;
221             iResult=BuildTaskList(pDep);
222             iterationLevel--;
223           }
224           pDep=pConf->GetNextSource();
225         }
226         // remove the temporarily added task
227         fTaskList.Remove(pTask);
228
229         // insert the task and set the cross-links
230         if (iResult>=0) {
231           HLTDebug("iteration %d: inserting task %s (%p)", iterationLevel, pTask->GetName(), pTask);
232           iResult=InsertTask(pTask);
233         }
234       } else {
235         delete pTask;
236         pTask=NULL;
237       }
238     }
239   } else {
240     iResult=-EINVAL;
241   }
242   return iResult;
243 }
244
245 int AliHLTSystem::CleanTaskList()
246 {
247   // see header file for class documentation
248   int iResult=0;
249   fpHLTOUTTask=NULL;
250   fpControlTask=NULL;
251   TObjLink* lnk=NULL;
252   while ((lnk=fTaskList.LastLink())!=NULL) {
253     delete (lnk->GetObject());
254     fTaskList.Remove(lnk);
255   }
256
257   return iResult;
258 }
259
260 int AliHLTSystem::InsertTask(AliHLTTask* pTask)
261 {
262   // see header file for class documentation
263   int iResult=0;
264   if (fpControlTask==NULL) {
265     fpControlTask=new AliHLTControlTask;
266     if (!fpControlTask) return -ENOMEM;
267     fTaskList.AddFirst(fpControlTask);
268   }
269   TObjLink *controlLnk=NULL;
270   TObjLink *lnk = fTaskList.FirstLink();
271   assert(!lnk || lnk->GetObject()==fpControlTask || fpControlTask==NULL);
272   if (lnk && lnk->GetObject()==fpControlTask) {
273     if (pTask->GetConf() && pTask->GetConf()->GetFirstSource()==NULL) {
274       pTask->SetDependency(fpControlTask);
275       fpControlTask->SetTarget(pTask);
276     }
277     controlLnk=lnk;
278     lnk=lnk->Next();
279   }
280   if ((iResult=pTask->CheckDependencies())<=0)
281     lnk=NULL;
282   while (lnk && iResult>0) {
283     AliHLTTask* pCurr = (AliHLTTask*)lnk->GetObject();
284     //HLTDebug("checking  \"%s\"", pCurr->GetName());
285     iResult=pTask->Depends(pCurr);
286     if (iResult>0) {
287       iResult=pTask->SetDependency(pCurr);
288       pCurr->SetTarget(pTask);
289       HLTDebug("set dependency  \"%s\" for configuration \"%s\"", pCurr->GetName(), pTask->GetName());
290     }
291     if (pCurr->Depends(pTask)) {
292       // circular dependency
293       HLTError("circular dependency: can not resolve dependencies for configuration \"%s\"", pTask->GetName());
294       iResult=-ELOOP;
295     } else if ((iResult=pTask->CheckDependencies())>0) {
296       lnk = lnk->Next();
297     }
298   }
299   if (iResult==0) {
300       if (lnk) {
301         fTaskList.AddAfter(lnk, pTask);
302       } else if (controlLnk) {
303         fTaskList.AddAfter(controlLnk, pTask);
304       } else {
305         fTaskList.AddFirst(pTask);
306       }
307       HLTDebug("task \"%s\" (%p) inserted (size %d)", pTask->GetName(), pTask, sizeof(AliHLTTask));
308   } else if (iResult>0) {
309     HLTError("can not resolve dependencies for configuration \"%s\" (%d unresolved)", pTask->GetName(), iResult);
310     iResult=-ENOLINK;
311   }
312   return iResult;
313 }
314
315 AliHLTTask* AliHLTSystem::FindTask(const char* id)
316 {
317   // see header file for class documentation
318   AliHLTTask* pTask=NULL;
319   if (id) {
320     pTask=dynamic_cast<AliHLTTask*>(fTaskList.FindObject(id)); 
321   }
322   return pTask;
323 }
324
325 void AliHLTSystem::PrintTaskList()
326 {
327   // see header file for class documentation
328   HLTLogKeyword("task list");
329   TObjLink *lnk = NULL;
330   HLTMessage("Task List");
331   lnk=fTaskList.FirstLink();
332   while (lnk) {
333     TObject* obj=lnk->GetObject();
334     if (obj) {
335       HLTMessage("  %s - status:", obj->GetName());
336       AliHLTTask* pTask=(AliHLTTask*)obj;
337       pTask->PrintStatus();
338     } else {
339     }
340     lnk = lnk->Next();
341   }
342 }
343
344 int AliHLTSystem::Run(Int_t iNofEvents, int bStop, AliHLTUInt64_t trgMask,
345                       AliHLTUInt32_t timestamp, AliHLTUInt32_t eventtype,
346                       AliHLTUInt32_t participatingDetectors)
347 {
348   // see header file for class documentation
349   int iResult=0;
350   int iCount=0;
351   SetStatusFlags(kRunning);
352   if (fEventCount>=0 || (iResult=InitTasks())>=0) {
353     if (fEventCount>=0 || (iResult=StartTasks())>=0) {
354       if (fEventCount==0) {
355         InitBenchmarking(fStopwatches);
356       } else {
357         // Matthias Oct 11 2008 this is a bug
358         // By resuming the stopwatches at this point, all continued counting, but the
359         // starting and stopping is controlled by the AliHLTStopwatchGuard
360         //ResumeBenchmarking(fStopwatches);    
361       }
362       for (int i=fEventCount; i<fEventCount+iNofEvents && iResult>=0; i++) {
363         if (fpHLTOUTTask) {
364           if (iNofEvents>1 && i==fEventCount) {
365             HLTWarning("can not add more than one event to the HLTOUT, skipping all but last block");
366           }
367           // reset and prepare for new data
368           fpHLTOUTTask->Reset();
369         }
370         if (eventtype == 0) {
371           eventtype = gkAliEventTypeData;
372           participatingDetectors = 0x0;
373         }
374         if ((iResult=ProcessTasks(i, trgMask, timestamp, eventtype, participatingDetectors))>=0) {
375           fGoodEvents++;
376           iCount++;
377         } else {
378           // TODO: define different running modes to either ignore errors in
379           // event processing or not
380           // currently ignored 
381           iResult=0;
382         }
383         AliHLTDataBuffer::SetGlobalEventCount(iCount);
384       }
385       fEventCount+=iNofEvents;
386       if (bStop) StopTasks();
387       else PauseBenchmarking(fStopwatches);
388     }
389     if (bStop) DeinitTasks();
390   }
391   if (iResult>=0) {
392     iResult=iCount;
393   } else  if (iResult==-126 /*ENOKEY*/) {
394     iResult=0; // do not propagate the error
395   }
396   ClearStatusFlags(kRunning);
397   AliHLTDataBuffer::PrintStatistics();
398   return iResult;
399 }
400
401 int AliHLTSystem::InitTasks()
402 {
403   // see header file for class documentation
404   int iResult=0;
405   TObjLink *lnk=fTaskList.FirstLink();
406
407   if (lnk==NULL) {
408     HLTInfo("Task list is empty, skipping HLT");
409     return -126 /*ENOKEY*/;
410   }
411   while (lnk && iResult>=0) {
412     TObject* obj=lnk->GetObject();
413     if (obj) {
414       AliHLTTask* pTask=(AliHLTTask*)obj;
415       iResult=pTask->Init(NULL, fpComponentHandler);
416 //       ProcInfo_t ProcInfo;
417 //       gSystem->GetProcInfo(&ProcInfo);
418 //       HLTInfo("task %s initialized (%d), current memory usage %d %d", pTask->GetName(), iResult, ProcInfo.fMemResident, ProcInfo.fMemVirtual);
419     } else {
420     }
421     lnk = lnk->Next();
422   }
423   if (iResult<0) {
424     HLTError("can not initialize task list, error %d", iResult);
425   }
426
427   return iResult;
428 }
429
430 int AliHLTSystem::InitBenchmarking(TObjArray* pStopwatches)
431 {
432   // see header file for class documentation
433   int iResult=0;
434   if (pStopwatches==NULL) return 0;
435
436   for (int i=0; i<(int)AliHLTComponent::kSWTypeCount; i++) {
437     TStopwatch* pStopwatch= new TStopwatch;
438     if (pStopwatch) {
439       pStopwatch->Reset();
440       pStopwatches->AddAt(pStopwatch, i);
441     } else {
442       iResult=-ENOMEM;
443       break;
444     }
445   }
446
447   TObjLink *lnk=fTaskList.FirstLink();
448   while (lnk && iResult>=0) {
449     TObject* obj=lnk->GetObject();
450     if (obj) {
451       AliHLTTask* pTask=(AliHLTTask*)obj;
452       AliHLTComponent* pComp=NULL;
453       if (iResult>=0 && (pComp=pTask->GetComponent())!=NULL) {
454         switch (pComp->GetComponentType()) {
455         case AliHLTComponent::kProcessor:
456           pComp->SetStopwatches(pStopwatches);
457           break;
458         case AliHLTComponent::kSource:
459           {
460             // this switch determines whether the time consumption of the
461             // AliHLTComponent base methods should be counted to the input
462             // stopwatch or base stopwatch.
463             //int inputBase=(int)AliHLTComponent::kSWBase;
464             int inputBase=(int)AliHLTComponent::kSWInput;
465             pComp->SetStopwatch(pStopwatches->At(inputBase), AliHLTComponent::kSWBase);
466             pComp->SetStopwatch(pStopwatches->At((int)AliHLTComponent::kSWInput), AliHLTComponent::kSWDA);
467           }
468           break;
469         case AliHLTComponent::kSink:
470           {
471             // this switch determines whether the time consumption of the
472             // AliHLTComponent base methods should be counted to the output
473             // stopwatch or base stopwatch.
474             //int outputBase=(int)AliHLTComponent::kSWBase;
475             int outputBase=(int)AliHLTComponent::kSWOutput;
476             pComp->SetStopwatch(pStopwatches->At(outputBase), AliHLTComponent::kSWBase);
477             pComp->SetStopwatch(pStopwatches->At((int)AliHLTComponent::kSWOutput), AliHLTComponent::kSWDA);
478           }
479           break;
480         default:
481           HLTWarning("unknown component type %d", (int)pComp->GetComponentType());
482         }
483       }
484     } else {
485     }
486     lnk = lnk->Next();
487   }
488   return iResult;
489 }
490
491 int AliHLTSystem::PauseBenchmarking(TObjArray* pStopwatches) const
492 {
493   // see header file for class documentation
494   if (pStopwatches==NULL) return 0;
495
496   for (int i=0; i<(int)AliHLTComponent::kSWTypeCount; i++) {
497     if (!pStopwatches->At(i)) continue;
498     TStopwatch* pSw=dynamic_cast<TStopwatch*>(pStopwatches->At(i));
499     if (pSw) pSw->Stop();
500   }
501   return 0;
502 }
503
504 int AliHLTSystem::ResumeBenchmarking(TObjArray* pStopwatches) const
505 {
506   // see header file for class documentation
507   if (pStopwatches==NULL) return 0;
508
509   for (int i=0; i<(int)AliHLTComponent::kSWTypeCount; i++) {
510     if (!pStopwatches->At(i)) continue;
511     TStopwatch* pSw=dynamic_cast<TStopwatch*>(pStopwatches->At(i));
512     if (pSw) pSw->Continue();
513   }
514   return 0;
515 }
516
517 int AliHLTSystem::PrintBenchmarking(TObjArray* pStopwatches, int bClean) const
518 {
519   // see header file for class documentation
520   int iInitialized=1;
521   if (pStopwatches==NULL) return 0;
522
523   for (int i=0; i<(int)AliHLTComponent::kSWTypeCount; i++) {
524     if (!dynamic_cast<TStopwatch*>(pStopwatches->At(i))) {
525       iInitialized=0;
526       break;
527     }
528   }
529
530   if (iInitialized!=0) {
531     HLTImportant("HLT statistics:\n"
532             "    base:              R:%.3fs C:%.3fs\n"
533             "    input:             R:%.3fs C:%.3fs\n"
534             "    output:            R:%.3fs C:%.3fs\n"
535             "    event processing : R:%.3fs C:%.3fs"
536             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWBase))->RealTime()
537             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWBase))->CpuTime()
538             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWInput))->RealTime()
539             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWInput))->CpuTime()
540             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWOutput))->RealTime()
541             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWOutput))->CpuTime()
542             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWDA))->RealTime()
543             , dynamic_cast<TStopwatch*>(pStopwatches->At(AliHLTComponent::kSWDA))->CpuTime()
544             );
545   }
546
547   if (bClean) {
548     for (int i=0; i<(int)AliHLTComponent::kSWTypeCount; i++) {
549       TObject* pObj=pStopwatches->RemoveAt(i);
550       if (pObj) delete pObj;
551     }
552   }
553   return 0;
554 }
555
556 int AliHLTSystem::StartTasks()
557 {
558   // see header file for class documentation
559   int iResult=0;
560   TObjLink *lnk=fTaskList.FirstLink();
561   while (lnk && iResult>=0) {
562     TObject* obj=lnk->GetObject();
563     if (obj) {
564       AliHLTTask* pTask=(AliHLTTask*)obj;
565       iResult=pTask->StartRun();
566 //       ProcInfo_t ProcInfo;
567 //       gSystem->GetProcInfo(&ProcInfo);
568 //       HLTInfo("task %s started (%d), current memory usage %d %d", pTask->GetName(), iResult, ProcInfo.fMemResident, ProcInfo.fMemVirtual);
569     } else {
570     }
571     lnk = lnk->Next();
572   }
573   if (iResult<0) {
574     HLTError("can not start task list, error %d", iResult);
575   } else {
576     SetStatusFlags(kStarted);
577     fEventCount=0;
578     fGoodEvents=0;
579     if ((iResult=SendControlEvent(kAliHLTDataTypeSOR))<0) {
580       HLTError("can not send SOR event: error %d", iResult);
581     }
582   }
583   return iResult;
584 }
585
586 int AliHLTSystem::ProcessTasks(Int_t eventNo, AliHLTUInt64_t trgMask,
587           AliHLTUInt32_t timestamp, AliHLTUInt32_t eventtype,
588           AliHLTUInt32_t participatingDetectors)
589 {
590   // see header file for class documentation
591   int iResult=0;
592   HLTDebug("processing event no %d", eventNo);
593   TObjLink *lnk=fTaskList.FirstLink();
594   while (lnk && iResult>=0) {
595     TObject* obj=lnk->GetObject();
596     if (obj) {
597       AliHLTTask* pTask=(AliHLTTask*)obj;
598       iResult=pTask->ProcessTask(eventNo, eventtype, trgMask, timestamp, participatingDetectors);
599 //       ProcInfo_t ProcInfo;
600 //       gSystem->GetProcInfo(&ProcInfo);
601 //       HLTInfo("task %s processed (%d), current memory usage %d %d", pTask->GetName(), iResult, ProcInfo.fMemResident, ProcInfo.fMemVirtual);
602     } else {
603     }
604     lnk = lnk->Next();
605   }
606
607   if (iResult>=0) {
608     HLTImportant("Event %d successfully finished (%d)", eventNo, iResult);
609     iResult=0;
610   } else {
611     HLTError("Processing of event %d failed (%d)", eventNo, iResult);
612   }
613
614   return iResult;
615 }
616
617 int AliHLTSystem::StopTasks()
618 {
619   // see header file for class documentation
620   int iResult=0;
621   if ((iResult=SendControlEvent(kAliHLTDataTypeEOR))<0) {
622     HLTError("can not send EOR event");
623   }
624
625   // cleanup blocks from the last event. This is a bit awkward. All output
626   // blocks from the chains need to be stored in the HLTOUT task. Though,
627   // we do not know, whether HLTOUT is going to be processed or not.
628   if (fpHLTOUTTask)
629     fpHLTOUTTask->Reset();
630
631   TObjLink *lnk=fTaskList.FirstLink();
632   while (lnk) {
633     TObject* obj=lnk->GetObject();
634     if (obj) {
635       AliHLTTask* pTask=(AliHLTTask*)obj;
636       int locResult=pTask->EndRun();
637       if (iResult>=0 && locResult<0) iResult=locResult;
638 //       ProcInfo_t ProcInfo;
639 //       gSystem->GetProcInfo(&ProcInfo);
640 //       HLTInfo("task %s stopped (%d), current memory usage %d %d", pTask->GetName(), iResult, ProcInfo.fMemResident, ProcInfo.fMemVirtual);
641     } else {
642     }
643     lnk = lnk->Next();
644   }
645   PrintBenchmarking(fStopwatches, 1 /*clean*/);
646   ClearStatusFlags(kStarted);
647   return iResult;
648 }
649
650 int AliHLTSystem::SendControlEvent(AliHLTComponentDataType dt)
651 {
652   // see header file for class documentation
653   int iResult=0;
654
655   AliHLTComponentBlockDataList controlBlocks;
656   AliHLTComponentBlockData bd;
657
658   // run decriptor block of type kAliHLTDataTypeSOR/kAliHLTDataTypeEOR 
659   AliHLTComponent::FillBlockData(bd);
660   AliHLTRunDesc runDesc;
661   memset(&runDesc, 0, sizeof(AliHLTRunDesc));
662   runDesc.fStructSize=sizeof(AliHLTRunDesc);
663   runDesc.fRunNo=AliHLTMisc::Instance().GetCDBRunNo();
664   bd.fPtr=&runDesc;
665   bd.fSize=sizeof(AliHLTRunDesc);
666   bd.fDataType=dt;
667   bd.fSpecification=kAliHLTVoidDataSpec;
668   controlBlocks.push_back(bd);
669
670   // ECS parameter of type kAliHLTDataTypeECSParam
671   if (fECSParams.IsNull())
672     fECSParams="CTP_TRIGGER_CLASS=00:DUMMY-TRIGGER-ALL:00-01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17";
673   AliHLTComponent::FillBlockData(bd);
674   bd.fPtr=(void*)fECSParams.Data();
675   bd.fSize=fECSParams.Length()+1;
676   bd.fDataType=kAliHLTDataTypeECSParam;
677   bd.fSpecification=kAliHLTVoidDataSpec;
678   controlBlocks.push_back(bd);  
679
680   AliHLTControlTask::AliHLTControlEventGuard g(fpControlTask, controlBlocks);
681   HLTDebug("sending event %s, run descriptor %p", AliHLTComponent::DataType2Text(dt).c_str(), &runDesc);
682   TObjLink *lnk=fTaskList.FirstLink();
683   while (lnk && iResult>=0) {
684     TObject* obj=lnk->GetObject();
685     if (obj) {
686       AliHLTTask* pTask=(AliHLTTask*)obj;
687       AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
688       if (dt==kAliHLTDataTypeSOR) eventType=gkAliEventTypeStartOfRun;
689       else if (dt==kAliHLTDataTypeEOR) eventType=gkAliEventTypeEndOfRun;
690       else HLTWarning("unknown control event %s", AliHLTComponent::DataType2Text(dt).c_str());
691       iResult=pTask->ProcessTask(-1, eventType, 0, 0);
692     } else {
693     }
694     lnk = lnk->Next();
695   }
696
697   // control events are not supposed to go into the HLTOUT
698   if (fpHLTOUTTask)
699     fpHLTOUTTask->Reset();
700
701   HLTDebug("event %s done (%d)", AliHLTComponent::DataType2Text(dt).c_str(), iResult);
702   return iResult;
703 }
704
705 int AliHLTSystem::DeinitTasks()
706 {
707   // see header file for class documentation
708   int iResult=0;
709   TObjLink *lnk=fTaskList.LastLink();
710   while (lnk) {
711     TObject* obj=lnk->GetObject();
712     if (obj) {
713       AliHLTTask* pTask=(AliHLTTask*)obj;
714       int localRes=pTask->Deinit();
715       if (iResult>=0) iResult=localRes;
716 //       ProcInfo_t ProcInfo;
717 //       gSystem->GetProcInfo(&ProcInfo);
718 //       HLTInfo("task %s cleaned (%d), current memory usage %d %d", pTask->GetName(), iResult, ProcInfo.fMemResident, ProcInfo.fMemVirtual);
719     } else {
720     }
721     lnk = lnk->Prev();
722   }
723   fEventCount=-1;
724   fGoodEvents=-1;
725
726   return iResult;
727 }
728
729 int AliHLTSystem::CleanHLTOUT()
730 {
731   // see header file for class documentation
732   if (fpChainHandlers) {
733     AliHLTOUT::AliHLTOUTHandlerListEntryVector* pHandlers=reinterpret_cast<AliHLTOUT::AliHLTOUTHandlerListEntryVector*>(fpChainHandlers);
734     fpChainHandlers=NULL;
735     if (pHandlers) {
736       AliHLTOUT::InvalidateBlocks(*pHandlers);
737       AliHLTOUT::RemoveEmptyDuplicateHandlers(*pHandlers);
738     }
739     assert(pHandlers->size()==0);
740     delete pHandlers;
741   }
742
743   if (fpEsdHandlers) {
744     AliHLTOUT::AliHLTOUTHandlerListEntryVector* pHandlers=reinterpret_cast<AliHLTOUT::AliHLTOUTHandlerListEntryVector*>(fpEsdHandlers);
745     fpEsdHandlers=NULL;
746     if (pHandlers) {
747       AliHLTOUT::InvalidateBlocks(*pHandlers);
748       AliHLTOUT::RemoveEmptyDuplicateHandlers(*pHandlers);
749     }
750     assert(pHandlers->size()==0);
751     delete pHandlers;
752   }
753
754   if (fpProprietaryHandlers) {
755     AliHLTOUT::AliHLTOUTHandlerListEntryVector* pHandlers=reinterpret_cast<AliHLTOUT::AliHLTOUTHandlerListEntryVector*>(fpProprietaryHandlers);
756     fpProprietaryHandlers=NULL;
757     if (pHandlers) {
758       AliHLTOUT::InvalidateBlocks(*pHandlers);
759       AliHLTOUT::RemoveEmptyDuplicateHandlers(*pHandlers);
760     }
761     assert(pHandlers->size()==0);
762     delete pHandlers;
763   }
764   return 0;
765 }
766
767 void* AliHLTSystem::AllocMemory( void* /*param*/, unsigned long size )
768 {
769   // see header file for class documentation
770   void* p=NULL;
771   try {
772     p=(void*)new char[size];
773   }
774   catch (...) {
775     AliHLTLogging log;
776     log.LoggingVarargs(kHLTLogError, "AliHLTSystem" , "AllocMemory" , __FILE__ , __LINE__ , "exeption during memory allocation" );
777   }
778   return p;
779 }
780
781 int AliHLTSystem::AllocEventDoneData( void* /*param*/, AliHLTEventID_t /*eventID*/, unsigned long size, AliHLTComponentEventDoneData** edd )
782 {
783   // see header file for class documentation
784   unsigned long blocksize=sizeof(AliHLTComponentEventDoneData)+size;
785   void* block=AllocMemory(NULL, blocksize);
786   if (!block) return -ENOMEM;
787   memset(block, 0, blocksize);
788   *edd=reinterpret_cast<AliHLTComponentEventDoneData*>(block);
789   (*edd)->fStructSize=sizeof(AliHLTComponentEventDoneData);
790   (*edd)->fDataSize=size;
791   (*edd)->fData=reinterpret_cast<AliHLTUInt8_t*>(block)+sizeof(AliHLTComponentEventDoneData);
792   
793   return 0;
794 }
795
796 int AliHLTSystem::Reconstruct(int nofEvents, AliRunLoader* runLoader, 
797                               AliRawReader* rawReader)
798 {
799   // see header file for class documentation
800   int iResult=0;
801   if (runLoader || rawReader || nofEvents==0) {
802     if (nofEvents>0) {HLTInfo("Run Loader %p, Raw Reader %p , %d event(s)", runLoader, rawReader, nofEvents);}
803     if (CheckStatus(kReady)) {
804       if (nofEvents==0) {
805         // special case to close the reconstruction
806         if (!CheckStatus(kError)) {
807         StopTasks();
808         DeinitTasks();
809         CleanHLTOUT();
810         }
811       } else {
812       if ((iResult=AliHLTOfflineInterface::SetParamsToComponents(runLoader, rawReader))>=0) {
813         AliHLTUInt64_t trgMask=0x1;
814         AliHLTUInt32_t timestamp=0;
815         AliHLTUInt32_t eventtype=0;
816         if (runLoader==NULL) {
817           // this is a quick workaround for the case of simulation
818           // the trigger framework is still under development, secondly, AliHLTSimulation
819           // does not yet add the emulated ECS parameters, so no CTP trigger is known in the HLT
820           // AliHLTTask will initialize one dummy CTP trigger class with bit 0, that's why the
821           // default trigger mask is 0x1
822           trgMask=AliHLTMisc::Instance().GetTriggerMask(rawReader);
823
824           // get the timestamp and type of the event from the raw reader
825           // this is currently only meaningfull for reconstruction (runloader==NULL)
826           timestamp=AliHLTMisc::Instance().GetTimeStamp(rawReader);
827           eventtype=AliHLTMisc::Instance().GetEventType(rawReader);
828         }
829         // the system always remains started after event processing, a specific
830         // call with nofEvents==0 is needed to execute the stop sequence
831         if ((iResult=Run(nofEvents, 0, trgMask, timestamp, eventtype))<0) SetStatusFlags(kError);
832       }
833       }
834     } else {
835       HLTError("wrong state %#x, required flags %#x", GetStatusFlags(), kReady);
836     }
837   } else {
838     HLTError("missing RunLoader (%p)/RawReader (%p) instance", runLoader, rawReader);
839     iResult=-EINVAL;
840   }
841   return iResult;
842 }
843
844 int AliHLTSystem::FillESD(int eventNo, AliRunLoader* runLoader, AliESDEvent* esd)
845 {
846   // see header file for class documentation
847   int iResult=0;
848   if (runLoader || esd) {
849     HLTInfo("Event %d: Run Loader %p, ESD %p", eventNo, runLoader, esd);
850     iResult=AliHLTOfflineInterface::FillComponentESDs(eventNo, runLoader, esd);
851   } else {
852     HLTError("missing run loader/ESD instance(s)");
853     iResult=-EINVAL;
854   }
855   return iResult;
856 }
857
858 int AliHLTSystem::ProcessHLTOUT(AliHLTOUT* pHLTOUT, AliESDEvent* esd)
859 {
860   // see header file for class documentation
861   int iResult=0;
862   if (!pHLTOUT) return -EINVAL;
863   HLTDebug("processing %d HLT data blocks", pHLTOUT->GetNofDataBlocks());
864
865   // add the current HLTOUT task to the collection
866   if (fpHLTOUTTask) {
867     AliHLTOUT* pTask=dynamic_cast<AliHLTOUT*>(fpHLTOUTTask);
868     if (pTask && (iResult=pTask->Init())>=0) {
869       if (pTask->GetNofDataBlocks()>0) {
870         pHLTOUT->AddSubCollection(pTask);
871       }
872     } else {
873       HLTWarning("can not initialize HLTOUT sub collection %s for reconstruction chain (%d), data blocks are lost", pTask?fpHLTOUTTask->GetName():"nil", iResult);
874       iResult=0;
875     }
876   }
877
878   
879   //
880   // process all kChain handlers first
881   //
882   if ((iResult=ProcessHLTOUTkChain(pHLTOUT))<0) {
883     HLTWarning("Processing of kChain-type data blocks failed with error code %d", iResult);
884     iResult=0;
885   } 
886
887   if (!fpEsdHandlers)
888     fpEsdHandlers=new AliHLTOUT::AliHLTOUTHandlerListEntryVector;
889   if (!fpProprietaryHandlers)
890     fpProprietaryHandlers=new AliHLTOUT::AliHLTOUTHandlerListEntryVector;
891
892   AliHLTOUT::AliHLTOUTHandlerListEntryVector* pEsdHandlers=reinterpret_cast<AliHLTOUT::AliHLTOUTHandlerListEntryVector*>(fpEsdHandlers);
893   AliHLTOUT::AliHLTOUTHandlerListEntryVector* pProprietaryHandlers=reinterpret_cast<AliHLTOUT::AliHLTOUTHandlerListEntryVector*>(fpProprietaryHandlers);
894   if (!pEsdHandlers || !pProprietaryHandlers) return -ENOMEM;
895
896   // invalidate all blocks
897   AliHLTOUT::InvalidateBlocks(*pEsdHandlers);
898   AliHLTOUT::InvalidateBlocks(*pProprietaryHandlers);
899
900   AliHLTComponentDataTypeList esdBlocks;
901
902   for (iResult=pHLTOUT->SelectFirstDataBlock();
903        iResult>=0;
904        iResult=pHLTOUT->SelectNextDataBlock()) {
905     AliHLTComponentDataType dt=kAliHLTVoidDataType;
906     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
907     pHLTOUT->GetDataBlockDescription(dt, spec);
908     AliHLTOUTHandler* pHandler=pHLTOUT->GetHandler();
909     AliHLTModuleAgent::AliHLTOUTHandlerType handlerType=pHLTOUT->GetDataBlockHandlerType();
910
911     // default handling for ESD data blocks does not require an explicite handler
912     if (!pHandler && (dt==kAliHLTDataTypeESDObject || dt==kAliHLTDataTypeESDTree)) {
913       handlerType=AliHLTModuleAgent::kEsd;
914     }
915     const char* pMsg="invalid";
916     switch (handlerType) {
917     case AliHLTModuleAgent::kEsd:
918       {
919         if (pHandler) {
920           // schedule for later processing
921           pHLTOUT->InsertHandler(*pEsdHandlers, pHLTOUT->GetDataBlockHandlerDesc());
922         } else {
923           AliHLTComponentDataTypeList::iterator element=esdBlocks.begin();
924           for (; element!=esdBlocks.end(); element++) {
925             if (*element==dt) {
926               HLTWarning("multiple ESDs of identical data type %s, please add appropriate handler to merge ESDs", AliHLTComponent::DataType2Text(dt).c_str());
927               break;
928             }
929           }
930           if (element==esdBlocks.end()) esdBlocks.push_back(dt);
931
932           // write directly
933           const AliHLTUInt8_t* pBuffer=NULL;
934           AliHLTUInt32_t size=0;
935           if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
936             pHLTOUT->WriteESD(pBuffer, size, dt, esd);
937             pHLTOUT->ReleaseDataBuffer(pBuffer);
938           }
939           pHLTOUT->MarkDataBlockProcessed();
940         }
941       }
942       break;
943     case AliHLTModuleAgent::kRawReader:
944       // handled in the AliRawReaderHLT
945       break;
946     case AliHLTModuleAgent::kRawStream:
947       HLTWarning("HLTOUT handler type 'kRawStream' not yet implemented: agent %s, data type %s, specification %#x",
948                  pHLTOUT->GetAgent()?pHLTOUT->GetAgent()->GetModuleId():"<invalid>",
949                  AliHLTComponent::DataType2Text(dt).c_str(), spec);
950       break;
951     case AliHLTModuleAgent::kChain:
952       HLTWarning("HLTOUT handler type 'kChain' has already been processed: agent %s, data type %s, specification %#x\n"
953                  "New block of this type added by the chain? Skipping data block ...",
954                  pHLTOUT->GetAgent()?pHLTOUT->GetAgent()->GetModuleId():"<invalid>",
955                  AliHLTComponent::DataType2Text(dt).c_str(), spec);
956       break;
957     case AliHLTModuleAgent::kProprietary:
958       HLTDebug("processing proprietary data: agent %s, data type %s, specification %#x",
959                  pHLTOUT->GetAgent()?pHLTOUT->GetAgent()->GetModuleId():"<invalid>",
960                  AliHLTComponent::DataType2Text(dt).c_str(), spec);
961       if (pHandler) {
962         AliHLTOUT::AliHLTOUTLockGuard g(pHLTOUT);
963         int res=pHandler->ProcessData(pHLTOUT);
964         if (res<0) {
965           HLTWarning("processing proprietary data failed (%d): agent %s, data type %s, specification %#x",
966                      res, pHLTOUT->GetAgent()?pHLTOUT->GetAgent()->GetModuleId():"<invalid>",
967                      AliHLTComponent::DataType2Text(dt).c_str(), spec);
968         }
969       }
970       break;
971     case AliHLTModuleAgent::kUnknownOutput:
972       pMsg="unknown";
973       // fall trough intended
974     default:
975       HLTWarning("%s handler type: agent %s, data type %s, specification %#x, ... skipping data block",
976                  pMsg, pHLTOUT->GetAgent()?pHLTOUT->GetAgent()->GetModuleId():"<invalid>",
977                  AliHLTComponent::DataType2Text(dt).c_str(), spec);
978     }
979   }
980   // TODO: the return value of SelectFirst/NextDataBlock must be
981   // changed in order to avoid this check
982   if (iResult==-ENOENT) iResult=0;
983
984   AliHLTOUT::AliHLTOUTHandlerListEntryVector::iterator handler;
985
986   // process and write all esd data blocks
987   for (handler=pEsdHandlers->begin(); handler!=pEsdHandlers->end() && iResult>=0; handler++) {
988     AliHLTOUT::AliHLTOUTSelectionGuard g(pHLTOUT, &(*handler));     
989     AliHLTOUTHandler* pHandler=*handler;
990     const AliHLTUInt8_t* pBuffer=NULL;
991     AliHLTUInt32_t size=0;
992     pHandler->ProcessData(pHLTOUT);
993     if ((size=pHandler->GetProcessedData(pBuffer))>0) {
994       AliHLTModuleAgent::AliHLTOUTHandlerDesc desc=*handler;
995       AliHLTComponentDataType dt=desc;
996       pHLTOUT->WriteESD(pBuffer, size, dt, esd);
997       pHandler->ReleaseProcessedData(pBuffer, size);
998     }
999     pHLTOUT->MarkDataBlocksProcessed(&(*handler));
1000   }
1001
1002   // process all kProprietary data blocks
1003   for (handler=pProprietaryHandlers->begin(); handler!=pProprietaryHandlers->end() && iResult>=0; handler++) {
1004     AliHLTOUT::AliHLTOUTSelectionGuard g(pHLTOUT, &(*handler));     
1005     AliHLTOUTHandler* pHandler=*handler;
1006     const AliHLTUInt8_t* pBuffer=NULL;
1007     AliHLTUInt32_t size=0;
1008     pHandler->ProcessData(pHLTOUT);
1009     if ((size=pHandler->GetProcessedData(pBuffer))>0) {
1010       HLTWarning("data produced by kProprietary handler ignored");
1011       pHandler->ReleaseProcessedData(pBuffer, size);
1012     }
1013     pHLTOUT->MarkDataBlocksProcessed(&(*handler));
1014   }
1015
1016   // remove all empty handlers form the list (handlers which did not get a block this time)
1017   AliHLTOUT::RemoveEmptyDuplicateHandlers(*pEsdHandlers);
1018   AliHLTOUT::RemoveEmptyDuplicateHandlers(*pProprietaryHandlers);
1019
1020   return iResult;
1021 }
1022
1023 int AliHLTSystem::ProcessHLTOUTkChain(AliHLTOUT* pHLTOUT)
1024 {
1025   // see header file for class documentation
1026   int iResult=0;
1027   if (!pHLTOUT) return -EINVAL;
1028
1029   if (!fpChainHandlers)
1030     fpChainHandlers=new AliHLTOUT::AliHLTOUTHandlerListEntryVector;
1031
1032   AliHLTOUT::AliHLTOUTHandlerListEntryVector* pChainHandlers=reinterpret_cast<AliHLTOUT::AliHLTOUTHandlerListEntryVector*>(fpChainHandlers);
1033   if (!pChainHandlers) return -ENOMEM;
1034
1035   // invalidate all blocks
1036   AliHLTOUT::InvalidateBlocks(*pChainHandlers);
1037
1038   // fill the list
1039   pHLTOUT->FillHandlerList(*pChainHandlers, AliHLTModuleAgent::kChain);
1040
1041   // process all defined chain handlers
1042   AliHLTOUT::AliHLTOUTHandlerListEntryVector::iterator chainHandler;
1043   for (chainHandler=pChainHandlers->begin(); chainHandler!=pChainHandlers->end() && iResult>=0; chainHandler++) {
1044     if (chainHandler->IsEmpty()) continue;
1045     AliHLTOUT::AliHLTOUTSelectionGuard g(pHLTOUT, &(*chainHandler));        
1046     AliHLTOUTHandler* pHandler=*chainHandler;
1047     const AliHLTUInt8_t* pBuffer=NULL;
1048     AliHLTUInt32_t size=0;
1049     pHandler->ProcessData(pHLTOUT);
1050     if ((size=pHandler->GetProcessedData(pBuffer))>0) {
1051       AliHLTModuleAgent::AliHLTOUTHandlerDesc desc=*chainHandler;
1052       //AliHLTComponentDataType dt=desc;
1053
1054       pHandler->ReleaseProcessedData(pBuffer, size);
1055     }
1056     pHLTOUT->MarkDataBlocksProcessed(&(*chainHandler));
1057   }
1058
1059   // remove all empty handlers form the list (handlers which did not get a block this time)
1060   AliHLTOUT::RemoveEmptyDuplicateHandlers(*pChainHandlers);
1061
1062   return iResult;
1063 }
1064
1065 int AliHLTSystem::LoadComponentLibraries(const char* libraries)
1066 {
1067   // see header file for class documentation
1068   int iResult=0;
1069   if (libraries) {
1070     if (fpComponentHandler) {
1071       TString libs(libraries);
1072       TObjArray* pTokens=libs.Tokenize(" ");
1073       if (pTokens) {
1074         int iEntries=pTokens->GetEntriesFast();
1075         for (int i=0; i<iEntries && iResult>=0; i++) {
1076           iResult=fpComponentHandler->LoadLibrary((((TObjString*)pTokens->At(i))->GetString()).Data());
1077         }
1078         delete pTokens;
1079       }
1080       if (iResult>=0) {
1081         SetStatusFlags(kLibrariesLoaded);
1082       } else {
1083         // lets see if we need this, probably not
1084         //fpComponentHandler->UnloadLibraries();
1085         ClearStatusFlags(kLibrariesLoaded);
1086       }
1087     } else {
1088       iResult=-EFAULT;
1089       HLTFatal("no component handler available");
1090     }
1091   } else {
1092     iResult=-EINVAL;
1093   }
1094   return iResult;
1095 }
1096
1097 int AliHLTSystem::Configure(AliRunLoader* runloader)
1098 {
1099   // see header file for class documentation
1100   return Configure(NULL, runloader);
1101 }
1102
1103 int AliHLTSystem::Configure(AliRawReader* rawReader, AliRunLoader* runloader)
1104 {
1105   // see header file for class documentation
1106   int iResult=0;
1107   if (CheckStatus(kRunning)) {
1108     HLTError("HLT system in running state, can not configure");
1109     return -EBUSY;
1110   }
1111   ClearStatusFlags(kTaskListCreated);
1112   if (CheckFilter(kHLTLogDebug))
1113     AliHLTModuleAgent::PrintStatus();
1114   if (CheckStatus(kConfigurationLoaded)==0) {
1115     iResult=LoadConfigurations(rawReader, runloader);
1116   } else {
1117     if (fChains.Length()==0) {
1118       HLTError("custom configuration(s) specified, but no configuration to run in local reconstruction, use \'chains=<chain,...>\' option");
1119       iResult=-ENOENT;
1120     }
1121   }
1122   if (iResult>=0) {
1123     SetStatusFlags(kConfigurationLoaded);
1124     if (CheckFilter(kHLTLogDebug))
1125       fpConfigurationHandler->PrintConfigurations();
1126     iResult=BuildTaskListsFromReconstructionChains(rawReader, runloader);
1127     if (iResult>=0) {
1128       SetStatusFlags(kTaskListCreated);
1129     }
1130   }
1131   if (iResult<0) SetStatusFlags(kError);
1132   
1133   return iResult;
1134 }
1135
1136 int AliHLTSystem::ScanOptions(const char* options)
1137 {
1138   // see header file for class documentation
1139   int iResult=0;
1140   if (options) {
1141     //AliHLTComponentHandler::TLibraryMode libMode=AliHLTComponentHandler::kDynamic;
1142     TString libs("");
1143     TString excludelibs("");
1144     TString alloptions(options);
1145     TObjArray* pTokens=alloptions.Tokenize(" ");
1146     if (pTokens) {
1147       int iEntries=pTokens->GetEntriesFast();
1148       for (int i=0; i<iEntries; i++) {
1149         TString token=(((TObjString*)pTokens->At(i))->GetString());
1150         if (token.Contains("loglevel=")) {
1151           TString param=token.ReplaceAll("loglevel=", "");
1152           if (param.IsDigit()) {
1153             SetGlobalLoggingLevel((AliHLTComponentLogSeverity)param.Atoi());
1154           } else if (param.BeginsWith("0x") &&
1155                      param.Replace(0,2,"",0).IsHex()) {
1156             int severity=0;
1157             sscanf(param.Data(),"%x", &severity);
1158             SetGlobalLoggingLevel((AliHLTComponentLogSeverity)severity);
1159           } else {
1160             HLTWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
1161           }
1162         } else if (token.Contains("frameworklog=")) {
1163           TString param=token.ReplaceAll("frameworklog=", "");
1164           if (param.IsDigit()) {
1165             SetFrameworkLog((AliHLTComponentLogSeverity)param.Atoi());
1166           } else if (param.BeginsWith("0x") &&
1167                      param.Replace(0,2,"",0).IsHex()) {
1168             int severity=0;
1169             sscanf(param.Data(),"%x", &severity);
1170             SetFrameworkLog((AliHLTComponentLogSeverity)severity);
1171           } else {
1172             HLTWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
1173           }
1174         } else if (token.Contains("alilog=off")) {
1175           SwitchAliLog(0);
1176         } else if (token.Contains("config=")) {
1177           TString param=token.ReplaceAll("config=", "");
1178           Int_t error=0;
1179           gROOT->Macro(param.Data(), &error);
1180           if (error==0) {
1181             SetStatusFlags(kConfigurationLoaded);
1182           } else {
1183             HLTError("can not execute macro \'%s\'", param.Data());
1184             iResult=-EBADF;
1185           }
1186         } else if (token.Contains("chains=")) {
1187           TString param=token.ReplaceAll("chains=", "");
1188           fChains=param.ReplaceAll(",", " ");
1189           if (fChains.IsNull()) fChains=" "; // disable all chains
1190         } else if (token.Contains("libmode=")) {
1191           TString param=token.ReplaceAll("libmode=", "");
1192           param.ReplaceAll(",", " ");
1193           if (fpComponentHandler) {
1194             if (param.CompareTo("static")==0) {
1195               fpComponentHandler->SetLibraryMode(AliHLTComponentHandler::kStatic);
1196             } else if (param.CompareTo("dynamic")==0) {
1197               fpComponentHandler->SetLibraryMode(AliHLTComponentHandler::kDynamic);
1198             } else {
1199               HLTWarning("wrong argument for option \'libmode=\', use \'static\' or \'dynamic\'");
1200             }
1201           }
1202         } else if (token.BeginsWith("ECS=")) {
1203           fECSParams=token.ReplaceAll("ECS=", "");
1204         } else if (token.BeginsWith("lib") && token.EndsWith(".so")) {
1205           libs+=token;
1206           libs+=" ";
1207         } else if (token.BeginsWith("!lib") && token.EndsWith(".so")) {
1208           excludelibs+=token;
1209           excludelibs+=" ";
1210         } else {
1211           HLTWarning("unknown option \'%s\'", token.Data());
1212         }
1213       }
1214       delete pTokens;
1215     }
1216
1217     if (iResult>=0) {
1218       if (libs.IsNull()) {
1219         const char** deflib=fgkHLTDefaultLibs;
1220         for (;*deflib; deflib++) {
1221           if (excludelibs.Contains(*deflib)) continue;
1222           libs+=*deflib;
1223           libs+=" ";
1224         }
1225       }
1226       if ((!CheckStatus(AliHLTSystem::kLibrariesLoaded)) &&
1227           (LoadComponentLibraries(libs.Data())<0)) {
1228         HLTError("error while loading HLT libraries");
1229         iResult=-EFAULT;
1230       }
1231     }
1232   }
1233   return iResult;
1234 }
1235
1236 int AliHLTSystem::Reset(int bForce)
1237 {
1238   // see header file for class documentation
1239   int iResult=0;
1240   if (!bForce && CheckStatus(kRunning)) {
1241     HLTError("HLT system in running state, can not configure");
1242     return -EBUSY;
1243   }
1244   CleanTaskList();
1245   ClearStatusFlags(~kUninitialized);
1246   return iResult;
1247 }
1248
1249 int AliHLTSystem::LoadConfigurations(AliRawReader* rawReader, AliRunLoader* runloader)
1250 {
1251   // see header file for class documentation
1252   if (CheckStatus(kRunning)) {
1253     HLTError("HLT system in running state, can not configure");
1254     return -EBUSY;
1255   }
1256   int iResult=0;
1257   AliHLTModuleAgent* pAgent=NULL;
1258
1259   // first check for the required libraries and load those
1260   TString extralibs;
1261   for (pAgent=AliHLTModuleAgent::GetFirstAgent(); 
1262        pAgent && iResult>=0;
1263        pAgent=AliHLTModuleAgent::GetNextAgent()) {
1264     const char* deplibs=pAgent->GetRequiredComponentLibraries();
1265     if (deplibs) {
1266       HLTDebug("required libraries \'%s\' for agent %s (%p)", deplibs, pAgent->GetName(), pAgent);
1267       extralibs+=" ";
1268       extralibs+=deplibs;
1269     }
1270   }
1271   if (iResult>=0) {
1272     iResult=LoadComponentLibraries(extralibs.Data());
1273   }
1274
1275   // in order to register the configurations in the correct sequence
1276   // all agents need to be ordered with respect to the required
1277   // libraries. Ordering relies on the naming convention
1278   // libAliHLT<Module>.so
1279   TList agents;
1280   for (pAgent=AliHLTModuleAgent::GetFirstAgent(); 
1281        pAgent && iResult>=0;
1282        pAgent=AliHLTModuleAgent::GetNextAgent()) {
1283     AliHLTModuleAgent* pPrevDep=NULL;
1284     TString dependencies=pAgent->GetRequiredComponentLibraries();
1285     TObjArray* pTokens=dependencies.Tokenize(" ");
1286     if (pTokens) {
1287       for (int n=0; n<pTokens->GetEntriesFast(); n++) {
1288         TString module=((TObjString*)pTokens->At(n))->GetString();
1289         HLTDebug("  checking %s", module.Data());
1290         module.ReplaceAll("libAliHLT", "");
1291         module.ReplaceAll(".so", "");
1292         
1293         for (AliHLTModuleAgent* pCurrent=dynamic_cast<AliHLTModuleAgent*>(pPrevDep==NULL?agents.First():agents.After(pPrevDep));
1294              pCurrent!=NULL; pCurrent=dynamic_cast<AliHLTModuleAgent*>(agents.After(pCurrent))) {
1295           HLTDebug("    checking %s == %s", module.Data(), pCurrent->GetModuleId());
1296
1297           if (module.CompareTo(pCurrent->GetModuleId())==0) {
1298             pPrevDep=pCurrent;
1299             break;
1300           }
1301         }
1302       }
1303       delete pTokens;
1304     }
1305
1306     if (pPrevDep) {
1307       // insert right after the last dependency
1308       agents.AddAfter(pPrevDep, pAgent);
1309       HLTDebug("insert %s after %s", pAgent->GetModuleId(), pPrevDep->GetModuleId());
1310     } else {
1311       // insert at the beginning
1312       agents.AddFirst(pAgent);
1313       HLTDebug("insert %s at beginning", pAgent->GetModuleId());
1314     }
1315   }
1316
1317   // now we load the configurations
1318   if (agents.GetEntries()) {
1319     TIter next(&agents);
1320     while ((pAgent = dynamic_cast<AliHLTModuleAgent*>(next()))) {
1321       HLTDebug("load configurations for agent %s (%p)", pAgent->GetName(), pAgent);
1322       pAgent->CreateConfigurations(fpConfigurationHandler, rawReader, runloader);
1323     }
1324   }
1325
1326   return iResult;
1327 }
1328
1329 int AliHLTSystem::BuildTaskListsFromReconstructionChains(AliRawReader* rawReader, AliRunLoader* runloader)
1330 {
1331   // see header file for class documentation
1332   if (CheckStatus(kRunning)) {
1333     HLTError("HLT system in running state, can not configure");
1334     return -EBUSY;
1335   }
1336   if (!CheckStatus(kConfigurationLoaded)) {
1337     HLTWarning("configurations not yet loaded");
1338     return 0;
1339   }
1340
1341   int iResult=0;
1342   int bHaveOutput=0;
1343
1344   // query chains
1345   TString chains;
1346   if (fChains.Length()>0) {
1347     chains=fChains;
1348     HLTImportant("custom reconstruction chain: %s", chains.Data());
1349   } else {
1350     AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
1351     while ((pAgent || fChains.Length()>0) && iResult>=0) {
1352       const char* agentchains=pAgent->GetReconstructionChains(rawReader, runloader);
1353       if (agentchains) {
1354         if (!chains.IsNull()) chains+=" ";
1355         chains+=agentchains;
1356         HLTInfo("reconstruction chains for agent %s (%p): %s", pAgent->GetName(), pAgent, agentchains);
1357       }
1358       pAgent=AliHLTModuleAgent::GetNextAgent();
1359     }
1360   }
1361
1362   // build task list for chains
1363   TObjArray* pTokens=chains.Tokenize(" ");
1364   if (pTokens) {
1365     int iEntries=pTokens->GetEntriesFast();
1366     for (int i=0; i<iEntries && iResult>=0; i++) {
1367       const char* pCID=((TObjString*)pTokens->At(i))->GetString().Data();
1368       AliHLTConfiguration* pConf=fpConfigurationHandler->FindConfiguration(pCID);
1369       if (pConf) {
1370         iResult=BuildTaskList(pConf);
1371         if (true) { // condition was deprecated but kept for sake of svn diff
1372           // bHaveOutput variable has to be set for both running modes
1373           // AliHLTSimulation and AliHLTReconstruction
1374           assert(fpComponentHandler!=NULL);
1375           TString cid=pConf->GetComponentID();
1376           if (runloader!=NULL && cid.CompareTo("HLTOUT")==0) {
1377             // remove from the input of a global HLTOUT configuration
1378             chains.ReplaceAll(pCID, "");
1379           } else if (bHaveOutput==0) {
1380             // check whether this configuration produces data output
1381             if ((bHaveOutput=fpComponentHandler->HasOutputData(cid.Data()))<0) {
1382               bHaveOutput=0;
1383               chains.ReplaceAll(pCID, "");
1384             }
1385           }
1386         }
1387       } else {
1388         HLTWarning("can not find configuration %s", pCID);
1389       }
1390     }
1391     delete pTokens;
1392   }
1393
1394   // build HLTOUT for simulation
1395   if (iResult>=0 && runloader) {
1396     if (bHaveOutput) {
1397       // there are components in the chain which produce data which need to be
1398       // piped to an HLTOUT
1399
1400       // add the SchemaEvolutionComponent which analyzes the ROOT objects in
1401       // the output stream
1402       if (fpComponentHandler->FindComponentIndex("ROOTSchemaEvolutionComponent")>=0 ||
1403           fpComponentHandler->LoadLibrary("libAliHLTUtil.so")>=0) {
1404         AliHLTConfiguration schemaevo("_schemaevolution_", "ROOTSchemaEvolutionComponent", 
1405                                       chains.Data(), "-file=HLT.StreamerInfo.root");
1406         iResult=BuildTaskList("_schemaevolution_");
1407       } else {
1408         HLTWarning("can not load libAliHLTUtil.so and ROOTSchemaEvolutionComponent");
1409       }
1410
1411       // add the HLTOUT component
1412       if (fpComponentHandler->FindComponentIndex("HLTOUT")>=0 ||
1413           fpComponentHandler->LoadLibrary("libHLTsim.so")>=0) {
1414         AliHLTConfiguration globalout("_globalout_", "HLTOUT", chains.Data(), NULL);
1415         iResult=BuildTaskList("_globalout_");
1416       } else {
1417         HLTError("can not load libHLTsim.so and HLTOUT component");
1418         iResult=-EFAULT;
1419       }
1420     }
1421   }
1422
1423   // build HLTOUT task for reconstruction
1424   // Matthias 08.07.2008 the rawReader is never set when running embedded into
1425   // AliReconstruction. The system is configured during AliHLTReconstructor::Init
1426   // where the RawReader is not available. It is available in the first invocation
1427   // of Reconstruct.
1428   // 
1429   // That means that policy is slightly changed:
1430   // - if the run loader is available -> AliSimulation
1431   // - no run loader available -> AliReconstruction
1432   if (iResult>=0 && !runloader) {
1433     if (bHaveOutput) {
1434       // there are components in the chain which produce data which need to be
1435       // piped to an HLTOUT sub-collection
1436       if (!fpHLTOUTTask) {
1437         iResult=AddHLTOUTTask(chains.Data());
1438       }
1439     }
1440   }
1441
1442   if (iResult>=0) SetStatusFlags(kTaskListCreated);
1443
1444   return iResult;
1445 }
1446
1447 int AliHLTSystem::AddHLTOUTTask(const char* hltoutchains)
1448 {
1449   // see header file for class documentation
1450   int iResult=0;
1451   if (!hltoutchains || hltoutchains[0]==0) return 0;
1452
1453   // check chains for output
1454   TString chains=hltoutchains;
1455   TObjArray* pTokens=chains.Tokenize(" ");
1456   if (pTokens) {
1457     int iEntries=pTokens->GetEntriesFast();
1458     for (int i=0; i<iEntries && iResult>=0; i++) {
1459       const char* token=((TObjString*)pTokens->At(i))->GetString().Data();
1460       AliHLTConfiguration* pConf=fpConfigurationHandler->FindConfiguration(token);
1461       if (pConf) {
1462         TString cid=pConf->GetComponentID();
1463         if (fpComponentHandler->HasOutputData(cid.Data())) {
1464           continue;
1465         }
1466       } else {
1467         HLTWarning("can not find configuration %s", token);
1468       }
1469       // remove from the list of hltout chains
1470       chains.ReplaceAll(token, "");
1471     }
1472     delete pTokens;
1473   }
1474
1475   // do not create the HLTOUT task if none of the chains have output
1476   if (chains.IsNull()) return 0;
1477
1478   // indicate the task to be available
1479   iResult=1;
1480
1481   if (fpHLTOUTTask) {
1482     if (strcmp(chains.Data(), fpHLTOUTTask->GetSourceChains())==0) {
1483       HLTWarning("HLTOUT task already added for chains \"%s\" %p", chains.Data(), fpHLTOUTTask);
1484     } else {
1485       HLTError("HLTOUT task already added for chains \"%s\" %p, ignoring new chains  \"%s\"",
1486                fpHLTOUTTask->GetSourceChains(), fpHLTOUTTask, chains.Data());
1487     }
1488     return iResult;
1489   }
1490
1491   fpHLTOUTTask=new AliHLTOUTTask(chains);
1492   if (fpHLTOUTTask) {
1493     if (fpHLTOUTTask->GetConf() && fpHLTOUTTask->GetConf()->SourcesResolved()>=0) {
1494       iResult=InsertTask(fpHLTOUTTask);
1495     } else {
1496       HLTError("HLTOUT task (%s) sources not resolved", fpHLTOUTTask->GetName());
1497       iResult=-ENOENT;
1498     }
1499
1500     if (iResult<0) {
1501       delete fpHLTOUTTask;
1502     }
1503
1504   } else {
1505     iResult=-ENOMEM;
1506   }
1507   return iResult;
1508 }
1509
1510 int AliHLTSystem::CheckStatus(int flag)
1511 {
1512   // see header file for class documentation
1513   if (flag==kUninitialized && flag==fState) return 1;
1514   if ((fState&flag)==flag) return 1;
1515   return 0;
1516 }
1517
1518 int AliHLTSystem::GetStatusFlags()
1519 {
1520   // see header file for class documentation
1521   return fState;
1522 }
1523
1524 int AliHLTSystem::SetStatusFlags(int flags)
1525 {
1526   // see header file for class documentation
1527   fState|=flags;
1528   return fState;
1529 }
1530
1531 int AliHLTSystem::ClearStatusFlags(int flags)
1532 {
1533   // see header file for class documentation
1534   fState&=~flags;
1535   return fState;
1536 }
1537
1538 AliHLTfctVoid AliHLTSystem::FindDynamicSymbol(const char* library, const char* symbol)
1539 {
1540   // see header file for class documentation
1541   if (fpComponentHandler==NULL) return NULL;
1542   return fpComponentHandler->FindSymbol(library, symbol);
1543 }
1544
1545 void AliHLTSystem::SetFrameworkLog(AliHLTComponentLogSeverity level) 
1546 {
1547   // see header file for class documentation
1548   SetLocalLoggingLevel(level);
1549   if (fpComponentHandler) fpComponentHandler->SetLocalLoggingLevel(level);
1550   if (fpConfigurationHandler) fpConfigurationHandler->SetLocalLoggingLevel(level);
1551 }
1552
1553 int AliHLTSystem::LoggingVarargs(AliHLTComponentLogSeverity severity, 
1554                                  const char* originClass, const char* originFunc,
1555                                  const char* file, int line, ... ) const
1556 {
1557   // see header file for function documentation
1558   int iResult=0;
1559
1560   va_list args;
1561   va_start(args, line);
1562
1563   if (!fName.IsNull())
1564     AliHLTLogging::SetLogString(this, " (%p)", "%s_pfmt_: ", fName.Data());
1565   iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args, !fName.IsNull() /*append if non empty*/));
1566   va_end(args);
1567
1568   return iResult;
1569 }