CounterSvc.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // STD & SLT
3 // ============================================================================
4 #include <algorithm>
5 #include <functional>
6 #include <utility>
7 #include <vector>
8 #include <numeric>
9 // ============================================================================
10 // GaudiKernel
11 // ============================================================================
12 #include "GaudiKernel/HashMap.h"
15 #include "GaudiKernel/MsgStream.h"
16 #include "GaudiKernel/Service.h"
17 #include "GaudiKernel/Stat.h"
18 // ============================================================================
25 class CounterSvc : public extends<Service, ICounterSvc>
26 {
27 public:
28  // inherit constructor
29  using extends::extends;
31  ~CounterSvc() override { remove().ignore(); }
33  StatusCode finalize() override
34  {
35  if ( msgLevel( MSG::DEBUG ) || m_print ) {
36  print();
37  }
38  remove().ignore();
39  // finalize the base class
40  return Service::finalize();
41  }
42  // ==========================================================================
50  Counter* get( const std::string& group, const std::string& name ) const override;
52  ICounterSvc::Counters get( const std::string& group ) const override;
65  StatusCode create( const std::string& group, const std::string& name, longlong initial_value,
66  Counter*& refpCounter ) override;
78  CountObject create( const std::string& group, const std::string& name, longlong initial_value = 0 ) override;
88  StatusCode remove( const std::string& group, const std::string& name ) override;
94  StatusCode remove( const std::string& group ) override;
96  virtual StatusCode remove();
104  StatusCode print( const std::string& group, const std::string& name, Printout& printer ) const override;
112  StatusCode print( const std::string& group, Printout& printer ) const override;
119  StatusCode print( const Counter* pCounter, Printout& printer ) const override;
126  StatusCode print( const CountObject& pCounter, Printout& printer ) const override;
130  StatusCode print( Printout& printer ) const override;
132  StatusCode defaultPrintout( MsgStream& log, const Counter* pCounter ) const override;
133 
134 private:
135  // find group/name for the counter:
137  {
138  if ( c ) {
139  for ( const auto& i : m_counts ) {
140  auto j = std::find_if( i.second.begin(), i.second.end(),
141  [&]( const NameMap::value_type& k ) { return k.second == c; } );
142  if ( j != i.second.end() ) return {i.first, j->first};
143  }
144  }
145  return {};
146  }
147  // get the overall number of counters
148  inline size_t num() const
149  {
150  return std::accumulate( m_counts.begin(), m_counts.end(), size_t{0},
151  []( size_t r, const CountMap::value_type& i ) {
152  return r +
153  std::count_if( i.second.begin(), i.second.end(),
154  []( const NameMap::value_type& j ) -> bool { return j.second; } );
155  } );
156  }
157 
158 public:
160  void print() const;
161 
162 private:
165  // the actual map of counters
166  CountMap m_counts;
167 
168  Gaudi::Property<bool> m_print{this, "PrintStat", true, "print statistics"};
169  Gaudi::Property<std::string> m_header{this, "StatTableHeader",
170  " Counter :: Group | # | sum | "
171  "mean/eff^* | rms/err^* | min | max |",
172  "the header row for the output Stat-table"};
174  this, "RegularRowFormat",
175  " %|15.15s|%|-15.15s|%|32t||%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |",
176  "the format for the regular row in the output Stat-table"};
178  this, "EfficiencyRowFormat",
179  "*%|15.15s|%|-15.15s|%|32t||%|10d| |%|11.5g| |(%|#9.7g| +- %|-#9.7g|)%%| ------- | ------- |",
180  "the format for the regular row in the outptu Stat-table"};
181  Gaudi::Property<bool> m_useEffFormat{this, "UseEfficiencyRowFormat", true,
182  "use the special format for printout of efficiency counters"};
183 };
184 // ===========================================================================
185 // Instantiation of a static factory class used by clients
186 // ===========================================================================
188 // ===========================================================================
189 // Access a counter object by name and group
190 // ===========================================================================
191 CounterSvc::Counter* CounterSvc::get( const std::string& grp, const std::string& nam ) const
192 {
193  auto i = m_counts.find( grp );
194  if ( m_counts.end() == i ) {
195  return nullptr;
196  } // RETURN
197  auto j = i->second.find( nam );
198  if ( i->second.end() == j ) {
199  return nullptr;
200  } // RETURN
201  return j->second; // RETURN
202 }
203 // ===========================================================================
204 // get all counters form the given group:
205 // ===========================================================================
207 {
208  ICounterSvc::Counters result;
209  auto i = m_counts.find( group );
210  if ( i != m_counts.end() ) {
211  std::transform( i->second.begin(), i->second.end(), std::back_inserter( result ),
212  [&]( const NameMap::value_type& j ) {
213  return CountObject{j.second, i->first, j.first};
214  } );
215  }
216  return result;
217 }
218 // ===========================================================================
219 // Create/get a counter object.
220 // ===========================================================================
221 #ifdef __ICC
222 // disable icc remark #2259: non-pointer conversion from "longlong={long long}" to "double" may lose significant bits
223 #pragma warning( push )
224 #pragma warning( disable : 2259 )
225 #endif
226 StatusCode CounterSvc::create( const std::string& grp, const std::string& nam, longlong initial_value,
227  Counter*& refpCounter )
228 {
229  // try to find existing counter:
230  refpCounter = get( grp, nam );
231  if ( refpCounter ) {
232  return COUNTER_EXISTS;
233  } // RETURN
234  // create the new counter
235  auto newc = new Counter();
236  refpCounter = newc;
237  if ( 0 != initial_value ) {
238  refpCounter->addFlag( static_cast<double>( initial_value ) ); // icc remark #2259
239  }
240  // find a proper group
241  auto i = m_counts.find( grp );
242  // (create a group if needed)
243  if ( m_counts.end() == i ) {
244  i = m_counts.emplace( grp, NameMap() ).first;
245  }
246  // insert new counter with proper name into proper group:
247  i->second.emplace( nam, newc );
248  return StatusCode::SUCCESS; // RETURN
249 }
250 #ifdef __ICC
251 // re-enable icc remark #2259
252 #pragma warning( pop )
253 #endif
254 // ===========================================================================
255 // Create a new counter object. If the counter object exists already,
256 // ===========================================================================
257 CounterSvc::CountObject CounterSvc::create( const std::string& group, const std::string& name, longlong initial_value )
258 {
259  Counter* p = nullptr;
260  StatusCode sc = create( group, name, initial_value, p );
261  if ( sc.isSuccess() && p ) {
262  return CountObject( p, group, name );
263  }
264  throw std::runtime_error( "CounterSvc::Counter('" + group + "::" + name + "') exists already!" );
265 }
266 // ===========================================================================
267 // Remove a counter object. The tuple (group,name) identifies the counter uniquely
268 // ===========================================================================
270 {
271  auto i = m_counts.find( grp );
272  if ( m_counts.end() == i ) {
273  return COUNTER_NOT_PRESENT;
274  } // RETURN
275  auto j = i->second.find( nam );
276  if ( i->second.end() == j ) {
277  return COUNTER_NOT_PRESENT;
278  } // RETURN
279  delete j->second;
280  i->second.erase( j );
281  return StatusCode::SUCCESS;
282 }
283 // ===========================================================================
284 // Remove a group of counter objects.
285 // ===========================================================================
287 {
288  auto i = m_counts.find( grp );
289  if ( m_counts.end() == i ) {
290  return COUNTER_NOT_PRESENT;
291  } // RETURN
292  for ( auto& j : i->second ) delete j.second;
293  i->second.clear();
294  return StatusCode::SUCCESS;
295 }
296 // ===========================================================================
297 // Remove all known counter objects
298 // ===========================================================================
300 {
301  // remove group by group
302  for ( auto& i : m_counts ) remove( i.first ).ignore();
303  m_counts.clear();
304  return StatusCode::SUCCESS;
305 }
306 // ===========================================================================
307 // Print counter value
308 // ===========================================================================
309 StatusCode CounterSvc::print( const std::string& grp, const std::string& nam, Printout& printer ) const
310 {
311  const Counter* c = get( grp, nam );
312  if ( !c ) {
313  return COUNTER_NOT_PRESENT;
314  } // RETURN
315  // create the stream and use it!
316  return printer( msgStream(), c );
317 }
318 
319 namespace
320 {
322  class conditionalPrint
323  {
324  private:
325  CounterSvc::Printout* printer;
326  MsgStream* log;
327 
328  public:
329  conditionalPrint( CounterSvc::Printout& _p, MsgStream& _l ) : printer( &_p ), log( &_l ) {}
330  template <class Pair>
331  void operator()( const Pair& p )
332  {
333  if ( p.second ) {
334  ( *printer )( *log, p.second ).ignore();
335  }
336  }
337  };
338 }
339 // ===========================================================================
340 // Print the counter value for the whole group of counters
341 // ===========================================================================
342 StatusCode CounterSvc::print( const std::string& grp, Printout& printer ) const
343 {
344  auto i = m_counts.find( grp );
345  if ( m_counts.end() == i ) {
346  return COUNTER_NOT_PRESENT;
347  }
348 
349  // Force printing in alphabetical order
350  std::map<std::string, Counter*> sorted_map( i->second.begin(), i->second.end() );
351  std::for_each( sorted_map.begin(), sorted_map.end(), conditionalPrint( printer, msgStream() ) );
352  return StatusCode::SUCCESS; // RETURN
353 }
354 // ===========================================================================
355 // Print counter value
356 // ===========================================================================
357 StatusCode CounterSvc::print( const Counter* pCounter, Printout& printer ) const
358 {
359  return printer( msgStream(), pCounter );
360 }
361 // ===========================================================================
362 // Print counter value
363 // ===========================================================================
364 StatusCode CounterSvc::print( const CountObject& refCounter, Printout& printer ) const
365 {
366  return print( refCounter.counter(), printer );
367 }
368 // ===========================================================================
369 // Print all known counters
370 // ===========================================================================
371 StatusCode CounterSvc::print( Printout& printer ) const
372 {
373  // Force printing in alphabetical order
375  for ( const auto& i : m_counts )
376  for ( const auto& j : i.second ) sorted_map[{i.first, j.first}] = j.second;
377  std::for_each( sorted_map.begin(), sorted_map.end(), conditionalPrint( printer, msgStream() ) );
378  return StatusCode::SUCCESS;
379 }
380 // ===========================================================================
381 // Print counter value
382 // ===========================================================================
384 {
385  if ( !c ) {
386  return StatusCode::FAILURE;
387  }
388  auto p = _find( c );
389 
390  log << MSG::ALWAYS << CountObject( const_cast<Counter*>( c ), p.first, p.second ) << endmsg;
391 
392  return StatusCode::SUCCESS;
393 }
394 // ===========================================================================
395 // "standard" printout a'la GaudiCommon
396 // ===========================================================================
397 void CounterSvc::print() const
398 {
399  // number of counters
400  const auto _num = num();
401  if ( 0 != _num ) {
402  always() << "Number of counters : " << _num << endmsg << m_header.value() << endmsg;
403  }
404  // Force printing in alphabetical order
406  for ( const auto& i : m_counts ) {
407  for ( const auto& j : i.second ) {
408  if ( j.second ) sorted_map[{i.first, j.first}] = j.second;
409  }
410  }
411  for ( const auto& i : sorted_map ) {
412  always() << Gaudi::Utils::formatAsTableRow( i.first.second, i.first.first, *i.second, m_useEffFormat, m_format1,
413  m_format2 )
414  << endmsg;
415  }
416 }
417 // ============================================================================
418 
419 // ============================================================================
420 // The END
421 // ============================================================================
Gaudi::Property< bool > m_useEffFormat
Definition: CounterSvc.cpp:181
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
virtual StatusCode remove()
Remove all known counter objects.
Definition: CounterSvc.cpp:299
Gaudi::Property< bool > m_print
Definition: CounterSvc.cpp:168
const std::string & name() const override
Retrieve name of the service.
Definition: Service.cpp:289
std::pair< iterator, bool > emplace(Args &&...args)
Definition: Map.h:166
StatusCode finalize() override
Definition: Service.cpp:174
Implementation of property with value of concrete type.
Definition: Property.h:314
GaudiUtils::HashMap< std::string, Counter * > NameMap
Definition: CounterSvc.cpp:163
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:74
Gaudi::Property< std::string > m_format1
Definition: CounterSvc.cpp:173
Gaudi::Property< std::string > m_header
Definition: CounterSvc.cpp:169
STL namespace.
T end(T...args)
Simple implementation of the abstract interface ICounterSvc.
Definition: CounterSvc.cpp:25
STL class.
Gaudi::Property< std::string > m_format2
Definition: CounterSvc.cpp:177
StatusCode defaultPrintout(MsgStream &log, const Counter *pCounter) const override
Default Printout for counters.
Definition: CounterSvc.cpp:383
#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:226
iterator end()
Definition: Map.h:132
GaudiUtils::HashMap< std::string, NameMap > CountMap
Definition: CounterSvc.cpp:164
void print() const
"standard" printout a&#39;la GaudiCommon
Definition: CounterSvc.cpp:397
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:166
iterator find(const key_type &key)
Definition: Map.h:149
std::pair< std::string, std::string > _find(const Counter *c) const
Definition: CounterSvc.cpp:136
T count_if(T...args)
iterator begin()
Definition: Map.h:131
T find_if(T...args)
STL class.
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
T begin(T...args)
T back_inserter(T...args)
Common class providing an architecture-independent hash map.
Definition: HashMap.h:77
MsgStream & msgStream() const
Return an uninitialized MsgStream.
T transform(T...args)
Counter * get(const std::string &group, const std::string &name) const override
Access an existing counter object.
Definition: CounterSvc.cpp:191
T accumulate(T...args)
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:148
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:31
StatusCode finalize() override
Finalization.
Definition: CounterSvc.cpp:33