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