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