]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/util/AliHLTCompStatCollector.cxx
extending the CompStatCollector: added scalers for the object publishing, added file...
[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
37 #define HLTSTAT_FOLDER_NAME               "HLTstat"
38 #define HLTSTAT_FOLDER_DESC               "ALICE HLT component statistics"
39 #define HLTSTAT_ENTRY_PARENT_FOLDER_NAME  "parents"
40 #define HLTSTAT_ENTRY_PARENT_FOLDER_DESC  "parent components"
41 #define HLTSTAT_ENTRY_PROPS_FOLDER_NAME   "props"
42 #define HLTSTAT_ENTRY_PROPS_FOLDER_DESC   "component properties"
43 #define HLTSTAT_ENTRY_PROPS_IDOBJ_NAME    "id"
44 #define HLTSTAT_ENTRY_PROPS_IDOBJ_DESC    "numerical id calculated from chain id"
45
46 /** ROOT macro for the implementation of ROOT specific class methods */
47 ClassImp(AliHLTCompStatCollector)
48
49 AliHLTCompStatCollector::AliHLTCompStatCollector()
50   :
51   AliHLTProcessor(),
52   fpTimer(NULL),
53   fpFolder(NULL),
54   fpStatTree(NULL),
55   fCycleTime(0),
56   fNofSets(0),
57   fArraySize(1000),
58   fPosition(0),
59   fpLevelArray(NULL),
60   fpSpecArray(NULL),
61   fpBlockNoArray(NULL),
62   fpIdArray(NULL),
63   fpTimeArray(NULL),
64   fpCTimeArray(NULL),
65   fpInputBlockCountArray(NULL),
66   fpTotalInputSizeArray(NULL),
67   fpOutputBlockCountArray(NULL),
68   fpTotalOutputSizeArray(NULL)
69   , fSizeEstimator(1000)
70   , fMode(kPublishObjects)
71   , fFileName()
72   , fFile(NULL)
73   , fLastTime(time(NULL))
74   , fPeriod(0)
75   , fEventModulo(0)
76 {
77   // see header file for class documentation
78   // or
79   // refer to README to build package
80   // or
81   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
82 }
83
84 AliHLTCompStatCollector::~AliHLTCompStatCollector()
85 {
86   // see header file for class documentation
87   ClearAll();
88 }
89
90 void AliHLTCompStatCollector::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
91 {
92   // see header file for class documentation
93   list.push_back(kAliHLTDataTypeComponentStatistics);
94 }
95
96 AliHLTComponentDataType AliHLTCompStatCollector::GetOutputDataType()
97 {
98   // see header file for class documentation
99   return kAliHLTMultipleDataType;
100 }
101
102 int AliHLTCompStatCollector::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
103 {
104   // see header file for class documentation
105   tgtList.clear();
106   tgtList.push_back(kAliHLTDataTypeHistogram);
107   tgtList.push_back(kAliHLTDataTypeTTree);
108   return tgtList.size();
109 }
110
111 void AliHLTCompStatCollector::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
112 {
113   // see header file for class documentation
114   constBase=fSizeEstimator;
115   inputMultiplier=100.0;
116 }
117
118 int AliHLTCompStatCollector::DoInit( int argc, const char** argv )
119 {
120   // see header file for class documentation
121   int iResult=0;
122   TString argument="";
123   int bMissingParam=0;
124   for (int i=0; i<argc && iResult>=0; i++) {
125     argument=argv[i];
126     if (argument.IsNull()) continue;
127
128     // -file
129     if (argument.CompareTo("-file")==0) {
130       if ((bMissingParam=(++i>=argc))) break;
131       fFileName=argv[i];
132       fMode|=kSaveObjects;
133
134     // -modulo
135     } else if (argument.CompareTo("-modulo")==0) {
136       if ((bMissingParam=(++i>=argc))) break;
137       TString param=argv[i];
138       if (param.IsDigit()) {
139         fEventModulo=param.Atoi();
140       } else {
141         HLTError("expecting number as parameter for option %s", argument.Data());
142         iResult=-EINVAL;
143       }
144
145     // -period
146     } else if (argument.CompareTo("-period")==0) {
147       if ((bMissingParam=(++i>=argc))) break;
148       TString param=argv[i];
149       if (param.IsDigit()) {
150         fPeriod=param.Atoi();
151       } else {
152         HLTError("expecting number as parameter for option %s", argument.Data());
153         iResult=-EINVAL;
154       }
155
156     // -publish
157     } else if (argument.CompareTo("-publish")==0) {
158       if ((bMissingParam=(++i>=argc))) break;
159       TString param=argv[i];
160       if (param.IsDigit()) {
161         if (param.Atoi()==1) fMode|=kPublishObjects;
162         else if (param.Atoi()==0) fMode&=~kPublishObjects;
163         else {
164           HLTError("expecting 0 or 1 as parameter for option %s", argument.Data());
165           iResult=-EINVAL;
166         }
167       } else {
168         HLTError("expecting number as parameter for option %s", argument.Data());
169         iResult=-EINVAL;
170       }
171     } else {
172       HLTError("unknown argument %s", argument.Data());
173       iResult=-EINVAL;
174     }
175   }
176   if (bMissingParam) {
177     HLTError("missing parameter for argument %s", argument.Data());
178     iResult=-EINVAL;
179   }
180
181   if (iResult>=0) {
182     fpLevelArray=new UInt_t[fArraySize];
183     fpSpecArray=new UInt_t[fArraySize];
184     fpBlockNoArray=new UInt_t[fArraySize];
185     fpIdArray=new UInt_t[fArraySize];
186     fpTimeArray=new UInt_t[fArraySize];
187     fpCTimeArray=new UInt_t[fArraySize];
188     fpInputBlockCountArray=new UInt_t[fArraySize];
189     fpTotalInputSizeArray=new UInt_t[fArraySize];
190     fpOutputBlockCountArray=new UInt_t[fArraySize];
191     fpTotalOutputSizeArray=new UInt_t[fArraySize];
192
193     fpStatTree=new TTree("CompStat", "HLT component statistics");
194     if (fpStatTree) {
195       fpStatTree->SetDirectory(0);
196       fpStatTree->Branch("cycleTime",        &fCycleTime, "cycleTime/F");
197       fpStatTree->Branch("nofSets",          &fNofSets, "nofSets/I");
198       fpStatTree->Branch("Level",            fpLevelArray, "Level[nofSets]/i");
199       fpStatTree->Branch("Specification",    fpSpecArray, "Specification[nofSets]/i");
200       fpStatTree->Branch("BlockNo",          fpBlockNoArray, "BlockNo[nofSets]/i");
201       fpStatTree->Branch("Id",               fpIdArray, "Id[nofSets]/i");
202       fpStatTree->Branch("Time",             fpTimeArray, "Time[nofSets]/i");
203       fpStatTree->Branch("CTime",            fpCTimeArray, "CTime[nofSets]/i");
204       fpStatTree->Branch("InputBlockCount",  fpInputBlockCountArray, "InputBlockCount[nofSets]/i");
205       fpStatTree->Branch("TotalInputSize",   fpTotalInputSizeArray, "TotalInputSize[nofSets]/i");
206       fpStatTree->Branch("OutputBlockCount", fpOutputBlockCountArray, "OutputBlockCount[nofSets]/i");
207       fpStatTree->Branch("TotalOutputSize",  fpTotalOutputSizeArray, "TotalOutputSize[nofSets]/i");
208     }
209   }
210
211   if (!fFileName.empty()) {
212     fFile=new TFile(fFileName.c_str(), "RECREATE");
213   }
214   return iResult;
215 }
216
217 int AliHLTCompStatCollector::DoDeinit( )
218 {
219   // see header file for class documentation
220   ClearAll();
221
222   if (fFile) {
223     fFile->Close();
224     delete fFile;
225     fFile=NULL;
226   }
227   return 0;
228 }
229
230 int AliHLTCompStatCollector::DoEvent( const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/)
231 {
232   // see header file for class documentation
233   int iResult=0;
234
235   AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
236   IsDataEvent(&eventType);
237
238   ResetFillingVariables();
239   if (fpTimer) {
240     fCycleTime=fpTimer->RealTime()*1000000;
241   }
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     iResult=ExtractComponentTableEntry((const AliHLTUInt8_t*)pBlock->fPtr, pBlock->fSize,
258                                        chainId, compId, compArgs,
259                                        parents);
260     if (iResult>0) {
261       HLTDebug("%s(%s) 0x%08x", chainId.c_str(), compId.c_str(), pBlock->fSpecification);
262       TObject* pObj=NULL;
263       TFolder* pEntry=NULL;
264       if ((pObj=fpFolder->FindObjectAny(chainId.c_str()))!=NULL &&
265           (pEntry=dynamic_cast<TFolder*>(pObj))!=NULL ) {
266         
267       } else if (pObj) {
268         HLTError("entry %s exists in folder, but is not a sub-folder", chainId.c_str());
269       } else if (chainId.size()>0) {
270         pEntry=new TFolder(chainId.c_str(), chainId.c_str());
271         if (pEntry) {
272           pEntry->SetOwner();
273           TFolder* pProps=pEntry->AddFolder(HLTSTAT_ENTRY_PROPS_FOLDER_NAME, HLTSTAT_ENTRY_PROPS_FOLDER_DESC);
274           if (pProps) {
275             pProps->Add(new TObjString(compId.c_str()));
276             if (!compArgs.empty())
277               pProps->Add(new TObjString(compArgs.c_str()));
278             TNamed* pCRC=new TNamed(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME, HLTSTAT_ENTRY_PROPS_IDOBJ_DESC);
279             if (pCRC) {
280               pCRC->SetUniqueID(pBlock->fSpecification);
281               pProps->Add(pCRC);
282             }
283           }
284           TFolder* pParents=pEntry->AddFolder(HLTSTAT_ENTRY_PARENT_FOLDER_NAME, HLTSTAT_ENTRY_PARENT_FOLDER_DESC);
285           if (pParents) {
286             for (vector<AliHLTUInt32_t>::iterator parent=parents.begin();
287                  parent!=parents.end(); parent++) {
288               TString name; name.Form("0x%08x", *parent);
289               pParents->Add(new TObjString(name));
290             }
291           }
292           if (parents.size()==0) {
293             newFolders.push_back(pEntry);
294           } else {
295             vector<TFolder*>::iterator iter=newFolders.begin();
296             vector<AliHLTUInt32_t>::iterator parent=parents.begin();
297             while (iter!=newFolders.end() && parent!=parents.end()) {
298               TObject* idobj=(*iter)->FindObjectAny(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
299               AliHLTUInt32_t crcid=0;
300               if (idobj) crcid=idobj->GetUniqueID();
301               HLTDebug("check: %s 0x%08x", (*iter)->GetName(), crcid);
302               if (idobj && crcid==*parent) break;
303               if ((++parent!=parents.end())) continue;
304               parent=parents.begin();
305               iter++;
306             }
307             newFolders.insert(iter,pEntry);
308           }
309         }
310       } else {
311         HLTError("missing chain id for table entry 0x%08x (%p %d), skipping ...", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize);
312       }
313     } else if (iResult!=0) {
314       HLTError("extraction of table entry 0x%08x (%p %d) failed with %d", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize, iResult);
315     }
316     iResult=0;
317   }
318
319   if (newFolders.size()>0) {
320     vector<TFolder*> revert;
321     vector<TFolder*>::iterator iter=newFolders.begin();
322     while (iter!=newFolders.end()) {
323       revert.insert(revert.begin(), *iter);
324       HLTDebug("%s", (*iter)->GetName());
325       iter++;
326     }
327     newFolders.empty();
328     newFolders.assign(revert.begin(), revert.end());
329
330     vector<TFolder*>::iterator publisher=newFolders.begin();
331     while (publisher!=newFolders.end()) {
332       bool bRemove=false;
333       HLTDebug("checking %s for parents", (*publisher)->GetName());
334       TFolder* propsFolder=dynamic_cast<TFolder*>((*publisher)->FindObject(HLTSTAT_ENTRY_PROPS_FOLDER_NAME));
335       assert(propsFolder);
336       TObject* idobj=NULL;
337       if (propsFolder) idobj=propsFolder->FindObject(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
338       assert(idobj);
339       AliHLTUInt32_t crcid=idobj->GetUniqueID();
340       TString idstr; idstr.Form("0x%08x", crcid);
341       if (idobj) {
342         for (vector<TFolder*>::iterator consumer=publisher+1;
343              consumer!=newFolders.end(); consumer++) {
344           HLTDebug("   checking %s", (*consumer)->GetName());
345           TFolder* parentFolder=dynamic_cast<TFolder*>((*consumer)->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
346           assert(parentFolder);
347           if (parentFolder) {
348             TIter entries(parentFolder->GetListOfFolders());
349             while (TObject* entry=entries.Next())
350               if (entry) {
351                 Bool_t foo; foo=kTRUE;// only to avoid warning in non-debug compile
352                 HLTDebug("   searching %s in %s: %s", idstr.Data(), (*consumer)->GetName(), entry->GetName());
353               }
354             TObject* parent=parentFolder->FindObjectAny(idstr);
355             if (parent) {
356               parentFolder->Add(*publisher);
357               parentFolder->Remove(parent);
358               bRemove=true;
359             }
360           }
361         }
362       }
363       if (bRemove) publisher=newFolders.erase(publisher);
364       else publisher++;
365     }
366
367     for (publisher=newFolders.begin();
368          publisher!=newFolders.end(); publisher++) {
369       RemoveRecurrence(*publisher);
370       fpFolder->Add(*publisher);
371     }
372   }
373
374   int blockNo=0;
375   for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentStatistics);
376        pBlock && iResult>=0;
377        pBlock=GetNextInputBlock(), blockNo++) {
378     unsigned int current=fPosition;
379     iResult=FillVariablesSorted(pBlock->fPtr, pBlock->fSize);
380     for (; current<fPosition; current++) {
381       fpSpecArray[current]=pBlock->fSpecification;
382       fpBlockNoArray[current]=blockNo;
383     }
384     // indicate availability of component statistic block
385     iResult=1;
386   }
387
388   int totalOutputSize=0;
389   if (iResult>0) {
390     fNofSets=fPosition;
391     fpStatTree->Fill();
392
393     // init the timer for the next cycle
394     if (!fpTimer)  fpTimer=new TStopwatch;
395     if (fpTimer) {
396       fpTimer->Reset();
397       fpTimer->Start();
398     }
399   }
400
401   if (eventType==gkAliEventTypeEndOfRun ||
402       (iResult>=0 && CheckPeriod())) {
403
404     // publish objects to component output
405     if ((fMode&kPublishObjects)!=0) {
406       if (!bEmbeddedTree) {
407         iResult=PushBack(fpStatTree, kAliHLTDataTypeTTree|kAliHLTDataOriginOut);
408         totalOutputSize+=GetLastObjectSize();
409       }
410       iResult=PushBack(fpFolder, kAliHLTDataTypeTObject|kAliHLTDataOriginOut);
411       totalOutputSize+=GetLastObjectSize();
412     }
413
414     // save objects to file
415     if ((fMode&kSaveObjects)!=0 && fFile!=NULL) {
416       HLTDebug("saving objects to file %s", fFileName.c_str());
417       fFile->cd();
418       if (!bEmbeddedTree) {
419         fpStatTree->Write("", TObject::kOverwrite);
420       }
421       fpFolder->Write("", TObject::kOverwrite);
422     }
423   }
424
425   if (iResult==-ENOSPC) {
426     fSizeEstimator+=totalOutputSize;
427   }
428
429   if (iResult>0) iResult=0;
430   return iResult;
431 }
432
433 void AliHLTCompStatCollector::ResetFillingVariables()
434 {
435   // see header file for class documentation
436   fCycleTime=0;
437   fNofSets=0;
438   fPosition=0;
439   memset(fpLevelArray, 0, sizeof(UInt_t)*fArraySize);
440   memset(fpSpecArray, 0, sizeof(UInt_t)*fArraySize);
441   memset(fpBlockNoArray, 0, sizeof(UInt_t)*fArraySize);
442   memset(fpIdArray, 0, sizeof(UInt_t)*fArraySize);
443   memset(fpTimeArray, 0, sizeof(UInt_t)*fArraySize);
444   memset(fpCTimeArray, 0, sizeof(UInt_t)*fArraySize);
445   memset(fpInputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
446   memset(fpTotalInputSizeArray, 0, sizeof(UInt_t)*fArraySize);
447   memset(fpOutputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
448   memset(fpTotalOutputSizeArray, 0, sizeof(UInt_t)*fArraySize);
449 }
450
451 int AliHLTCompStatCollector::FillVariablesSorted(void* ptr, int size)
452 {
453   // see header file for class documentation
454   int iResult=0;
455   if (size%sizeof(AliHLTComponentStatistics)) {
456     HLTError("data block is not aligned to the size of the AliHLTComponentStatistics struct");
457     return -EINVAL;
458   }
459   AliHLTComponentStatistics* pStat=reinterpret_cast<AliHLTComponentStatistics*>(ptr);
460   UInt_t nofStats=size/sizeof(AliHLTComponentStatistics);
461   vector<int> indexList;
462   UInt_t i=0;
463   for (i=0; i<nofStats; i++) {
464     vector<int>::iterator element=indexList.begin();
465     for (; element!=indexList.end(); element++) {
466       if (pStat[i].fLevel>pStat[*element].fLevel) {
467         break;
468       }
469     }
470     indexList.insert(element, i);
471   }
472
473   i=fPosition;
474   for (vector<int>::iterator element=indexList.begin();
475        element!=indexList.end();
476        element++, i++) {
477     if (i<fArraySize) {
478       fpLevelArray[i]=pStat[*element].fLevel;
479       fpIdArray[i]=pStat[*element].fId;
480       fpTimeArray[i]=pStat[*element].fTime;
481       fpCTimeArray[i]=pStat[*element].fCTime;
482       fpInputBlockCountArray[i]=pStat[*element].fInputBlockCount;
483       fpTotalInputSizeArray[i]=pStat[*element].fTotalInputSize;
484       fpOutputBlockCountArray[i]=pStat[*element].fOutputBlockCount;
485       fpTotalOutputSizeArray[i]=pStat[*element].fTotalOutputSize;
486     } else {
487       // TODO: dynamically grow arrays with placement new
488     }
489   }
490
491   if (i>=fArraySize) {
492     HLTWarning("too little space in branch variables to fill %d statistics blocks, available %d at position %d", i, fArraySize, fPosition);
493     fPosition=fArraySize;
494   } else {
495     fPosition=i;
496   }
497   
498   return iResult;
499 }
500
501 void AliHLTCompStatCollector::ClearAll()
502 {
503   // see header file for class documentation
504   if (fpTimer) delete fpTimer; fpTimer=NULL;
505   if (fpFolder) delete fpFolder; fpFolder=NULL;
506   if (fpStatTree) delete fpStatTree; fpStatTree=NULL;
507   if (fpLevelArray) delete fpLevelArray; fpLevelArray=NULL;
508   if (fpSpecArray) delete fpSpecArray; fpSpecArray=NULL;
509   if (fpBlockNoArray) delete fpBlockNoArray; fpBlockNoArray=NULL;
510   if (fpIdArray) delete fpIdArray; fpIdArray=NULL;
511   if (fpTimeArray) delete fpTimeArray; fpTimeArray=NULL;
512   if (fpCTimeArray) delete fpCTimeArray; fpCTimeArray=NULL;
513   if (fpInputBlockCountArray) delete fpInputBlockCountArray; fpInputBlockCountArray=NULL;
514   if (fpTotalInputSizeArray) delete fpTotalInputSizeArray; fpTotalInputSizeArray=NULL;
515   if (fpOutputBlockCountArray) delete fpOutputBlockCountArray; fpOutputBlockCountArray=NULL;
516   if (fpTotalOutputSizeArray) delete fpTotalOutputSizeArray; fpTotalOutputSizeArray=NULL;
517 }
518
519 int AliHLTCompStatCollector::RemoveRecurrence(TFolder* pRoot) const
520 {
521   // see header file for class documentation
522   int iResult=0;
523   if (!pRoot) return -EINVAL;
524   TFolder* parentFolder=dynamic_cast<TFolder*>(pRoot->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
525   assert(parentFolder);
526   vector<TFolder*> listRemove;
527   if (parentFolder) {
528     TIter entries(parentFolder->GetListOfFolders());
529     TFolder* entry=NULL;
530     TObject* obj=NULL;
531     while ((obj=entries.Next())!=NULL && (entry=dynamic_cast<TFolder*>(obj))!=NULL) {
532       TString name=entry->GetName();
533       HLTDebug("checking %s for recurrence", name.Data());
534       TIter tokens(parentFolder->GetListOfFolders());
535       TFolder* token=NULL;
536       while ((obj=tokens.Next())!=NULL && (token=dynamic_cast<TFolder*>(obj))!=NULL) {
537         if (name.CompareTo(token->GetName())==0) continue;
538         if ((obj=token->FindObjectAny(name))!=NULL) {
539           listRemove.push_back(entry);
540           HLTDebug("found recurrence in %s", token->GetName());
541           break;
542         } else {
543           HLTDebug("no recurrence found in %s", token->GetName());
544         }
545       }
546       RemoveRecurrence(entry);
547     }
548     for (vector<TFolder*>::iterator removeElement=listRemove.begin();
549          removeElement!=listRemove.end(); removeElement++) {
550       parentFolder->Remove(*removeElement);
551     }
552   }
553   
554   return iResult;  
555 }
556
557 bool AliHLTCompStatCollector::CheckPeriod(bool bUpdate)
558 {
559   // see header file for class documentation
560   bool result=true;
561   if (fEventModulo>0) {
562     if ((result=((GetEventCount()+1)%fEventModulo)==0)) {
563       return true;
564     }
565   }
566   if (fPeriod>0) {
567     if ((result=((difftime(time(NULL), fLastTime)>(double)fPeriod))) &&
568         bUpdate) {
569       fLastTime=time(NULL);
570     }
571   }
572   return result;
573 }