CounterSvc.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // STD & SLT
3 // ============================================================================
4 #include <utility>
5 #include <vector>
6 #include <algorithm>
7 #include <functional>
8 // ============================================================================
9 // GaudiKernel
10 // ============================================================================
11 #include "GaudiKernel/ICounterSvc.h"
12 #include "GaudiKernel/ISvcLocator.h"
13 #include "GaudiKernel/MsgStream.h"
14 #include "GaudiKernel/Service.h"
15 #include "GaudiKernel/HashMap.h"
16 #include "GaudiKernel/Stat.h"
17 // ============================================================================
24 class CounterSvc: public extends1<Service, ICounterSvc> {
25 public:
27  CounterSvc ( const std::string& name ,
28  ISvcLocator* svcLoc )
29  : base_class(name, svcLoc)
30  // the header row
31  , m_header ( " Counter :: Group | # | sum | mean/eff^* | rms/err^* | min | max |")
32  // format for regular statistical printout rows
33  , m_format1 ( " %|15.15s|%|-15.15s|%|32t||%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |" )
34  // format for "efficiency" statistical printout rows
35  , m_format2 ( "*%|15.15s|%|-15.15s|%|32t||%|10d| |%|11.5g| |(%|#9.7g| +- %|-#9.7g|)%%| ------- | ------- |" )
36  //
37  {
38  declareProperty ("PrintStat" , m_print ) ;
39  //
40  declareProperty
41  ( "StatTableHeader" , m_header ,
42  "The header row for the output Stat-table" ) ;
43  //
44  declareProperty
45  ( "RegularRowFormat" , m_format1 ,
46  "The format for the regular row in the output Stat-table" ) ;
47  //
48  declareProperty
49  ( "EfficiencyRowFormat" , m_format2 ,
50  "The format for the regular row in the outptu Stat-table" ) ;
51  //
52  declareProperty
53  ( "UseEfficiencyRowFormat" , m_useEffFormat ,
54  "Use the special format for printout of efficiency counters" ) ;
55  }
57  ~CounterSvc() override { remove().ignore() ; }
59  StatusCode finalize() override
60  {
61  if ( outputLevel() <= MSG::DEBUG || m_print ) { print () ; }
62  remove().ignore() ;
63  // finalize the base class
64  return Service::finalize() ;
65  }
66  // ==========================================================================
74  Counter* get
75  ( const std::string& group ,
76  const std::string& name ) const override;
78  ICounterSvc::Counters get ( const std::string& group ) const override ;
92  ( const std::string& group ,
93  const std::string& name ,
94  longlong initial_value ,
95  Counter*& refpCounter ) override ;
107  CountObject create
108  ( const std::string& group ,
109  const std::string& name ,
110  longlong initial_value = 0 ) override ;
120  StatusCode remove
121  ( const std::string& group ,
122  const std::string& name ) override ;
128  StatusCode remove
129  ( const std::string& group ) override ;
131  virtual StatusCode remove();
140  ( const std::string& group,
141  const std::string& name,
142  Printout& printer) const override;
151  (const std::string& group,
152  Printout& printer) const override;
160  ( const Counter* pCounter,
161  Printout& printer) const override;
169  ( const CountObject& pCounter,
170  Printout& printer) const override;
174  StatusCode print(Printout& printer) const override;
177  ( MsgStream& log,
178  const Counter* pCounter) const override ;
179 private:
180  // find group/name for the counter:
181  inline std::pair<std::string,std::string> _find ( const Counter* c ) const
182  {
183  if ( c ) {
184  for ( const auto& i : m_counts ) {
185  auto j = std::find_if( i.second.begin(), i.second.end(),
186  [&](const NameMap::value_type& k) {
187  return k.second == c;
188  });
189  if (j!=i.second.end()) return { i.first, j->first } ;
190  }
191  }
192  return { };
193  }
194  // get the overall number of counters
195  inline size_t num () const
196  {
197  return std::accumulate( m_counts.begin(), m_counts.end(), size_t{0},
198  [](size_t r, const CountMap::value_type& i) {
199  return r + std::count_if(i.second.begin(),i.second.end(),
200  [](const NameMap::value_type& j) -> bool { return j.second; });
201  });
202  }
203 public:
205  void print () const ;
206 private:
209  // the actual map of counters
210  CountMap m_counts ;
211  // boolean flag to print statistics
212  bool m_print = true ;
213  // the header row
214  std::string m_header ;
215  // format for regular statistical printout rows
216  std::string m_format1 ;
217  // format for "efficiency" statistical printout rows
218  std::string m_format2 ;
219  // flag to use the special "efficiency" format
220  bool m_useEffFormat = true;
221 } ;
222 // ===========================================================================
223 // Instantiation of a static factory class used by clients
224 // ===========================================================================
226 // ===========================================================================
227 // Access a counter object by name and group
228 // ===========================================================================
229 CounterSvc::Counter* CounterSvc::get
230 ( const std::string& grp ,
231  const std::string& nam ) const
232 {
233  auto i = m_counts.find ( grp ) ;
234  if ( m_counts.end() == i ) { return nullptr ; } // RETURN
235  auto j = i->second.find ( nam ) ;
236  if ( i->second.end() == j ) { return nullptr ; } // RETURN
237  return j->second ; // RETURN
238 }
239 // ===========================================================================
240 // get all counters form the given group:
241 // ===========================================================================
242 ICounterSvc::Counters CounterSvc::get ( const std::string& group ) const
243 {
244  ICounterSvc::Counters result ;
245  auto i = m_counts.find ( group ) ;
246  if ( i != m_counts.end() ) {
247  std::transform( i->second.begin(), i->second.end(),
248  std::back_inserter(result),
249  [&](const NameMap::value_type& j) {
250  return CountObject{ j.second, i->first, j.first };
251  } );
252  }
253  return result ;
254 }
255 // ===========================================================================
256 // Create/get a counter object.
257 // ===========================================================================
258 #ifdef __ICC
259 // disable icc remark #2259: non-pointer conversion from "longlong={long long}" to "double" may lose significant bits
260 #pragma warning(push)
261 #pragma warning(disable:2259)
262 #endif
264 ( const std::string& grp ,
265  const std::string& nam ,
266  longlong initial_value ,
267  Counter*& refpCounter )
268 {
269  // try to find existing counter:
270  refpCounter = get ( grp , nam ) ;
271  if ( refpCounter ) { return COUNTER_EXISTS ; } // RETURN
272  // create the new counter
273  auto newc = new Counter() ;
274  refpCounter = newc ;
275  if ( 0 != initial_value ) {
276  refpCounter->addFlag ( static_cast<double>(initial_value) ) ; // icc remark #2259
277  }
278  // find a proper group
279  auto i = m_counts.find ( grp ) ;
280  // (create a group if needed)
281  if ( m_counts.end() == i )
282  { i = m_counts.emplace ( grp , NameMap() ).first ; }
283  // insert new counter with proper name into proper group:
284  i->second.emplace( nam , newc );
285  return StatusCode::SUCCESS ; // RETURN
286 }
287 #ifdef __ICC
288 // re-enable icc remark #2259
289 #pragma warning(pop)
290 #endif
291 // ===========================================================================
292 // Create a new counter object. If the counter object exists already,
293 // ===========================================================================
294 CounterSvc::CountObject CounterSvc::create
295 ( const std::string& group ,
296  const std::string& name ,
297  longlong initial_value )
298 {
299  Counter* p = nullptr;
300  StatusCode sc = create ( group, name, initial_value, p ) ;
301  if ( sc.isSuccess() && p ) { return CountObject ( p , group , name ) ; }
302  throw std::runtime_error("CounterSvc::Counter('"+group+"::"+name+"') exists already!");
303 }
304 // ===========================================================================
305 // Remove a counter object. The tuple (group,name) identifies the counter uniquely
306 // ===========================================================================
308 ( const std::string& grp ,
309  const std::string& nam )
310 {
311  auto i = m_counts.find ( grp ) ;
312  if ( m_counts.end() == i ) { return COUNTER_NOT_PRESENT ; } // RETURN
313  auto j = i->second.find ( nam ) ;
314  if ( i->second.end() == j ) { return COUNTER_NOT_PRESENT ; } // RETURN
315  delete j->second ;
316  i->second.erase ( j ) ;
317  return StatusCode::SUCCESS ;
318 }
319 // ===========================================================================
320 // Remove a group of counter objects.
321 // ===========================================================================
322 StatusCode CounterSvc::remove ( const std::string& grp )
323 {
324  auto i = m_counts.find ( grp ) ;
325  if ( m_counts.end() == i ) { return COUNTER_NOT_PRESENT ; } // RETURN
326  for ( auto& j : i->second ) delete j.second ;
327  i->second.clear() ;
328  return StatusCode::SUCCESS ;
329 }
330 // ===========================================================================
331 // Remove all known counter objects
332 // ===========================================================================
334 {
335  // remove group by group
336  for ( auto& i : m_counts ) remove ( i.first ).ignore () ;
337  m_counts.clear() ;
338  return StatusCode::SUCCESS;
339 }
340 // ===========================================================================
341 // Print counter value
342 // ===========================================================================
344 ( const std::string& grp,
345  const std::string& nam,
346  Printout& printer) const
347 {
348  const Counter* c = get( grp , nam ) ;
349  if ( !c ) { return COUNTER_NOT_PRESENT ; } // RETURN
350  // create the stream and use it!
351  MsgStream log ( msgSvc() , name() ) ;
352  return printer ( log , c ) ;
353 }
354 
355 namespace {
357  class conditionalPrint {
358  private:
359  CounterSvc::Printout *printer;
360  MsgStream *log;
361  public:
362  conditionalPrint(CounterSvc::Printout &_p, MsgStream &_l): printer(&_p), log(&_l) {}
363  template<class Pair>
364  void operator() (const Pair &p) {
365  if (p.second) {
366  (*printer)(*log, p.second).ignore();
367  }
368  }
369  };
370 }
371 // ===========================================================================
372 // Print the counter value for the whole group of counters
373 // ===========================================================================
375 ( const std::string& grp ,
376  Printout& printer ) const
377 {
378  auto i = m_counts.find ( grp ) ;
379  if ( m_counts.end() == i ) { return COUNTER_NOT_PRESENT ; }
380 
381  MsgStream log(msgSvc(), name());
382  // Force printing in alphabetical order
383  std::map<std::string, Counter*> sorted_map(i->second.begin(), i->second.end());
384  std::for_each(sorted_map.begin(), sorted_map.end(),
385  conditionalPrint(printer, log));
386  return StatusCode::SUCCESS; // RETURN
387 }
388 // ===========================================================================
389 // Print counter value
390 // ===========================================================================
392 ( const Counter* pCounter,
393  Printout& printer ) const
394 {
395  MsgStream log(msgSvc(), name() ) ;
396  return printer ( log , pCounter ) ;
397 }
398 // ===========================================================================
399 // Print counter value
400 // ===========================================================================
402 ( const CountObject& refCounter,
403  Printout& printer) const
404 { return print( refCounter.counter() , printer ) ; }
405 // ===========================================================================
406 // Print all known counters
407 // ===========================================================================
408 StatusCode CounterSvc::print( Printout& printer ) const
409 {
410  MsgStream log ( msgSvc() , name() ) ;
411  // Force printing in alphabetical order
412  std::map<std::pair<std::string,std::string>, Counter*> sorted_map;
413  for ( const auto& i : m_counts ) for ( const auto& j : i.second )
414  sorted_map[ { i.first, j.first } ] = j.second;
415  std::for_each(sorted_map.begin(), sorted_map.end(),
416  conditionalPrint(printer, log));
417  return StatusCode::SUCCESS;
418 }
419 // ===========================================================================
420 // Print counter value
421 // ===========================================================================
424  const Counter* c ) const
425 {
426  if ( !c ) { return StatusCode::FAILURE ; }
427  auto p = _find ( c ) ;
428 
429  log << MSG::ALWAYS
430  << CountObject( const_cast<Counter*>(c) , p.first , p.second )
431  << endmsg ;
432 
433  return StatusCode::SUCCESS;
434 }
435 // ===========================================================================
436 // "standard" printout a'la GaudiCommon
437 // ===========================================================================
438 void CounterSvc::print () const
439 {
440  MsgStream log ( msgSvc() , name() ) ;
441  // number of counters
442  const auto _num = num() ;
443  if ( 0 != _num )
444  {
445  log << MSG::ALWAYS
446  << "Number of counters : " << _num << endmsg
447  << m_header << endmsg ;
448  }
449  // Force printing in alphabetical order
450  std::map<std::pair<std::string,std::string>, Counter*> sorted_map;
451  for ( const auto& i : m_counts ) {
452  for ( const auto& j : i.second ) {
453  if ( j.second ) sorted_map[ {i.first, j.first} ] = j.second;
454  }
455  }
456  for ( const auto& i : sorted_map ) {
457  log << Gaudi::Utils::formatAsTableRow( i.first.second
458  , i.first.first
459  , *i.second
461  , m_format1
462  , m_format2 )
463  << endmsg ;
464  }
465 }
466 // ============================================================================
467 
468 // ============================================================================
469 // The END
470 // ============================================================================
std::pair< std::string, std::string > _find(const Counter *c) const
Definition: CounterSvc.cpp:181
GaudiUtils::HashMap< std::string, NameMap > CountMap
Definition: CounterSvc.cpp:208
tuple c
Definition: gaudirun.py:391
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
virtual StatusCode remove()
Remove all known counter objects.
Definition: CounterSvc.cpp:333
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
std::string m_header
the header row
Definition: CounterSvc.cpp:214
StatusCode finalize() override
Definition: Service.cpp:188
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:76
Counter * get(const std::string &group, const std::string &name) const override
Access an existing counter object.
Definition: CounterSvc.cpp:230
bool m_useEffFormat
flag to use the special "efficiency" format
Definition: CounterSvc.cpp:220
bool m_print
boolean flag to print statistics
Definition: CounterSvc.cpp:212
STL namespace.
std::vector< CountObject > Counters
the actual type of vectors of initialized counters
Definition: ICounterSvc.h:99
std::string m_format2
format for "efficiency" statistical printout rows
Definition: CounterSvc.cpp:218
Simple implementation of the abstract interface ICounterSvc.
Definition: CounterSvc.cpp:24
StatusCode create(const std::string &group, const std::string &name, longlong initial_value, Counter *&refpCounter) override
Create a new counter object.
Definition: CounterSvc.cpp:264
GaudiUtils::HashMap< std::string, Counter * > NameMap
Definition: CounterSvc.cpp:207
iterator end()
Definition: Map.h:132
void print() const
"standard" printout a'la GaudiCommon
Definition: CounterSvc.cpp:438
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
std::pair< const K, T > value_type
Definition: Map.h:94
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
CountMap m_counts
the actual map of counters
Definition: CounterSvc.cpp:210
CounterSvc(const std::string &name, ISvcLocator *svcLoc)
Standard Constructor.
Definition: CounterSvc.cpp:27
iterator find(const key_type &key)
Definition: Map.h:149
std::string m_format1
format for regular statistical printout rows
Definition: CounterSvc.cpp:216
iterator begin()
Definition: Map.h:131
StatusCode defaultPrintout(MsgStream &log, const Counter *pCounter) const override
Default Printout for counters.
Definition: CounterSvc.cpp:423
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
void print(string text)
Definition: mergesort.cpp:33
GAUDI_API std::string formatAsTableRow(const StatEntity &counter, const bool flag, const std::string &format1=" |%|7d| |%|11.7g| |%|#11.5g| |%|#10.5g| |%|#10.5g| |%|#10.5g| |", const std::string &format2="*|%|7d| |%|11.5g| |(%|#9.7g| +- %|-#8.6g|)%%| ----- | ----- |")
print the counter in a form of the table row
Definition: StatEntity.cpp:299
Common class providing an architecture-independent hash map.
Definition: HashMap.h:77
size_t num() const
Definition: CounterSvc.cpp:195
list i
Definition: ana.py:128
~CounterSvc() override
Standard destructor.
Definition: CounterSvc.cpp:57
StatusCode finalize() override
Finalization.
Definition: CounterSvc.cpp:59