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