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