26ce765e53505e8cbdbed5e07336a88c2d34c132
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTSystem.cxx
1 // $Id$
2
3 /**************************************************************************
4  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5  *                                                                        *
6  * Authors: Matthias Richter <Matthias.Richter@ift.uib.no>                *
7  *          for The ALICE Off-line Project.                               *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          *
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 /** @file   AliHLTSystem.cxx
19     @author Matthias Richter
20     @date   
21     @brief  Implementation of HLT module management.
22 */
23
24 #if __GNUC__>= 3
25 using namespace std;
26 #endif
27
28 #include "AliHLTStdIncludes.h"
29 #include "AliHLTSystem.h"
30 #include "AliHLTComponentHandler.h"
31 #include "AliHLTComponent.h"
32 #include "AliHLTConfiguration.h"
33 #include "AliHLTConfigurationHandler.h"
34 #include "AliHLTTask.h"
35 #include "AliHLTModuleAgent.h"
36 #include "AliHLTOfflineInterface.h"
37 #include <TObjArray.h>
38 #include <TObjString.h>
39 #include <TString.h>
40
41 /** ROOT macro for the implementation of ROOT specific class methods */
42 ClassImp(AliHLTSystem)
43
44 AliHLTSystem::AliHLTSystem()
45   :
46   fpComponentHandler(new AliHLTComponentHandler()),
47   fpConfigurationHandler(new AliHLTConfigurationHandler()),
48   fTaskList(),
49   fState(0)
50 {
51   // see header file for class documentation
52   // or
53   // refer to README to build package
54   // or
55   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
56
57   if (fgNofInstances++>0)
58     HLTWarning("multiple instances of AliHLTSystem, you should not use more than one at a time");
59
60   SetGlobalLoggingLevel(kHLTLogDefault);
61   if (fpComponentHandler) {
62     AliHLTComponentEnvironment env;
63     memset(&env, 0, sizeof(AliHLTComponentEnvironment));
64     env.fAllocMemoryFunc=AliHLTSystem::AllocMemory;
65     env.fLoggingFunc=NULL;
66     fpComponentHandler->SetEnvironment(&env);
67   } else {
68     HLTFatal("can not create Component Handler");
69   }
70   if (fpConfigurationHandler) {
71     AliHLTConfiguration::GlobalInit(fpConfigurationHandler);
72   } else {
73     HLTFatal("can not create Configuration Handler");
74   }
75 }
76
77 AliHLTSystem::AliHLTSystem(const AliHLTSystem&)
78   :
79   AliHLTLogging(),
80   fpComponentHandler(NULL),
81   fpConfigurationHandler(NULL),
82   fTaskList(),
83   fState(0)
84 {
85   // see header file for class documentation
86   if (fgNofInstances++>0)
87     HLTWarning("multiple instances of AliHLTSystem, you should not use more than one at a time");
88
89   HLTFatal("copy constructor untested");
90 }
91
92 AliHLTSystem& AliHLTSystem::operator=(const AliHLTSystem&)
93
94   // see header file for class documentation
95   HLTFatal("assignment operator untested");
96   return *this;
97 }
98
99 AliHLTSystem::~AliHLTSystem()
100 {
101   // see header file for class documentation
102   fgNofInstances--;
103   CleanTaskList();
104   AliHLTConfiguration::GlobalDeinit(fpConfigurationHandler);
105   if (fpConfigurationHandler) {
106     delete fpConfigurationHandler;
107   }
108   fpConfigurationHandler=NULL;
109   
110   if (fpComponentHandler) {
111     delete fpComponentHandler;
112   }
113   fpComponentHandler=NULL;
114 }
115
116 int AliHLTSystem::fgNofInstances=0;
117
118 int AliHLTSystem::AddConfiguration(AliHLTConfiguration* pConf)
119 {
120   // see header file for class documentation
121   int iResult=0;
122   if (pConf) {
123   } else {
124     iResult=-EINVAL;
125   }
126   return iResult;
127 }
128
129 int AliHLTSystem::InsertConfiguration(AliHLTConfiguration* pConf, AliHLTConfiguration* pPrec)
130 {
131   // see header file for class documentation
132   int iResult=0;
133   if (pConf) {
134     if (pPrec) {
135       // find the position
136     }
137   } else {
138     iResult=-EINVAL;
139   }
140   return iResult;
141 }
142
143 int AliHLTSystem::DeleteConfiguration(AliHLTConfiguration* pConf)
144 {
145   // see header file for class documentation
146   int iResult=0;
147   if (pConf) {
148   } else {
149     iResult=-EINVAL;
150   }
151   return iResult;
152 }
153
154 int AliHLTSystem::BuildTaskList(AliHLTConfiguration* pConf)
155 {
156   // see header file for class documentation
157   int iResult=0;
158   if (pConf) {
159     AliHLTTask* pTask=NULL;
160     if ((pTask=FindTask(pConf->GetName()))!=NULL) {
161       if (pTask->GetConf()!=pConf) {
162         HLTError("configuration missmatch, there is already a task with configuration name \"%s\", but it is different. Most likely configuration %p is not registered properly", pConf->GetName(), pConf);
163         iResult=-EEXIST;
164         pTask=NULL;
165       }
166     } else if (pConf->SourcesResolved(1)!=1) {
167         HLTError("configuration \"%s\" has unresolved sources, aborting ...", pConf->GetName());
168         iResult=-ENOLINK;
169     } else {
170       pTask=new AliHLTTask(pConf);
171       if (pTask==NULL) {
172         iResult=-ENOMEM;
173       }
174     }
175     if (pTask) {
176       // check for circular dependencies
177       if ((iResult=pConf->FollowDependency(pConf->GetName()))>0) {
178         HLTError("detected circular dependency for configuration \"%s\"", pTask->GetName());
179         pTask->PrintDependencyTree(pTask->GetName(), 1/*use the configuration list*/);
180         HLTError("aborted ...");
181         iResult=-ELOOP;
182       }
183       if (iResult>=0) {
184         // check whether all dependencies are already in the task list
185         // create the missing ones
186         // this step is an iterative process which calls this function again for the missing
187         // configurations, in order to avoid the currently processed task to be created
188         // again it is added to the list temporarily and removed afterwards
189         // This is of high importance to preserve the order of the tasks. Furthermore, the
190         // InsertTask method has to be used in order to set all the cross links right 
191         fTaskList.Add(pTask);
192         AliHLTConfiguration* pDep=pConf->GetFirstSource();
193         while (pDep!=NULL && iResult>=0) {
194           if (FindTask(pDep->GetName())==NULL) {
195             iResult=BuildTaskList(pDep);
196           }
197           pDep=pConf->GetNextSource();
198         }
199         // remove the temporarily added task
200         fTaskList.Remove(pTask);
201
202         // insert the task and set the cross-links
203         if (iResult>=0) {
204           iResult=InsertTask(pTask);
205         }
206       } else {
207         delete pTask;
208         pTask=NULL;
209       }
210     }
211   } else {
212     iResult=-EINVAL;
213   }
214   return iResult;
215 }
216
217 int AliHLTSystem::CleanTaskList()
218 {
219   // see header file for class documentation
220   int iResult=0;
221   TObjLink* lnk=NULL;
222   while ((lnk=fTaskList.FirstLink())!=NULL) {
223     fTaskList.Remove(lnk);
224     delete (lnk->GetObject());
225   }
226   return iResult;
227 }
228
229 int AliHLTSystem::InsertTask(AliHLTTask* pTask)
230 {
231   // see header file for class documentation
232   int iResult=0;
233   TObjLink *lnk = NULL;
234   if ((iResult=pTask->CheckDependencies())>0)
235     lnk=fTaskList.FirstLink();
236   while (lnk && iResult>0) {
237     AliHLTTask* pCurr = (AliHLTTask*)lnk->GetObject();
238     //HLTDebug("checking  \"%s\"", pCurr->GetName());
239     iResult=pTask->Depends(pCurr);
240     if (iResult>0) {
241       iResult=pTask->SetDependency(pCurr);
242       pCurr->SetTarget(pTask);
243       HLTDebug("set dependency  \"%s\" for configuration \"%s\"", pCurr->GetName(), pTask->GetName());
244     }
245     if (pCurr->Depends(pTask)) {
246       // circular dependency
247       HLTError("circular dependency: can not resolve dependencies for configuration \"%s\"", pTask->GetName());
248       iResult=-ELOOP;
249     } else if ((iResult=pTask->CheckDependencies())>0) {
250       lnk = lnk->Next();
251     }
252   }
253   if (iResult==0) {
254       if (lnk) {
255         fTaskList.AddAfter(lnk, pTask);
256       } else {
257         fTaskList.AddFirst(pTask);
258       }
259       HLTDebug("task \"%s\" inserted", pTask->GetName());
260   } else if (iResult>0) {
261     HLTError("can not resolve dependencies for configuration \"%s\" (%d unresolved)", pTask->GetName(), iResult);
262     iResult=-ENOLINK;
263   }
264   return iResult;
265 }
266
267 AliHLTTask* AliHLTSystem::FindTask(const char* id)
268 {
269   // see header file for class documentation
270   AliHLTTask* pTask=NULL;
271   if (id) {
272     pTask=(AliHLTTask*)fTaskList.FindObject(id); 
273   }
274   return pTask;
275 }
276
277 void AliHLTSystem::PrintTaskList()
278 {
279   // see header file for class documentation
280   HLTLogKeyword("task list");
281   TObjLink *lnk = NULL;
282   HLTMessage("Task List");
283   lnk=fTaskList.FirstLink();
284   while (lnk) {
285     TObject* obj=lnk->GetObject();
286     if (obj) {
287       HLTMessage("  %s - status:", obj->GetName());
288       AliHLTTask* pTask=(AliHLTTask*)obj;
289       pTask->PrintStatus();
290     } else {
291     }
292     lnk = lnk->Next();
293   }
294 }
295
296 int AliHLTSystem::Run(Int_t iNofEvents) 
297 {
298   // see header file for class documentation
299   int iResult=0;
300   int iCount=0;
301   SetStatusFlags(kRunning);
302   if ((iResult=InitTasks())>=0) {
303     if ((iResult=StartTasks())>=0) {
304       for (int i=0; i<iNofEvents && iResult>=0; i++) {
305         iResult=ProcessTasks(i);
306         if (iResult>=0) {
307           HLTInfo("Event %d successfully finished (%d)", i, iResult);
308           iResult=0;
309           iCount++;
310         } else {
311           HLTError("Processing of event %d failed (%d)", i, iResult);
312           // TODO: define different running modes to either ignore errors in
313           // event processing or not
314           // currently ignored 
315           //iResult=0;
316         }
317       }
318       StopTasks();
319     } else {
320       HLTError("can not start task list");
321     }
322     DeinitTasks();
323   } else if (iResult!=-ENOENT) {
324     HLTError("can not initialize task list");
325   }
326   if (iResult>=0) iResult=iCount;
327   ClearStatusFlags(kRunning);
328   return iResult;
329 }
330
331 int AliHLTSystem::InitTasks()
332 {
333   // see header file for class documentation
334   int iResult=0;
335   TObjLink *lnk=fTaskList.FirstLink();
336   if (lnk==NULL) {
337     HLTWarning("Task list is empty, aborting ...");
338     return -ENOENT;
339   }
340   while (lnk && iResult>=0) {
341     TObject* obj=lnk->GetObject();
342     if (obj) {
343       AliHLTTask* pTask=(AliHLTTask*)obj;
344       iResult=pTask->Init(NULL, fpComponentHandler);
345     } else {
346     }
347     lnk = lnk->Next();
348   }
349   if (iResult<0) {
350   }
351   return iResult;
352 }
353
354 int AliHLTSystem::StartTasks()
355 {
356   // see header file for class documentation
357   int iResult=0;
358   TObjLink *lnk=fTaskList.FirstLink();
359   while (lnk && iResult>=0) {
360     TObject* obj=lnk->GetObject();
361     if (obj) {
362       AliHLTTask* pTask=(AliHLTTask*)obj;
363       iResult=pTask->StartRun();
364     } else {
365     }
366     lnk = lnk->Next();
367   }
368   if (iResult<0) {
369   }
370   return iResult;
371 }
372
373 int AliHLTSystem::ProcessTasks(Int_t eventNo)
374 {
375   // see header file for class documentation
376   int iResult=0;
377   HLTDebug("processing event no %d", eventNo);
378   TObjLink *lnk=fTaskList.FirstLink();
379   while (lnk && iResult>=0) {
380     TObject* obj=lnk->GetObject();
381     if (obj) {
382       AliHLTTask* pTask=(AliHLTTask*)obj;
383       iResult=pTask->ProcessTask(eventNo);
384       HLTDebug("task %s finnished (%d)", pTask->GetName(), iResult);
385     } else {
386     }
387     lnk = lnk->Next();
388   }
389   return iResult;
390 }
391
392 int AliHLTSystem::StopTasks()
393 {
394   // see header file for class documentation
395   int iResult=0;
396   TObjLink *lnk=fTaskList.FirstLink();
397   while (lnk && iResult>=0) {
398     TObject* obj=lnk->GetObject();
399     if (obj) {
400       AliHLTTask* pTask=(AliHLTTask*)obj;
401       iResult=pTask->EndRun();
402     } else {
403     }
404     lnk = lnk->Next();
405   }
406   return iResult;
407 }
408
409 int AliHLTSystem::DeinitTasks()
410 {
411   // see header file for class documentation
412   int iResult=0;
413   TObjLink *lnk=fTaskList.FirstLink();
414   while (lnk && iResult>=0) {
415     TObject* obj=lnk->GetObject();
416     if (obj) {
417       AliHLTTask* pTask=(AliHLTTask*)obj;
418       iResult=pTask->Deinit();
419     } else {
420     }
421     lnk = lnk->Next();
422   }
423   return iResult;
424 }
425
426 void* AliHLTSystem::AllocMemory( void* param, unsigned long size )
427 {
428   // see header file for class documentation
429   if (param==NULL) {
430     // get rid of 'unused parameter' warning
431   }
432   return (void*)new char[size];
433 }
434
435 int AliHLTSystem::Reconstruct(int nofEvents, AliRunLoader* runLoader, 
436                               AliRawReader* rawReader)
437 {
438   // see header file for class documentation
439   int iResult=0;
440   if (runLoader) {
441     HLTInfo("Run Loader %p, Raw Reader %p , %d events", runLoader, rawReader, nofEvents);
442     if (CheckStatus(kReady)) {
443       if ((iResult=AliHLTOfflineInterface::SetParamsToComponents(runLoader, rawReader))>=0) {
444         iResult=Run(nofEvents);
445       }
446     } else {
447       HLTError("wrong state %#x, required flags %#x", GetStatusFlags(), kReady);
448     }
449   } else {
450     HLTError("missing run loader instance");
451     iResult=-EINVAL;
452   }
453   return iResult;
454 }
455
456 int AliHLTSystem::FillESD(int eventNo, AliRunLoader* runLoader, AliESD* esd)
457 {
458   // see header file for class documentation
459   int iResult=0;
460   if (runLoader) {
461     HLTInfo("Event %d: Run Loader %p, ESD %p", eventNo, runLoader, esd);
462     iResult=AliHLTOfflineInterface::FillComponentESDs(eventNo, runLoader, esd);
463   } else {
464     HLTError("missing run loader/ESD instance(s)");
465     iResult=-EINVAL;
466   }
467   return iResult;
468 }
469
470 int AliHLTSystem::LoadComponentLibraries(const char* libraries)
471 {
472   // see header file for class documentation
473   int iResult=0;
474   if (libraries) {
475     if (fpComponentHandler) {
476       TString libs(libraries);
477       TObjArray* pTokens=libs.Tokenize(" ");
478       if (pTokens) {
479         int iEntries=pTokens->GetEntries();
480         for (int i=0; i<iEntries && iResult>=0; i++) {
481           iResult=fpComponentHandler->LoadLibrary((((TObjString*)pTokens->At(i))->GetString()).Data());
482         }
483         delete pTokens;
484       }
485       if (iResult>=0) {
486         SetStatusFlags(kLibrariesLoaded);
487       } else {
488         // lets see if we need this, probably not
489         //fpComponentHandler->UnloadLibraries();
490         ClearStatusFlags(kLibrariesLoaded);
491       }
492     } else {
493       iResult=-EFAULT;
494       HLTFatal("no component handler available");
495     }
496   } else {
497     iResult=-EINVAL;
498   }
499   return iResult;
500 }
501
502 int AliHLTSystem::Configure(AliRunLoader* runloader)
503 {
504   // see header file for class documentation
505   int iResult=0;
506   if (CheckStatus(kRunning)) {
507     HLTError("HLT system in running state, can not configure");
508     return -EBUSY;
509   }
510   if (CheckFilter(kHLTLogDebug))
511     AliHLTModuleAgent::PrintStatus();
512   ClearStatusFlags(kConfigurationLoaded|kTaskListCreated);
513   iResult=LoadConfigurations(runloader);
514   if (iResult>=0) {
515     SetStatusFlags(kConfigurationLoaded);
516     iResult=BuildTaskListsFromTopConfigurations(runloader);
517     if (iResult>=0) {
518       SetStatusFlags(kTaskListCreated);
519     }
520   }
521   if (iResult<0) SetStatusFlags(kError);
522   
523   return iResult;
524 }
525
526 int AliHLTSystem::Reset(int bForce)
527 {
528   // see header file for class documentation
529   int iResult=0;
530   if (!bForce && CheckStatus(kRunning)) {
531     HLTError("HLT system in running state, can not configure");
532     return -EBUSY;
533   }
534   CleanTaskList();
535   ClearStatusFlags(~kUninitialized);
536   return iResult;
537 }
538
539 int AliHLTSystem::LoadConfigurations(AliRunLoader* runloader)
540 {
541   // see header file for class documentation
542   if (CheckStatus(kRunning)) {
543     HLTError("HLT system in running state, can not configure");
544     return -EBUSY;
545   }
546   int iResult=0;
547   AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
548   while (pAgent && iResult>=0) {
549     const char* deplibs=pAgent->GetRequiredComponentLibraries();
550     if (deplibs) {
551       HLTDebug("load libraries \'%s\' for agent %s (%p)", deplibs, pAgent->GetName(), pAgent);
552       iResult=LoadComponentLibraries(deplibs);
553     }
554     if (iResult>=0) {
555       HLTDebug("load configurations for agent %s (%p)", pAgent->GetName(), pAgent);
556       pAgent->CreateConfigurations(fpConfigurationHandler, runloader);
557       pAgent=AliHLTModuleAgent::GetNextAgent();
558     }
559   }
560   return iResult;
561 }
562
563 int AliHLTSystem::BuildTaskListsFromTopConfigurations(AliRunLoader* runloader)
564 {
565   // see header file for class documentation
566   if (CheckStatus(kRunning)) {
567     HLTError("HLT system in running state, can not configure");
568     return -EBUSY;
569   }
570   if (!CheckStatus(kConfigurationLoaded)) {
571     HLTWarning("configurations not yet loaded");
572     return 0;
573   }
574
575   int iResult=0;
576   AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
577   while (pAgent && iResult>=0) {
578     TString tops=pAgent->GetTopConfigurations(runloader);
579     HLTDebug("top configurations for agent %s (%p): %s", pAgent->GetName(), pAgent, tops.Data());
580     TObjArray* pTokens=tops.Tokenize(" ");
581     if (pTokens) {
582       int iEntries=pTokens->GetEntries();
583       for (int i=0; i<iEntries && iResult>=0; i++) {
584         const char* pCID=((TObjString*)pTokens->At(i))->GetString().Data();
585         AliHLTConfiguration* pConf=fpConfigurationHandler->FindConfiguration(pCID);
586         if (pConf) {
587           iResult=BuildTaskList(pConf);
588         } else {
589           HLTWarning("can not find top configuration %s", pCID);
590         }
591       }
592       delete pTokens;
593     }
594     
595     pAgent=AliHLTModuleAgent::GetNextAgent();
596   }
597   if (iResult>=0) SetStatusFlags(kTaskListCreated);
598
599   return iResult;
600 }
601
602 int AliHLTSystem::CheckStatus(int flag)
603 {
604   // see header file for class documentation
605   if (flag==kUninitialized && flag==fState) return 1;
606   if ((fState&flag)==flag) return 1;
607   return 0;
608 }
609
610 int AliHLTSystem::GetStatusFlags()
611 {
612   // see header file for class documentation
613   return fState;
614 }
615
616 int AliHLTSystem::SetStatusFlags(int flags)
617 {
618   // see header file for class documentation
619   fState|=flags;
620   return fState;
621 }
622
623 int AliHLTSystem::ClearStatusFlags(int flags)
624 {
625   // see header file for class documentation
626   fState&=~flags;
627   return fState;
628 }