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