bugfix AliHLTCompStatCollector: filling entry 'Level' of the component statistics...
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTCompStatCollector.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /// @file   AliHLTCompStatCollector.cxx
20 /// @author Matthias Richter
21 /// @date   
22 /// @brief  Collector component for the component statistics information.
23 ///
24
25 #include "AliHLTCompStatCollector.h"
26 #include "AliHLTErrorGuard.h"
27 #include "TFile.h"
28 #include "TStopwatch.h"
29 #include "TH1F.h"
30 #include "TH2F.h"
31 #include "TH2C.h"
32 #include "TTree.h"
33 #include "TFolder.h"
34 #include "TNamed.h"
35 #include "TString.h"
36 #include <cassert>
37 #include <algorithm>
38 using std::sort;
39
40 #define HLTSTAT_FOLDER_NAME               "HLTstat"
41 #define HLTSTAT_FOLDER_DESC               "ALICE HLT component statistics"
42 #define HLTSTAT_ENTRY_PARENT_FOLDER_NAME  "parents"
43 #define HLTSTAT_ENTRY_PARENT_FOLDER_DESC  "parent components"
44 #define HLTSTAT_ENTRY_PROPS_FOLDER_NAME   "props"
45 #define HLTSTAT_ENTRY_PROPS_FOLDER_DESC   "component properties"
46 #define HLTSTAT_ENTRY_PROPS_IDOBJ_NAME    "id"
47 #define HLTSTAT_ENTRY_PROPS_IDOBJ_DESC    "numerical id calculated from chain id"
48
49 /** ROOT macro for the implementation of ROOT specific class methods */
50 ClassImp(AliHLTCompStatCollector)
51
52 AliHLTCompStatCollector::AliHLTCompStatCollector()
53   :
54   AliHLTProcessor(),
55   fpTimer(NULL),
56   fpFolder(NULL),
57   fInstances(),
58   fpStatTree(NULL),
59   fCycleTime(0),
60   fNofSets(0),
61   fArraySize(0),
62   fPosition(0),
63   fpLevelArray(NULL),
64   fpSpecArray(NULL),
65   fpBlockNoArray(NULL),
66   fpIdArray(NULL),
67   fpTimeArray(NULL),
68   fpCTimeArray(NULL),
69   fpInputBlockCountArray(NULL),
70   fpTotalInputSizeArray(NULL),
71   fpNormalizedInputSizeArray(NULL),
72   fpOutputBlockCountArray(NULL),
73   fpTotalOutputSizeArray(NULL)
74   , fpInputOutputRatioArray(NULL)
75   , fpNormalizedInputOutputRatioArray(NULL)
76   , fpComponentCycleTimeArray(NULL)
77   , fpEventTypeArray(NULL)
78   , fpEventCountArray(NULL)
79   , fSizeEstimator(1000)
80   , fMode(kPublishObjects)
81   , fFileName()
82   , fFile(NULL)
83   , fLastTime(time(NULL))
84   , fPeriod(0)
85   , fEventModulo(0)
86 {
87   // see header file for class documentation
88   // or
89   // refer to README to build package
90   // or
91   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
92 }
93
94 AliHLTCompStatCollector::~AliHLTCompStatCollector()
95 {
96   // see header file for class documentation
97   ClearAll();
98 }
99
100 void AliHLTCompStatCollector::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
101 {
102   // see header file for class documentation
103   list.push_back(kAliHLTDataTypeComponentStatistics);
104 }
105
106 AliHLTComponentDataType AliHLTCompStatCollector::GetOutputDataType()
107 {
108   // see header file for class documentation
109   return kAliHLTMultipleDataType;
110 }
111
112 int AliHLTCompStatCollector::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
113 {
114   // see header file for class documentation
115   tgtList.clear();
116   tgtList.push_back(kAliHLTDataTypeHistogram);
117   tgtList.push_back(kAliHLTDataTypeTTree);
118   return tgtList.size();
119 }
120
121 void AliHLTCompStatCollector::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
122 {
123   // see header file for class documentation
124   constBase=fSizeEstimator;
125   inputMultiplier=100.0;
126 }
127
128 int AliHLTCompStatCollector::DoInit( int argc, const char** argv )
129 {
130   // see header file for class documentation
131   int iResult=0;
132   TString argument="";
133   int bMissingParam=0;
134   for (int i=0; i<argc && iResult>=0; i++) {
135     argument=argv[i];
136     if (argument.IsNull()) continue;
137
138     // -file
139     if (argument.CompareTo("-file")==0) {
140       if ((bMissingParam=(++i>=argc))) break;
141       fFileName=argv[i];
142       fMode|=kSaveObjects;
143
144     // -modulo
145     } else if (argument.CompareTo("-modulo")==0) {
146       if ((bMissingParam=(++i>=argc))) break;
147       TString param=argv[i];
148       if (param.IsDigit()) {
149         fEventModulo=param.Atoi();
150       } else {
151         HLTError("expecting number as parameter for option %s", argument.Data());
152         iResult=-EINVAL;
153       }
154
155     // -period
156     } else if (argument.CompareTo("-period")==0) {
157       if ((bMissingParam=(++i>=argc))) break;
158       TString param=argv[i];
159       if (param.IsDigit()) {
160         fPeriod=param.Atoi();
161       } else {
162         HLTError("expecting number as parameter for option %s", argument.Data());
163         iResult=-EINVAL;
164       }
165
166     // -publish
167     } else if (argument.CompareTo("-publish")==0) {
168       if ((bMissingParam=(++i>=argc))) break;
169       TString param=argv[i];
170       if (param.IsDigit()) {
171         if (param.Atoi()==1) fMode|=kPublishObjects;
172         else if (param.Atoi()==0) fMode&=~kPublishObjects;
173         else {
174           HLTError("expecting 0 or 1 as parameter for option %s", argument.Data());
175           iResult=-EINVAL;
176         }
177       } else {
178         HLTError("expecting number as parameter for option %s", argument.Data());
179         iResult=-EINVAL;
180       }
181
182     // -arraysize
183     } else if (argument.CompareTo("-arraysize")==0) {
184       if ((bMissingParam=(++i>=argc))) break;
185       TString param=argv[i];
186       if (param.IsDigit()) {
187         //fArraySize=param.Atoi();
188         HLTWarning("argument -arraysize is deprecated, array size adjusted dynamically");
189       } else {
190         HLTError("expecting number as parameter for option %s", argument.Data());
191         iResult=-EINVAL;
192       }
193
194     } else {
195       HLTError("unknown argument %s", argument.Data());
196       iResult=-EINVAL;
197     }
198   }
199   if (bMissingParam) {
200     HLTError("missing parameter for argument %s", argument.Data());
201     iResult=-EINVAL;
202   }
203
204   if (!fFileName.empty()) {
205     fFile=new TFile(fFileName.c_str(), "RECREATE");
206   }
207   return iResult;
208 }
209
210 int AliHLTCompStatCollector::DoDeinit( )
211 {
212   // see header file for class documentation
213   ClearAll();
214
215   if (fFile) {
216     fFile->Close();
217     delete fFile;
218     fFile=NULL;
219   }
220   return 0;
221 }
222
223 int AliHLTCompStatCollector::DoEvent( const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/)
224 {
225   // see header file for class documentation
226   int iResult=0;
227
228   AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
229   IsDataEvent(&eventType);
230
231   ResetFillingVariables();
232   if (fpTimer) {
233     fCycleTime=fpTimer->RealTime()*1000000;
234   }
235
236   // only if the map of instances is empty it can be initialized from the
237   // component table entries
238   // the logical check fo eventType==gkAliEventTypeStartOfRun does not work
239   // for simulated data where the blocks of the SOR are stored inside the
240   // first event
241   bool bMapInitialization=fInstances.empty();
242   vector<AliHLTCompStatCollector::AliHLTCompStatInstance> sortedInstances;
243
244   bool bEmbeddedTree=false;
245   bool bFolderCreated=false;
246   if ((bFolderCreated=(fpFolder==NULL))) {
247     fpFolder=new TFolder(HLTSTAT_FOLDER_NAME, HLTSTAT_FOLDER_DESC);
248     if (bEmbeddedTree) fpFolder->Add(fpStatTree);
249   }
250   if (!fpFolder) return -ENOMEM;
251   vector<TFolder*> newFolders;
252
253   for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentTable);
254        pBlock && iResult>=0;
255        pBlock=GetNextInputBlock()) {
256     string chainId, compId, compArgs;
257     vector<AliHLTUInt32_t> parents;
258     int level=0;
259     iResult=ExtractComponentTableEntry((const AliHLTUInt8_t*)pBlock->fPtr, pBlock->fSize,
260                                        chainId, compId, compArgs,
261                                        parents, level);
262     if (iResult>0) {
263       HLTDebug("%s(%s) 0x%08x", chainId.c_str(), compId.c_str(), pBlock->fSpecification);
264       if (bMapInitialization) {
265         map<AliHLTUInt32_t, AliHLTCompStatInstance>::const_iterator element=fInstances.find(pBlock->fSpecification);
266         AliHLTCompStatInstance newInstance(pBlock->fSpecification, chainId, compId, compArgs, parents, level);
267         if (element==fInstances.end()) {
268           // new instance
269           fInstances[pBlock->fSpecification]=newInstance;
270           sortedInstances.push_back(newInstance);
271         } else {
272           // check existing instance
273           if (element->second!=newInstance) {
274             HLTWarning("component table entries have identical CRC ids but different content\n  in list: %s\n  skipping: %s",          
275                        element->second.Description().c_str(), newInstance.Description().c_str());
276           }
277         }
278       }
279
280       TObject* pObj=NULL;
281       TFolder* pEntry=NULL;
282       if ((pObj=fpFolder->FindObjectAny(chainId.c_str()))!=NULL &&
283           (pEntry=dynamic_cast<TFolder*>(pObj))!=NULL ) {
284         
285       } else if (pObj) {
286         HLTError("entry %s exists in folder, but is not a sub-folder", chainId.c_str());
287       } else if (chainId.size()>0) {
288         pEntry=new TFolder(chainId.c_str(), chainId.c_str());
289         if (pEntry) {
290           pEntry->SetOwner();
291           TFolder* pProps=pEntry->AddFolder(HLTSTAT_ENTRY_PROPS_FOLDER_NAME, HLTSTAT_ENTRY_PROPS_FOLDER_DESC);
292           if (pProps) {
293             pProps->Add(new TObjString(compId.c_str()));
294             if (!compArgs.empty())
295               pProps->Add(new TObjString(compArgs.c_str()));
296             TNamed* pCRC=new TNamed(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME, HLTSTAT_ENTRY_PROPS_IDOBJ_DESC);
297             if (pCRC) {
298               pCRC->SetUniqueID(pBlock->fSpecification);
299               pProps->Add(pCRC);
300             }
301           }
302           TFolder* pParents=pEntry->AddFolder(HLTSTAT_ENTRY_PARENT_FOLDER_NAME, HLTSTAT_ENTRY_PARENT_FOLDER_DESC);
303           if (pParents) {
304             for (vector<AliHLTUInt32_t>::iterator parent=parents.begin();
305                  parent!=parents.end(); parent++) {
306               TString name; name.Form("0x%08x", *parent);
307               pParents->Add(new TObjString(name));
308             }
309           }
310           if (parents.size()==0) {
311             newFolders.push_back(pEntry);
312           } else {
313             vector<TFolder*>::iterator iter=newFolders.begin();
314             vector<AliHLTUInt32_t>::iterator parent=parents.begin();
315             while (iter!=newFolders.end() && parent!=parents.end()) {
316               TObject* idobj=(*iter)->FindObjectAny(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
317               AliHLTUInt32_t crcid=0;
318               if (idobj) crcid=idobj->GetUniqueID();
319               HLTDebug("check: %s 0x%08x", (*iter)->GetName(), crcid);
320               if (idobj && crcid==*parent) break;
321               if ((++parent!=parents.end())) continue;
322               parent=parents.begin();
323               iter++;
324             }
325             newFolders.insert(iter,pEntry);
326           }
327         }
328       } else {
329         HLTError("missing chain id for table entry 0x%08x (%p %d), skipping ...", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize);
330       }
331     } else if (iResult!=0) {
332       HLTError("extraction of table entry 0x%08x (%p %d) failed with %d", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize, iResult);
333     }
334     iResult=0;
335   }
336
337   if (bMapInitialization) {
338     // assign tags to all instances in the map
339     int level=-1;
340     int tag=-1;
341     TString componentId;
342     TObjArray* taglist=NULL;
343     sort(sortedInstances.begin(), sortedInstances.end(), AliHLTCompStatInstance::SortByLevelAndComponentId);
344     for (vector< AliHLTCompStatInstance>::const_iterator element=sortedInstances.begin();
345          element!=sortedInstances.end();
346          element++) {
347       if (level!=element->GetLevel() ||
348           componentId.CompareTo(element->GetComponentId().c_str())!=0) {
349         tag++;
350         level=element->GetLevel();
351         componentId=element->GetComponentId().c_str();
352         if (fpFolder) {
353           if (!taglist) {
354             taglist=new TObjArray;
355             taglist->SetName("CompStatMap");
356             fpFolder->Add(taglist);
357           }
358           if (taglist) {
359             TString entry;
360             entry.Form("%02d ", tag); entry+=componentId;
361             taglist->Add(new TObjString(entry));
362           }
363         }
364       }
365       fInstances[element->GetCRCId()].SetTag(tag);
366     }
367
368     if (fpStatTree==NULL && !fInstances.empty()) {
369       iResult=AllocateStatTree(fInstances.size());
370       if (!fpStatTree || iResult<0) {
371         ALIHLTERRORGUARD(1, "failed to allocate tree for statistics collection, error %d", iResult);
372       }
373     }
374   }
375
376   if (newFolders.size()>0) {
377     vector<TFolder*> revert;
378     vector<TFolder*>::iterator iter=newFolders.begin();
379     while (iter!=newFolders.end()) {
380       revert.insert(revert.begin(), *iter);
381       HLTDebug("%s", (*iter)->GetName());
382       iter++;
383     }
384     newFolders.empty();
385     newFolders.assign(revert.begin(), revert.end());
386
387     vector<TFolder*>::iterator publisher=newFolders.begin();
388     while (publisher!=newFolders.end()) {
389       bool bRemove=false;
390       HLTDebug("checking %s for parents", (*publisher)->GetName());
391       TFolder* propsFolder=dynamic_cast<TFolder*>((*publisher)->FindObject(HLTSTAT_ENTRY_PROPS_FOLDER_NAME));
392       assert(propsFolder);
393       TObject* idobj=NULL;
394       if (propsFolder) idobj=propsFolder->FindObject(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
395       assert(idobj);
396       if (idobj) {
397         AliHLTUInt32_t crcid=idobj->GetUniqueID();
398         TString idstr; idstr.Form("0x%08x", crcid);
399         for (vector<TFolder*>::iterator consumer=publisher+1;
400              consumer!=newFolders.end(); consumer++) {
401           HLTDebug("   checking %s", (*consumer)->GetName());
402           TFolder* parentFolder=dynamic_cast<TFolder*>((*consumer)->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
403           assert(parentFolder);
404           if (parentFolder) {
405 #ifdef __DEBUG
406             TIter entries(parentFolder->GetListOfFolders());
407             while (TObject* entry=entries.Next())
408               if (entry) {
409                 HLTDebug("   searching %s in %s: %s", idstr.Data(), (*consumer)->GetName(), entry->GetName());
410               }
411 #endif
412             TObject* parent=parentFolder->FindObjectAny(idstr);
413             if (parent) {
414               parentFolder->Add(*publisher);
415               parentFolder->Remove(parent);
416               bRemove=true;
417             }
418           }
419         }
420       }
421       if (bRemove) publisher=newFolders.erase(publisher);
422       else publisher++;
423     }
424
425     for (publisher=newFolders.begin();
426          publisher!=newFolders.end(); publisher++) {
427       RemoveRecurrence(*publisher);
428       fpFolder->Add(*publisher);
429     }
430   }
431
432   int blockNo=0;
433   for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentStatistics);
434        pBlock && iResult>=0;
435        pBlock=GetNextInputBlock(), blockNo++) {
436     unsigned int current=fPosition;
437     iResult=FillVariablesSorted(pBlock->fPtr, pBlock->fSize, eventType);
438     for (; current<fPosition; current++) {
439       fpSpecArray[current]=pBlock->fSpecification;
440       fpBlockNoArray[current]=blockNo;
441     }
442     // indicate availability of component statistic block
443     iResult=1;
444   }
445
446   int totalOutputSize=0;
447   if (iResult>0 && eventType) {
448     fNofSets=fPosition;
449     if (fpStatTree) fpStatTree->Fill();
450
451     // init the timer for the next cycle
452     if (!fpTimer)  fpTimer=new TStopwatch;
453     if (fpTimer) {
454       fpTimer->Reset();
455       fpTimer->Start();
456     }
457   }
458
459   if (eventType==gkAliEventTypeEndOfRun ||
460       (iResult>=0 && CheckPeriod())) {
461
462     // publish objects to component output
463     if ((fMode&kPublishObjects)!=0) {
464       if (!bEmbeddedTree && fpStatTree) {
465         iResult=PushBack(fpStatTree, kAliHLTDataTypeTTree|kAliHLTDataOriginOut);
466         totalOutputSize+=GetLastObjectSize();
467       }
468       iResult=PushBack(fpFolder, kAliHLTDataTypeTObject|kAliHLTDataOriginOut);
469       totalOutputSize+=GetLastObjectSize();
470     }
471
472     // save objects to file
473     if ((fMode&kSaveObjects)!=0 && fFile!=NULL) {
474       HLTDebug("saving objects to file %s", fFileName.c_str());
475       fFile->cd();
476       if (!bEmbeddedTree && fpStatTree) {
477         fpStatTree->Write("", TObject::kOverwrite);
478       }
479       fpFolder->Write("", TObject::kOverwrite);
480     }
481   }
482
483   if (iResult==-ENOSPC) {
484     fSizeEstimator+=totalOutputSize;
485   }
486
487   if (iResult>0) iResult=0;
488   return iResult;
489 }
490
491 void AliHLTCompStatCollector::ResetFillingVariables()
492 {
493   // see header file for class documentation
494
495   for (map<AliHLTUInt32_t, AliHLTCompStatInstance>::iterator element=fInstances.begin();
496        element!=fInstances.end();
497        element++) {
498     element->second.ResetProcessed();
499   }
500
501   fCycleTime=0;
502   fNofSets=0;
503   fPosition=0;
504   if (fArraySize==0) return;
505   memset(fpLevelArray, 0, sizeof(UInt_t)*fArraySize);
506   memset(fpSpecArray, 0, sizeof(UInt_t)*fArraySize);
507   memset(fpBlockNoArray, 0, sizeof(UInt_t)*fArraySize);
508   memset(fpIdArray, 0, sizeof(UInt_t)*fArraySize);
509   memset(fpTimeArray, 0, sizeof(UInt_t)*fArraySize);
510   memset(fpCTimeArray, 0, sizeof(UInt_t)*fArraySize);
511   memset(fpInputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
512   memset(fpTotalInputSizeArray, 0, sizeof(UInt_t)*fArraySize);
513   memset(fpNormalizedInputSizeArray, 0, sizeof(UInt_t)*fArraySize);
514   memset(fpOutputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
515   memset(fpTotalOutputSizeArray, 0, sizeof(UInt_t)*fArraySize);
516   memset(fpInputOutputRatioArray, 0, sizeof(UInt_t)*fArraySize);
517   memset(fpNormalizedInputOutputRatioArray, 0, sizeof(UInt_t)*fArraySize);
518   memset(fpComponentCycleTimeArray, 0, sizeof(UInt_t)*fArraySize);
519   memset(fpEventTypeArray, 0, sizeof(UInt_t)*fArraySize);
520   memset(fpEventCountArray, 0, sizeof(UInt_t)*fArraySize);
521 }
522
523 int AliHLTCompStatCollector::FillVariablesSorted(void* ptr, int size, AliHLTUInt32_t eventType)
524 {
525   // see header file for class documentation
526   int iResult=0;
527   if (size%sizeof(AliHLTComponentStatistics)) {
528     // older or invalid structure
529     HLTError("data block is not aligned to the size of the AliHLTComponentStatistics struct");
530     return -EINVAL;
531   }
532   
533   AliHLTComponentStatistics* pStat=reinterpret_cast<AliHLTComponentStatistics*>(ptr);
534   UInt_t nofStats=size/sizeof(AliHLTComponentStatistics);
535   vector<int> indexList;
536   UInt_t i=0;
537   for (i=0; i<nofStats; i++) {
538     vector<int>::iterator element=indexList.begin();
539     for (; element!=indexList.end(); element++) {
540       if (pStat[i].fLevel>pStat[*element].fLevel) {
541         break;
542       }
543     }
544     indexList.insert(element, i);
545   }
546
547   i=fPosition;
548   for (vector<int>::iterator element=indexList.begin();
549        element!=indexList.end();
550        element++) {
551     map<AliHLTUInt32_t, AliHLTCompStatInstance>::iterator instance=fInstances.find(pStat[*element].fId);
552     if (i<fArraySize && instance!=fInstances.end()) {
553       if (instance->second.IsProcessed()) {
554         //HLTWarning("already processed instance %s, skip", instance->second.Description().c_str());
555         continue;
556       }
557       instance->second.MarkProcessed();
558       if ((int)pStat[*element].fLevel!=instance->second.GetLevel()) {
559         // TODO: there is currently a mismatch of the level set in the statistics entry and
560         // the one in the component table entries. However this does not matter for
561         // archiving because the CRC id is related to a tag/level
562         //HLTWarning("level does not match for instance %s, expected %d", instance->second.Description().c_str(), pStat[*element].fLevel);
563       }
564       fpLevelArray[i]=pStat[*element].fLevel;
565       fpIdArray[i]=pStat[*element].fId;
566       fpTimeArray[i]=pStat[*element].fTime;
567       fpCTimeArray[i]=pStat[*element].fCTime;
568       fpInputBlockCountArray[i]=pStat[*element].fInputBlockCount;
569       fpTotalInputSizeArray[i]=pStat[*element].fTotalInputSize;
570       fpNormalizedInputSizeArray[i]=pStat[*element].fTotalInputSize;
571       if (pStat[*element].fInputBlockCount>0) 
572         fpNormalizedInputSizeArray[i]/=pStat[*element].fInputBlockCount;
573       fpOutputBlockCountArray[i]=pStat[*element].fOutputBlockCount;
574       fpTotalOutputSizeArray[i]=pStat[*element].fTotalOutputSize;
575       if (pStat[*element].fTotalOutputSize>0)
576         fpInputOutputRatioArray[i]=pStat[*element].fTotalInputSize/pStat[*element].fTotalOutputSize;
577       if (pStat[*element].fInputBlockCount>0)
578         fpNormalizedInputOutputRatioArray[i]=fpInputOutputRatioArray[i]*pStat[*element].fOutputBlockCount/pStat[*element].fInputBlockCount;
579       fpComponentCycleTimeArray[i]=pStat[*element].fComponentCycleTime;
580       fpEventTypeArray[i]=eventType;
581       fpEventCountArray[i]=GetEventCount();
582       i++;
583     } else if (instance==fInstances.end()) {
584       HLTWarning("can not find instance of CRC id 0x%08x", pStat[*element].fId);
585     }
586   }
587
588   if (i>fArraySize) {
589     HLTWarning("too little space in branch variables to fill %d statistics blocks, total available %d, current position %d", i, fArraySize, fPosition);
590     fPosition=fArraySize;
591   } else {
592     fPosition=i;
593   }
594   
595   return iResult;
596 }
597
598 int AliHLTCompStatCollector::AllocateStatTree(AliHLTUInt32_t size)
599 {
600   // allocate the statistics tree and the branch arrays
601   if (fArraySize>0) {
602     ClearStatTree();
603   }
604   fArraySize=size;
605   if (fArraySize==0) return 0;
606
607   fpLevelArray=new UInt_t[fArraySize];
608   fpSpecArray=new UInt_t[fArraySize];
609   fpBlockNoArray=new UInt_t[fArraySize];
610   fpIdArray=new UInt_t[fArraySize];
611   fpTimeArray=new UInt_t[fArraySize];
612   fpCTimeArray=new UInt_t[fArraySize];
613   fpInputBlockCountArray=new UInt_t[fArraySize];
614   fpTotalInputSizeArray=new UInt_t[fArraySize];
615   fpNormalizedInputSizeArray=new UInt_t[fArraySize];
616   fpOutputBlockCountArray=new UInt_t[fArraySize];
617   fpTotalOutputSizeArray=new UInt_t[fArraySize];
618   fpInputOutputRatioArray=new UInt_t[fArraySize];
619   fpNormalizedInputOutputRatioArray=new UInt_t[fArraySize];
620   fpComponentCycleTimeArray=new UInt_t[fArraySize];
621   fpEventTypeArray=new UInt_t[fArraySize];
622   fpEventCountArray=new UInt_t[fArraySize];
623
624   fpStatTree=new TTree("CompStat", "HLT component statistics");
625   if (fpStatTree) {
626     fpStatTree->SetDirectory(0);
627     fpStatTree->Branch("cycleTime",        &fCycleTime, "cycleTime/F");
628     fpStatTree->Branch("nofSets",          &fNofSets, "nofSets/I");
629     fpStatTree->Branch("Level",            fpLevelArray, "Level[nofSets]/i");
630     fpStatTree->Branch("Specification",    fpSpecArray, "Specification[nofSets]/i");
631     fpStatTree->Branch("BlockNo",          fpBlockNoArray, "BlockNo[nofSets]/i");
632     fpStatTree->Branch("Id",               fpIdArray, "Id[nofSets]/i");
633     fpStatTree->Branch("Time",             fpTimeArray, "Time[nofSets]/i");
634     fpStatTree->Branch("CTime",            fpCTimeArray, "CTime[nofSets]/i");
635     fpStatTree->Branch("InputBlockCount",  fpInputBlockCountArray, "InputBlockCount[nofSets]/i");
636     fpStatTree->Branch("TotalInputSize",   fpTotalInputSizeArray, "TotalInputSize[nofSets]/i");
637     fpStatTree->Branch("NormalizedInputSize",   fpNormalizedInputSizeArray, "NormalizedInputSize[nofSets]/i");
638     fpStatTree->Branch("OutputBlockCount", fpOutputBlockCountArray, "OutputBlockCount[nofSets]/i");
639     fpStatTree->Branch("TotalOutputSize",  fpTotalOutputSizeArray, "TotalOutputSize[nofSets]/i");
640     fpStatTree->Branch("InputOutputRatio",  fpInputOutputRatioArray, "InputOutputRatio[nofSets]/i");
641     fpStatTree->Branch("NormalizedInputOutputRatio",  fpNormalizedInputOutputRatioArray, "NormalizedInputOutputRatio[nofSets]/i");
642     fpStatTree->Branch("ComponentCycleTime",fpComponentCycleTimeArray, "ComponentCycleTime[nofSets]/i");
643     fpStatTree->Branch("EventType",fpEventTypeArray, "EventType[nofSets]/i");
644     fpStatTree->Branch("EventCount",fpEventCountArray, "EventCount[nofSets]/i");
645   }
646
647   return 0;
648 }
649
650 void AliHLTCompStatCollector::ClearAll()
651 {
652   // see header file for class documentation
653   if (fpTimer) delete fpTimer; fpTimer=NULL;
654   if (fpFolder) delete fpFolder; fpFolder=NULL;
655   ClearStatTree();
656 }
657
658 void AliHLTCompStatCollector::ClearStatTree()
659 {
660   // clear the statistics tree and the branch arrays
661   if (fpStatTree) delete fpStatTree; fpStatTree=NULL;
662   if (fpLevelArray) delete fpLevelArray; fpLevelArray=NULL;
663   if (fpSpecArray) delete fpSpecArray; fpSpecArray=NULL;
664   if (fpBlockNoArray) delete fpBlockNoArray; fpBlockNoArray=NULL;
665   if (fpIdArray) delete fpIdArray; fpIdArray=NULL;
666   if (fpTimeArray) delete fpTimeArray; fpTimeArray=NULL;
667   if (fpCTimeArray) delete fpCTimeArray; fpCTimeArray=NULL;
668   if (fpInputBlockCountArray) delete fpInputBlockCountArray; fpInputBlockCountArray=NULL;
669   if (fpTotalInputSizeArray) delete fpTotalInputSizeArray; fpTotalInputSizeArray=NULL;
670   if (fpNormalizedInputSizeArray) delete fpNormalizedInputSizeArray; fpNormalizedInputSizeArray=NULL;
671   if (fpOutputBlockCountArray) delete fpOutputBlockCountArray; fpOutputBlockCountArray=NULL;
672   if (fpTotalOutputSizeArray) delete fpTotalOutputSizeArray; fpTotalOutputSizeArray=NULL;
673   if (fpInputOutputRatioArray) delete fpInputOutputRatioArray; fpInputOutputRatioArray=NULL;
674   if (fpNormalizedInputOutputRatioArray) delete fpNormalizedInputOutputRatioArray; fpNormalizedInputOutputRatioArray=NULL;
675   if (fpComponentCycleTimeArray) delete fpComponentCycleTimeArray; fpComponentCycleTimeArray=NULL;
676   if (fpEventTypeArray) delete fpEventTypeArray; fpEventTypeArray=NULL;
677   if (fpEventCountArray) delete fpEventCountArray; fpEventCountArray=NULL;
678   fArraySize=0;
679 }
680
681 int AliHLTCompStatCollector::RemoveRecurrence(TFolder* pRoot) const
682 {
683   // see header file for class documentation
684   int iResult=0;
685   if (!pRoot) return -EINVAL;
686   TFolder* parentFolder=dynamic_cast<TFolder*>(pRoot->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
687   assert(parentFolder);
688   vector<TFolder*> listRemove;
689   if (parentFolder) {
690     TIter entries(parentFolder->GetListOfFolders());
691     TFolder* entry=NULL;
692     TObject* obj=NULL;
693     while ((obj=entries.Next())!=NULL && (entry=dynamic_cast<TFolder*>(obj))!=NULL) {
694       TString name=entry->GetName();
695       HLTDebug("checking %s for recurrence", name.Data());
696       TIter tokens(parentFolder->GetListOfFolders());
697       TFolder* token=NULL;
698       while ((obj=tokens.Next())!=NULL && (token=dynamic_cast<TFolder*>(obj))!=NULL) {
699         if (name.CompareTo(token->GetName())==0) continue;
700         if (token->FindObjectAny(name)!=NULL) {
701           listRemove.push_back(entry);
702           HLTDebug("found recurrence in %s", token->GetName());
703           break;
704         } else {
705           HLTDebug("no recurrence found in %s", token->GetName());
706         }
707       }
708       RemoveRecurrence(entry);
709     }
710     for (vector<TFolder*>::iterator removeElement=listRemove.begin();
711          removeElement!=listRemove.end(); removeElement++) {
712       parentFolder->Remove(*removeElement);
713     }
714   }
715   
716   return iResult;  
717 }
718
719 bool AliHLTCompStatCollector::CheckPeriod(bool bUpdate)
720 {
721   // see header file for class documentation
722   bool result=true;
723   if (fEventModulo>0) {
724     if ((result=((GetEventCount()+1)%fEventModulo)==0)) {
725       return true;
726     }
727   }
728   if (fPeriod>0) {
729     if ((result=((difftime(time(NULL), fLastTime)>(double)fPeriod))) &&
730         bUpdate) {
731       fLastTime=time(NULL);
732     }
733   }
734   return result;
735 }
736
737 void AliHLTCompStatCollector::Print(const char* option) const
738 {
739   // print information
740   if (strcmp(option, "instances")==0) {
741     vector<AliHLTCompStatInstance> sortedInstances;
742     for (map<AliHLTUInt32_t, AliHLTCompStatInstance>::const_iterator element=fInstances.begin();
743          element!=fInstances.end();
744          element++) {
745       sortedInstances.push_back(element->second);
746     }
747     sort(sortedInstances.begin(), sortedInstances.end(), AliHLTCompStatInstance::SortByLevelAndComponentId);
748     for (vector<AliHLTCompStatInstance>::const_iterator element=sortedInstances.begin();
749          element!=sortedInstances.end();
750          element++) {
751       element->Print("");
752     }
753   }
754 }
755
756 AliHLTCompStatCollector::AliHLTCompStatInstance::AliHLTCompStatInstance()
757   : fCRCId(0)
758   , fChainId()
759   , fComponentId()
760   , fComponentParam()
761   , fParents()
762   , fLevel(-1)
763   , fTag(-1)
764   , fProcessed(false)
765 {
766   /// default constructor
767 }
768
769 AliHLTCompStatCollector::AliHLTCompStatInstance::AliHLTCompStatInstance(AliHLTUInt32_t CRCId,
770                                                                         const char* chainId,
771                                                                         const char* componentId,
772                                                                         const char* componentParam,
773                                                                         const vector<AliHLTUInt32_t>& parents,
774                                                                         int level,
775                                                                         int tag)
776   : fCRCId(CRCId)
777   , fChainId(chainId)
778   , fComponentId(componentId)
779   , fComponentParam(componentParam)
780   , fParents(parents)
781   , fLevel(level)
782   , fTag(tag)
783   , fProcessed(false)
784 {
785 }
786
787 AliHLTCompStatCollector::AliHLTCompStatInstance::AliHLTCompStatInstance(AliHLTUInt32_t CRCId,
788                                                                         const string& chainId,
789                                                                         const string& componentId,
790                                                                         const string& componentParam,
791                                                                         const vector<AliHLTUInt32_t>& parents,
792                                                                         int level,
793                                                                         int tag)
794   : fCRCId(CRCId)
795   , fChainId(chainId)
796   , fComponentId(componentId)
797   , fComponentParam(componentParam)
798   , fParents(parents)
799   , fLevel(level)
800   , fTag(tag)
801   , fProcessed(false)
802 {
803 }
804
805 AliHLTCompStatCollector::AliHLTCompStatInstance::AliHLTCompStatInstance(const AliHLTCompStatCollector::AliHLTCompStatInstance& src)
806   : fCRCId(src.fCRCId)
807   , fChainId(src.fChainId)
808   , fComponentId(src.fComponentId)
809   , fComponentParam(src.fComponentParam)
810   , fParents(src.fParents)
811   , fLevel(src.fLevel)
812   , fTag(src.fTag)
813   , fProcessed(src.fProcessed)
814 {
815   /// copy constructor
816 }
817
818 AliHLTCompStatCollector::AliHLTCompStatInstance& AliHLTCompStatCollector::AliHLTCompStatInstance::operator=(const AliHLTCompStatCollector::AliHLTCompStatInstance& src)
819 {
820   /// assignment operator
821   if (&src==this) return *this;
822
823   fCRCId=src.fCRCId;
824   fChainId=src.fChainId;
825   fComponentId=src.fComponentId;
826   fComponentParam=src.fComponentParam;
827   fParents.assign(src.fParents.begin(), src.fParents.end());
828   fLevel=src.fLevel;
829   fTag=src.fTag;
830
831   return *this;
832 }
833
834 AliHLTCompStatCollector::AliHLTCompStatInstance::~AliHLTCompStatInstance()
835 {
836   /// destructor
837 }
838
839 string AliHLTCompStatCollector::AliHLTCompStatInstance::Description(const char* /*option*/) const
840 {
841   // get a description string
842   TString description;
843   description.Form("0x%08x level %d tag %d: %s (%s) %s",
844                    fCRCId, fLevel, fTag, fChainId.c_str(), fComponentId.c_str(), fComponentParam.c_str());
845   string ret=description.Data();
846   return ret;
847 }
848
849 void AliHLTCompStatCollector::AliHLTCompStatInstance::Print(const char* /*option*/) const
850 {
851   // print info to cout
852   cout << Description() << endl;
853 }
854
855 bool AliHLTCompStatCollector::AliHLTCompStatInstance::operator==(const AliHLTCompStatInstance &b) const
856 {
857   // check if two instances are equal
858   if (fChainId       !=b.fChainId)          return false;
859   if (fComponentId   !=b.fComponentId)      return false;
860   if (fComponentParam!=b.fComponentParam)   return false;
861   if (fCRCId         !=b.fCRCId)            return false;
862   if (fLevel         !=b.fLevel)            return false;
863   if (fTag>=0 && fTag!=b.fTag && b.fTag>=0) return false;
864
865   return true;
866 }
867
868 bool AliHLTCompStatCollector::AliHLTCompStatInstance::SortByLevelAndComponentId(const AliHLTCompStatInstance &a,
869                                                                                 const AliHLTCompStatInstance &b)
870 {
871   // helper function for std::sort
872   if ( a.fLevel       != b.fLevel )       return ( a.fLevel       < b.fLevel );
873   if ( a.fComponentId != b.fComponentId ) return ( a.fComponentId < b.fComponentId );
874   if ( a.fChainId     != b.fChainId )     return ( a.fChainId     < b.fChainId );
875   return 0;
876 }