Gaudi Framework, version v23r4

Home   Generated: Mon Sep 17 2012

GoogleAuditor.cpp

Go to the documentation of this file.
00001 
00002 #include <vector>
00003 #include <string>
00004 #include <utility>
00005 #include <memory>
00006 #include <algorithm>
00007 
00008 #include "GaudiKernel/AudFactory.h"
00009 #include "GaudiKernel/Auditor.h"
00010 #include "GaudiKernel/IAuditorSvc.h"
00011 #include "GaudiKernel/GaudiException.h"
00012 #include "GaudiKernel/MsgStream.h"
00013 #include "GaudiKernel/IIncidentListener.h"
00014 #include "GaudiKernel/IIncidentSvc.h"
00015 
00016 #include "GaudiAlg/GaudiSequencer.h"
00017 #include "GaudiAlg/Sequencer.h"
00018 
00019 #include "boost/assign/list_of.hpp"
00020 
00021 #include "google/heap-profiler.h"
00022 #include "google/heap-checker.h"
00023 #include "google/profiler.h"
00024 
00025 namespace Google
00026 {
00027 
00035   class AuditorBase : public extends1<Auditor, IIncidentListener>
00036   {
00037 
00038   public:
00039 
00041     AuditorBase( const std::string& name, ISvcLocator* pSvcLocator);
00042 
00044     virtual ~AuditorBase() {  }
00045 
00047     StatusCode initialize()
00048     {
00049       m_log << MSG::INFO << "Initialised" << endmsg;
00050 
00051       SmartIF<IIncidentSvc> inSvc(serviceLocator()->service("IncidentSvc"));
00052       if ( ! inSvc.isValid() ) return StatusCode::FAILURE;
00053 
00054       inSvc->addListener( this, IncidentType::BeginEvent );
00055 
00056       return StatusCode::SUCCESS;
00057     }
00058 
00060     StatusCode finalize()
00061     {
00062       if ( alreadyRunning() ) stopAudit();
00063       return StatusCode::SUCCESS;
00064     }
00065 
00066   private:
00067 
00069     void startAudit()
00070     {
00071       m_log << MSG::INFO << " -> Starting full audit from event " << m_nEvts << " to "
00072             << m_nEvts+m_nSampleEvents << endmsg;
00073       m_inFullAudit = true;
00074       m_sampleEventCount = 1;
00075       std::ostringstream t;
00076       t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
00077       google_before(t.str());
00078     }
00079 
00081     void stopAudit()
00082     {
00083       m_log << MSG::INFO << " -> Stopping full audit" << endmsg;
00084       std::ostringstream t;
00085       t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
00086       google_after(t.str());
00087       m_inFullAudit = false;
00088       m_sampleEventCount = 0;
00089     }
00090 
00093     bool isSequencer( INamedInterface* i ) const
00094     {
00095       return ( dynamic_cast<GaudiSequencer*>(i) != NULL ||
00096                dynamic_cast<Sequencer*>(i)      != NULL );
00097     }
00098 
00099   public:
00100 
00106     void handle( const Incident& incident )
00107     {
00108       if ( IncidentType::BeginEvent == incident.type() )
00109       {
00110         ++m_nEvts;
00111         m_audit = ( m_nEvts > m_eventsToSkip &&
00112                     ( m_freq < 0            ||
00113                       m_nEvts == 1          ||
00114                       m_nEvts % m_freq == 0  ) );
00115         m_log << MSG::DEBUG << "Event " << m_nEvts
00116               << " Audit=" << m_audit << endmsg;
00117         if ( m_fullEventAudit )
00118         {
00119           if ( m_inFullAudit )
00120           {
00121             if ( m_sampleEventCount >= m_nSampleEvents &&
00122                  alreadyRunning() )
00123             {
00124               stopAudit();
00125             }
00126             else
00127             {
00128               ++m_sampleEventCount;
00129             }
00130           }
00131           if ( m_audit && !m_inFullAudit && !alreadyRunning() )
00132           {
00133             startAudit();
00134           }
00135         }
00136       }
00137     }
00138 
00139   public:
00140 
00141     void before(StandardEventType type, INamedInterface* i)
00142     {
00143       if ( !m_skipSequencers || !isSequencer(i) )
00144       {
00145         before(type,i->name());
00146       }
00147     }
00148 
00149     void before(CustomEventTypeRef type, INamedInterface* i)
00150     {
00151       if ( !m_skipSequencers || !isSequencer(i) )
00152       {
00153         before(type,i->name());
00154       }
00155     }
00156 
00157     void before(StandardEventType type, const std::string& s)
00158     {
00159       std::ostringstream t;
00160       t << type;
00161       before(t.str(),s);
00162     }
00163 
00164     void before(CustomEventTypeRef, const std::string& s)
00165     {
00166       if ( !m_fullEventAudit && m_audit &&
00167            std::find(m_veto.begin(),m_veto.end(),s) == m_veto.end() &&
00168            ( m_list.empty() || std::find(m_list.begin(),m_list.end(),s) != m_list.end() ) )
00169       {
00170         if ( !alreadyRunning() )
00171         {
00172           m_log << MSG::INFO << "Starting Auditor for " << s << endmsg;
00173           m_startedBy = s;
00174           std::ostringstream t;
00175           t << s << "-Event" << m_nEvts;
00176           google_before(t.str());
00177         }
00178         else
00179         {
00180           m_log << MSG::WARNING
00181                 << "Auditor already running. Cannot be started for " << s
00182                 << endmsg;
00183         }
00184       }
00185     }
00186 
00187     void after(StandardEventType type, INamedInterface* i, const StatusCode& sc)
00188     {
00189       if ( !m_skipSequencers || !isSequencer(i) )
00190       {
00191         std::ostringstream t;
00192         t << type;
00193         after(t.str(),i,sc);
00194       }
00195     }
00196 
00197     void after(CustomEventTypeRef type, INamedInterface* i, const StatusCode& sc)
00198     {
00199       if ( !m_skipSequencers || !isSequencer(i) )
00200       {
00201         after(type,i->name(),sc);
00202       }
00203     }
00204 
00205     void after(StandardEventType type, const std::string& s, const StatusCode& sc)
00206     {
00207       std::ostringstream t;
00208       t << type;
00209       after(t.str(),s,sc);
00210     }
00211 
00212     void after(CustomEventTypeRef, const std::string& s, const StatusCode&)
00213     {
00214       if ( !m_fullEventAudit && m_audit &&
00215            std::find(m_veto.begin(),m_veto.end(),s) == m_veto.end() &&
00216            ( m_list.empty() || std::find(m_list.begin(),m_list.end(),s) != m_list.end() ) )
00217       {
00218         if ( s == m_startedBy )
00219         {
00220           std::ostringstream t;
00221           t << s << "-Event" << m_nEvts;
00222           google_after(t.str());
00223         }
00224       }
00225     }
00226 
00227     // Obsolete methods
00228     void beforeInitialize  (INamedInterface *i) { return before(IAuditor::Initialize,i);   }
00229     void beforeReinitialize(INamedInterface *i) { return before(IAuditor::ReInitialize,i); }
00230     void beforeExecute     (INamedInterface *i) { return before(IAuditor::Execute,i);      }
00231     void beforeBeginRun    (INamedInterface *i) { return before(IAuditor::BeginRun,i);     }
00232     void beforeEndRun      (INamedInterface *i) { return before(IAuditor::EndRun,i);       }
00233     void beforeFinalize    (INamedInterface *i) { return before(IAuditor::Finalize,i);     }
00234 
00235     void afterInitialize   (INamedInterface *i) { return after(IAuditor::Initialize,i,StatusCode::SUCCESS); }
00236     void afterReinitialize (INamedInterface *i) { return after(IAuditor::ReInitialize,i,StatusCode::SUCCESS); }
00237     void afterExecute      (INamedInterface *i, const StatusCode& s) { return after(IAuditor::Execute,i,s); }
00238     void afterBeginRun     (INamedInterface *i) { return after(IAuditor::BeginRun,i,StatusCode::SUCCESS); }
00239     void afterEndRun       (INamedInterface *i) { return after(IAuditor::EndRun,i,StatusCode::SUCCESS); }
00240     void afterFinalize     (INamedInterface *i) { return after(IAuditor::Finalize,i,StatusCode::SUCCESS); }
00241 
00242   protected:
00243 
00245     virtual void google_before(const std::string& s) = 0;
00246 
00248     virtual void google_after(const std::string& s) = 0;
00249 
00251     virtual bool alreadyRunning() = 0;
00252 
00253   protected:
00254 
00255     mutable MsgStream         m_log;   
00256 
00257   private:
00258 
00259     std::vector<std::string>  m_when;  
00260     std::vector<std::string>  m_veto;  
00261     std::vector<std::string>  m_list;  
00262 
00263     unsigned long long m_eventsToSkip; 
00264 
00265     bool m_skipSequencers; 
00266 
00267     int m_freq;   
00268 
00269     bool m_audit; 
00270 
00271     unsigned long long m_nEvts; 
00272 
00273     bool m_fullEventAudit; 
00274 
00275     unsigned long long m_nSampleEvents; 
00276 
00277     unsigned long long m_sampleEventCount; 
00278 
00279     bool m_inFullAudit; 
00280 
00281     std::string m_startedBy; 
00282 
00283   };
00284 
00285   AuditorBase::AuditorBase( const std::string& name,
00286                             ISvcLocator* pSvcLocator )
00287     : base_class ( name , pSvcLocator )
00288     , m_log      ( msgSvc() , name )
00289     , m_audit    ( false )
00290     , m_nEvts    ( 0 )
00291     , m_sampleEventCount( 0 )
00292     , m_inFullAudit ( false )
00293   {
00294     m_when =
00295 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
00296       {
00297         "Initialize",
00298         "ReInitialize",
00299         "Execute",
00300         "BeginRun",
00301         "EndRun",
00302         "Finalize"
00303       }
00304 #else
00305       boost::assign::list_of
00306         ("Initialize")
00307         ("ReInitialize")
00308         ("Execute")
00309         ("BeginRun")
00310         ("EndRun")
00311         ("Finalize")
00312 #endif
00313     ;
00314     declareProperty("ActivateAt", m_when,
00315                     "List of phases to activate the Auditoring during" );
00316     declareProperty("DisableFor", m_veto,
00317                     "List of component names to disable the auditing for" );
00318     declareProperty("EnableFor", m_list );
00319     declareProperty("ProfileFreq", m_freq = -1,
00320                     "The frequence to audit events. -1 means all events" );
00321     declareProperty("DoFullEventProfile", m_fullEventAudit = false,
00322                     "If true, instead of individually auditing components, the full event (or events) will be audited in one go" );
00323     declareProperty("FullEventNSampleEvents", m_nSampleEvents = 1,
00324                     "The number of events to include in a full event audit, if enabled" );
00325     declareProperty("SkipEvents", m_eventsToSkip = 0,
00326                     "Number of events to skip before activating the auditing" );
00327     declareProperty("SkipSequencers", m_skipSequencers = true,
00328                     "If true, auditing will be skipped for Sequencer objects." );
00329   }
00330 
00344   class HeapProfiler : public AuditorBase
00345   {
00346 
00347   public:
00348 
00350     HeapProfiler( const std::string& name, ISvcLocator* pSvcLocator)
00351       : AuditorBase( name, pSvcLocator )
00352     {
00353       declareProperty( "DumpHeapProfiles",    m_dumpProfileHeaps   = true  );
00354       declareProperty( "PrintProfilesToLog",  m_printProfilesToLog = false );
00355     }
00356 
00357   protected:
00358 
00359     void google_before(const std::string& s)
00360     {
00361       HeapProfilerStart(s.c_str());
00362     }
00363 
00364     void google_after(const std::string& s)
00365     {
00366       if ( m_dumpProfileHeaps )
00367       {
00368         HeapProfilerDump(s.c_str());
00369       }
00370       if ( m_printProfilesToLog )
00371       {
00372         const char * profile = GetHeapProfile();
00373         m_log << MSG::INFO << profile << endmsg;
00374         delete profile;
00375       }
00376       HeapProfilerStop();
00377     }
00378 
00379     bool alreadyRunning() { return IsHeapProfilerRunning(); }
00380 
00381   private:
00382 
00383     bool m_dumpProfileHeaps;
00384     bool m_printProfilesToLog;
00385 
00386   };
00387 
00401   class HeapChecker : public AuditorBase
00402   {
00403 
00404   public:
00405 
00407     HeapChecker( const std::string& name, ISvcLocator* pSvcLocator)
00408       : AuditorBase ( name, pSvcLocator ),
00409         m_enabled   ( true ),
00410         m_checker   ( NULL )
00411     { }
00412 
00413     virtual ~HeapChecker() { delete m_checker; }
00414 
00415   public:
00416 
00417     StatusCode initialize()
00418     {
00419       const StatusCode sc = AuditorBase::initialize();
00420       if ( sc.isFailure() ) return sc;
00421 
00422       const char * HEAPCHECK = getenv("HEAPCHECK");
00423       if ( !HEAPCHECK )
00424       {
00425         m_log << MSG::FATAL
00426               << "Environment variable HEAPCHECK must be set to 'local'"
00427               << endmsg;
00428         return StatusCode::FAILURE;
00429       }
00430       if ( std::string(HEAPCHECK) != "local" )
00431       {
00432         m_log << MSG::WARNING
00433               << "Environment variable HEAPCHECK is set to " << HEAPCHECK
00434               << " Partial Program Heap Checking is disabled"
00435               << endmsg;
00436         m_enabled = false;
00437       }
00438 
00439       return sc;
00440     }
00441 
00442   protected:
00443 
00444     void google_before(const std::string& s)
00445     {
00446       if ( m_enabled && !m_checker )
00447       {
00448         m_checker = new HeapLeakChecker(s.c_str());
00449       }
00450     }
00451 
00452     void google_after(const std::string& s)
00453     {
00454       if ( m_enabled && m_checker )
00455       {
00456         if ( ! m_checker->NoLeaks() )
00457         {
00458           m_log << MSG::WARNING << "Leak detected for " << s << endmsg;
00459         }
00460         delete m_checker;
00461         m_checker = NULL;
00462       }
00463     }
00464 
00465     bool alreadyRunning() { return m_enabled && m_checker != NULL ; }
00466 
00467   private:
00468 
00469     bool m_enabled;
00470     HeapLeakChecker * m_checker;
00471 
00472   };
00473 
00487   class CPUProfiler : public AuditorBase
00488   {
00489 
00490   public:
00491 
00492     CPUProfiler( const std::string& name, ISvcLocator* pSvcLocator )
00493       : AuditorBase ( name, pSvcLocator ),
00494         m_running   ( false )
00495     { }
00496 
00497   protected:
00498 
00499     void google_before(const std::string& s)
00500     {
00501       if ( !m_running )
00502       {
00503         m_running = true;
00504         ProfilerStart((s+".prof").c_str());
00505       }
00506     }
00507 
00508     void google_after(const std::string&)
00509     {
00510       if ( m_running )
00511       {
00512         ProfilerStop();
00513         m_running = false;
00514       }
00515     }
00516 
00517     bool alreadyRunning() { return m_running; }
00518 
00519   private:
00520 
00521     bool m_running;
00522 
00523   };
00524 
00525   DECLARE_AUDITOR_FACTORY( HeapProfiler )
00526   DECLARE_AUDITOR_FACTORY( HeapChecker  )
00527   DECLARE_AUDITOR_FACTORY( CPUProfiler  )
00528 
00529 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Mon Sep 17 2012 13:49:35 for Gaudi Framework, version v23r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004