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