| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# CounterSvc.cpp

Go to the documentation of this file.

    00001 // $Id: CounterSvc.cpp,v 1.6 2007/09/24 19:15:57 marcocle Exp $
    00002 // ============================================================================
    00003 // CVS tag $Name:  $, verison $Revision: 1.6 $
    00004 // ============================================================================
    00005 // STD & SLT
    00006 // ============================================================================
    00007 #include <utility>
    00008 #include <vector>
    00009 #include <algorithm>
    00010 #include <functional>
    00011 // ============================================================================
    00012 // GaudiKernel
    00013 // ============================================================================
    00014 #include "GaudiKernel/ICounterSvc.h"
    00015 #include "GaudiKernel/ISvcLocator.h"
    00016 #include "GaudiKernel/SvcFactory.h"
    00017 #include "GaudiKernel/MsgStream.h"
    00018 #include "GaudiKernel/Service.h"
    00019 #include "GaudiKernel/HashMap.h"
    00020 // ============================================================================
    00027 class CounterSvc
    00028   : virtual public ICounterSvc
    00029   , public             Service
    00030 {
    00031 public:
    00033   CounterSvc ( const std::string& name   ,
    00034                ISvcLocator*       svcLoc )
    00035     : Service(name, svcLoc)
    00036     , m_counts ()
    00037     , m_print  ( true )
    00038     //
    00039     // the header row
    00040     , m_header  ( "       Counter :: Group         |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |")
    00041     // format for regular statistical printout rows
    00042     , m_format1 ( " %|15.15s|%|-15.15s|%|32t||%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |"         )
    00043     // format for "efficiency" statistical printout rows
    00044     , m_format2 ( "*%|15.15s|%|-15.15s|%|32t||%|10d| |%|11.5g| |(%|#9.7g| +- %|-#9.7g|)%%|   -------   |   -------   |" )
    00045     // flag to use the special "efficiency" format
    00046     , m_useEffFormat ( true )
    00047     //
    00048   {
    00049     declareProperty ("PrintStat" , m_print ) ;
    00050     //
    00051     declareProperty
    00052       ( "StatTableHeader"        , m_header                          ,
    00053         "The header row for the output Stat-table"                   ) ;
    00054     //
    00055     declareProperty
    00056       ( "RegularRowFormat"       , m_format1                         ,
    00057         "The format for the regular row in the output Stat-table"    ) ;
    00058     //
    00059     declareProperty
    00060       ( "EfficiencyRowFormat"    , m_format2                         ,
    00061         "The format for the regular row in the outptu Stat-table"    ) ;
    00062     //
    00063     declareProperty
    00064       ( "UseEfficiencyRowFormat" , m_useEffFormat                    ,
    00065         "Use the special format for printout of efficiency counters" ) ;
    00066   }
    00068   virtual ~CounterSvc() { remove().ignore() ; };
    00070   virtual StatusCode queryInterface
    00071   ( const InterfaceID& riid , void** ppvI )
    00072   {
    00073     // valid placeholder?
    00074     if ( 0 == ppvI ) { return StatusCode::FAILURE ; }  // RETURN
    00075     if ( ICounterSvc::interfaceID() == riid )
    00076     {
    00077       *ppvI = static_cast<ICounterSvc*>(this);
    00078       addRef(); // NB! : inrement the reference count!
    00079       return StatusCode::SUCCESS;                     // RETURN
    00080     }
    00081     // Interface is not directly availible: try out a base class
    00082     return Service::queryInterface( riid, ppvI );
    00083   }
    00085   virtual StatusCode finalize()
    00086   {
    00087     if ( outputLevel() <= MSG::DEBUG || m_print ) { print () ; }
    00088     remove().ignore() ;
    00089     // finalize the base class
    00090     return Service::finalize() ;
    00091   }
    00092   // ==========================================================================
    00100   virtual Counter* get
    00101   ( const std::string& group ,
    00102     const std::string& name  ) const;
    00104   virtual ICounterSvc::Counters get ( const std::string& group ) const ;
    00117   virtual StatusCode create
    00118   ( const std::string& group ,
    00119     const std::string& name  ,
    00120     longlong initial_value   ,
    00121     Counter*& refpCounter    ) ;
    00133   virtual CountObject create
    00134   ( const std::string& group    ,
    00135     const std::string& name     ,
    00136     longlong initial_value = 0  ) ;
    00146   virtual StatusCode remove
    00147   ( const std::string& group ,
    00148     const std::string& name  ) ;
    00154   virtual StatusCode remove
    00155   ( const std::string& group ) ;
    00157   virtual StatusCode remove();
    00165   virtual StatusCode print
    00166   ( const std::string& group,
    00167     const std::string& name,
    00168     Printout& printer) const;
    00176   virtual StatusCode print
    00177   (const std::string& group,
    00178    Printout& printer) const;
    00185   virtual StatusCode print
    00186   ( const Counter* pCounter,
    00187     Printout& printer) const;
    00194   virtual StatusCode print
    00195   ( const CountObject& pCounter,
    00196     Printout& printer) const;
    00200   virtual StatusCode print(Printout& printer) const;
    00202   virtual StatusCode defaultPrintout
    00203   ( MsgStream& log,
    00204     const Counter* pCounter) const ;
    00205 private:
    00206   // find group/name for the counter:
    00207   inline std::pair<std::string,std::string> _find ( const Counter* c ) const
    00208   {
    00209     if ( 0 == c ) { return std::pair<std::string,std::string>() ; }
    00210     for ( CountMap::const_iterator i = m_counts.begin() ; m_counts.end() != i ; ++i )
    00211     {
    00212       for ( NameMap::const_iterator j = i->second.begin() ; i->second.end() != j ; ++j )
    00213       { if ( j->second == c ) { return std::make_pair( i->first , j->first )  ; } }
    00214     }
    00215     return std::pair<std::string,std::string>() ;
    00216   }
    00217   // get the overall number of counters
    00218   inline size_t num () const
    00219   {
    00220     size_t result = 0 ;
    00221     {
    00222       for ( CountMap::const_iterator i = m_counts.begin(); i != m_counts.end(); ++i )
    00223       {
    00224         for ( NameMap::const_iterator j = i->second.begin() ; i->second.end() != j ; ++j )
    00225         { if ( 0 != j->second ) { ++result ; } ; }
    00226       }
    00227     }
    00228     return result ;
    00229   }
    00230 public:
    00232   void print () const ;
    00233 private:
    00234   typedef GaudiUtils::HashMap<std::string,Counter*> NameMap  ;
    00235   typedef GaudiUtils::HashMap<std::string,NameMap>  CountMap ;
    00236   // the actual map of counters
    00237   CountMap m_counts ;
    00238   // boolean flag to print statistics
    00239   bool     m_print  ;
    00240   // the header row
    00241   std::string    m_header  ;
    00242   // format for regular statistical printout rows
    00243   std::string    m_format1 ;
    00244   // format for "efficiency" statistical printout rows
    00245   std::string    m_format2 ;
    00246   // flag to use the special "efficiency" format
    00247   bool           m_useEffFormat ;
    00248 } ;
    00249 // ===========================================================================
    00250 // Instantiation of a static factory class used by clients
    00251 // ===========================================================================
    00252 DECLARE_SERVICE_FACTORY(CounterSvc)
    00253 // ===========================================================================
    00254 // Access a counter object by name and group
    00255 // ===========================================================================
    00256 CounterSvc::Counter* CounterSvc::get
    00257 ( const std::string& grp  ,
    00258   const std::string& nam  ) const
    00259 {
    00260   CountMap::const_iterator i = m_counts.find  ( grp ) ;
    00261   if (  m_counts.end() == i ) { return 0 ; }                    // RETURN
    00262   NameMap::const_iterator  j = i->second.find ( nam ) ;
    00263   if ( i->second.end() == j ) { return 0 ; }                    // RETURN
    00264   return j->second ;                                            // RETURN
    00265 }
    00266 // ===========================================================================
    00267 // get all counters form the given group:
    00268 // ===========================================================================
    00269 ICounterSvc::Counters CounterSvc::get ( const std::string& group ) const
    00270 {
    00271   ICounterSvc::Counters result ;
    00272   CountMap::const_iterator i = m_counts.find  ( group ) ;
    00273   if (  m_counts.end() == i ) { return result ; } // RETURN
    00274   for ( NameMap::const_iterator j = i->second.begin() ; i->second.end() != j ; ++j )
    00275   { result.push_back( CountObject ( j->second, i->first , j->first ) ) ; }
    00276   return result ;
    00277 }
    00278 // ===========================================================================
    00279 // Create/get a counter object.
    00280 // ===========================================================================
    00281 StatusCode CounterSvc::create
    00282 ( const std::string& grp ,
    00283   const std::string& nam ,
    00284   longlong initial_value ,
    00285   Counter*& refpCounter  )
    00286 {
    00287   // try to find existing counter:
    00288   refpCounter = get ( grp , nam ) ;
    00289   if ( 0 != refpCounter ) { return COUNTER_EXISTS ; }                // RETURN
    00290   // create the new counter
    00291   Counter* newc = new Counter() ;
    00292   refpCounter = newc ;
    00293   if ( 0 != initial_value ) {
    00294         refpCounter->addFlag ( static_cast<double>(initial_value) ) ;
    00295   }
    00296   // find a proper group
    00297   CountMap::iterator i = m_counts.find  ( grp ) ;
    00298   // (create a group if needed)
    00299   if (  m_counts.end() == i )
    00300   { i = m_counts.insert ( std::make_pair ( grp , NameMap() ) ).first ; }
    00301   // insert new counter with priper name into proper group:
    00302   i->second.insert( std::make_pair( nam , newc ) ).first ;
    00303   return StatusCode::SUCCESS ;                                     // RETURN
    00304 }
    00305 // ===========================================================================
    00306 // Create a new counter object. If the counter object exists already,
    00307 // ===========================================================================
    00308 CounterSvc::CountObject CounterSvc::create
    00309 ( const std::string& group ,
    00310   const std::string& name  ,
    00311   longlong initial_value   )
    00312 {
    00313   Counter* p = 0;
    00314   StatusCode sc = create ( group, name, initial_value, p ) ;
    00315   if ( sc.isSuccess() && 0 != p ) { return CountObject ( p , group , name ) ; }
    00316   throw std::runtime_error("CounterSvc::Counter('"+group+"::"+name+"') exists already!");
    00317 }
    00318 // ===========================================================================
    00319 // Remove a counter object. The tuple (group,name) identifies the counter uniquely
    00320 // ===========================================================================
    00321 StatusCode CounterSvc::remove
    00322 ( const std::string& grp ,
    00323   const std::string& nam )
    00324 {
    00325   CountMap::iterator i = m_counts.find  ( grp ) ;
    00326   if (  m_counts.end() == i ) { return COUNTER_NOT_PRESENT ; }  // RETURN
    00327   NameMap::iterator  j = i->second.find ( nam ) ;
    00328   if ( i->second.end() == j ) { return COUNTER_NOT_PRESENT ; }  // RETURN
    00329   delete j->second ;
    00330   i->second.erase ( j ) ;
    00331   return StatusCode::SUCCESS ;
    00332 }
    00333 // ===========================================================================
    00334 // Remove a group of counter objects.
    00335 // ===========================================================================
    00336 StatusCode CounterSvc::remove ( const std::string& grp )
    00337 {
    00338   CountMap::iterator i = m_counts.find ( grp  ) ;
    00339   if (  m_counts.end() == i ) { return COUNTER_NOT_PRESENT ; }  // RETURN
    00340   for ( NameMap::iterator j = i->second.begin() ; i->second.end() != j ; ++j )
    00341   { delete j->second ; }
    00342   i->second.clear() ;
    00343   return StatusCode::SUCCESS ;
    00344 }
    00345 // ===========================================================================
    00346 // Remove all known counter objects
    00347 // ===========================================================================
    00348 StatusCode CounterSvc::remove()
    00349 {
    00350   // remove group by group
    00351   for ( CountMap::iterator i = m_counts.begin() ; m_counts.end() != i ; ++i )
    00352   { remove ( i->first ).ignore () ; }
    00353   m_counts.clear() ;
    00354   return StatusCode::SUCCESS;
    00355 }
    00356 // ===========================================================================
    00357 // Print counter value
    00358 // ===========================================================================
    00359 StatusCode CounterSvc::print
    00360 ( const std::string& grp,
    00361   const std::string& nam,
    00362   Printout& printer) const
    00363 {
    00364   const Counter* c = get( grp , nam ) ;
    00365   if ( 0 == c ) { return COUNTER_NOT_PRESENT ; }                  // RETURN
    00366   // create the stream and use it!
    00367   MsgStream log ( msgSvc() , name() ) ;
    00368   return printer ( log , c ) ;
    00369 }
    00370 // ===========================================================================
    00371 // Print the counter valuee for thre whole group of counters
    00372 // ===========================================================================
    00373 StatusCode CounterSvc::print
    00374 ( const std::string& grp ,
    00375   Printout& printer      ) const
    00376 {
    00377   CountMap::const_iterator i = m_counts.find ( grp ) ;
    00378   if ( m_counts.end() == i ) { return COUNTER_NOT_PRESENT ; }
    00379   MsgStream log(msgSvc(), name());
    00380   for ( NameMap::const_iterator  j = i->second.begin() ; i->second.end() != j ; ++j )
    00381   { printer ( log , j->second ).ignore() ; }
    00382   //
    00383   return StatusCode::SUCCESS;   // RETURN
    00384 }
    00385 // ===========================================================================
    00386 // Print counter value
    00387 // ===========================================================================
    00388 StatusCode CounterSvc::print
    00389 ( const Counter* pCounter,
    00390   Printout& printer ) const
    00391 {
    00392   MsgStream log(msgSvc(), name() ) ;
    00393   return printer ( log , pCounter ) ;
    00394 }
    00395 // ===========================================================================
    00396 // Print counter value
    00397 // ===========================================================================
    00398 StatusCode CounterSvc::print
    00399 ( const CountObject& refCounter,
    00400   Printout& printer) const
    00401 { return print( refCounter.counter() , printer ) ; }
    00402 // ===========================================================================
    00403 // Print all known counters
    00404 // ===========================================================================
    00405 StatusCode CounterSvc::print( Printout& printer ) const
    00406 {
    00407   MsgStream log ( msgSvc() , name() ) ;
    00408   for( CountMap::const_iterator i = m_counts.begin(); i != m_counts.end(); ++i)
    00409   {
    00410     for ( NameMap::const_iterator j = i->second.begin() ; i->second.end() != j ; ++j )
    00411     { printer ( log , j->second ).ignore() ; }
    00412   }
    00413   return StatusCode::SUCCESS;
    00414 }
    00415 // ===========================================================================
    00416 // Print counter value
    00417 // ===========================================================================
    00418 StatusCode CounterSvc::defaultPrintout
    00419 ( MsgStream& log,
    00420   const Counter* c ) const
    00421 {
    00422   if ( 0 == c ) { return StatusCode::FAILURE ; }
    00423   std::pair<std::string,std::string> p = _find ( c ) ;
    00424
    00425   log << MSG::ALWAYS
    00426       << CountObject( const_cast<Counter*>(c) , p.first , p.second )
    00427       << endreq ;
    00428
    00429   return StatusCode::SUCCESS;
    00430 }
    00431 // ===========================================================================
    00432 // "standard" printout a'la GaudiCommon
    00433 // ===========================================================================
    00434 void CounterSvc::print () const
    00435 {
    00436   MsgStream log ( msgSvc() , name() ) ;
    00437   // number of counters
    00438   const size_t _num = num() ;
    00439   if ( 0 != _num )
    00440   {
    00441     log << MSG::ALWAYS
    00442         << "Number of counters : "  << _num << endreq
    00443         << m_header << endreq ;
    00444   }
    00445   for ( CountMap::const_iterator i = m_counts.begin(); i != m_counts.end(); ++i )
    00446   {
    00447     for ( NameMap::const_iterator j = i->second.begin() ; i->second.end() != j ; ++j )
    00448     {
    00449       Counter* c = j->second ;
    00450       if ( 0 == c ) { continue ; }
    00451       log <<
    00452         Gaudi::Utils::formatAsTableRow
    00453         ( j->first , i->first , *c , m_useEffFormat , m_format1 , m_format2 )
    00454           << endreq ;
    00455     }
    00456   }
    00457 }
    00458 // ============================================================================
    00459
    00460 // ============================================================================
    00461 // The END
    00462 // ============================================================================