Gaudi Framework, version v21r7

Home   Generated: 22 Jan 2010

IncidentSvc.cpp

Go to the documentation of this file.
00001 // $Id: $
00002 // ============================================================================
00003 #ifdef _WIN32
00004 // ============================================================================
00005 // Avoid conflicts between windows and the message service.
00006 // ============================================================================
00007 #define NOMSG
00008 #define NOGDI
00009 #endif
00010 // ============================================================================
00011 // Include Files
00012 // ============================================================================
00013 #include "GaudiKernel/MsgStream.h"
00014 #include "GaudiKernel/ISvcLocator.h"
00015 #include "GaudiKernel/SmartIF.h"
00016 #include "GaudiKernel/IIncidentListener.h"
00017 #include "GaudiKernel/Incident.h"
00018 #include "GaudiKernel/GaudiException.h"
00019 #include "GaudiKernel/LockedChrono.h"
00020 // ============================================================================
00021 // Local 
00022 // ============================================================================
00023 #include "IncidentSvc.h"
00024 // ============================================================================
00025 // Instantiation of a static factory class used by clients to create
00026 //  instances of this service
00027 DECLARE_SERVICE_FACTORY(IncidentSvc)
00028 // ============================================================================ 
00029 namespace 
00030 {
00031   // ==========================================================================
00032   static const std::string s_unknown = "<unknown>" ;
00033   // Helper to get the name of the listener
00034   inline const std::string& getListenerName ( IIncidentListener* lis )
00035   {
00036     SmartIF<INamedInterface> iNamed(lis);
00037     return iNamed.isValid() ? iNamed->name() : s_unknown ;
00038   }
00039   // ==========================================================================
00040 }
00041 // ============================================================================
00042 // Constructors and Desctructors
00043 // ============================================================================
00044 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc )
00045   : base_class(name, svc)
00046   , m_currentIncidentType(0)
00047   , m_log(msgSvc(), name)
00048   , m_timer() 
00049   , m_timerLock ( false ) 
00050 {}
00051 // ============================================================================
00052 IncidentSvc::~IncidentSvc() 
00053 {
00054   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00055   
00056   for (ListenerMap::iterator i = m_listenerMap.begin();
00057        i != m_listenerMap.end();
00058        ++i) {
00059     delete i->second;
00060   }
00061 }
00062 // ============================================================================
00063 // Inherited Service overrides:
00064 // ============================================================================
00065 StatusCode IncidentSvc::initialize() 
00066 {
00067   // initialize the Service Base class
00068   StatusCode sc = Service::initialize();
00069   if ( sc.isFailure() ) {
00070     return sc;
00071   }
00072   
00073   m_log.setLevel(outputLevel());
00074   m_currentIncidentType = 0;
00075   
00076   // set my own (IncidentSvc) properties via the jobOptionService
00077   sc = setProperties();
00078   if ( sc.isFailure() ) 
00079   {
00080     m_log << MSG::ERROR << "Could not set my properties" << endmsg;
00081     return sc;
00082   }
00083   
00084   return StatusCode::SUCCESS;
00085 }
00086 // ============================================================================
00087 StatusCode IncidentSvc::finalize() 
00088 {
00089   m_log 
00090     << MSG::DEBUG
00091     << m_timer.outputUserTime
00092     ( "Incident  timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
00093     << m_timer.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
00094   
00095   // Finalize this specific service
00096   StatusCode sc = Service::finalize();
00097   if ( sc.isFailure() ) { return sc; }
00098   
00099   return StatusCode::SUCCESS;
00100 }
00101 // ============================================================================
00102 // Inherited IIncidentSvc overrides:
00103 // ============================================================================
00104 void IncidentSvc::addListener 
00105 ( IIncidentListener* lis , 
00106   const std::string& type ,
00107   long prio, bool rethrow, bool singleShot) 
00108 {
00109   
00110   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00111   
00112   std::string ltype;
00113   if( type == "" ) ltype = "ALL";
00114   else             ltype = type;
00115   // find if the type already exists
00116   ListenerMap::iterator itMap = m_listenerMap.find( ltype );
00117   if( itMap == m_listenerMap.end() ) {
00118     // if not found, create and insert now a list of listeners
00119     ListenerList* newlist = new ListenerList();
00120     std::pair<ListenerMap::iterator, bool> p;
00121     p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist));
00122     if( p.second ) itMap = p.first;
00123   }
00124   ListenerList* llist = (*itMap).second;
00125   // add Listener in the ListenerList according to the priority
00126   ListenerList::iterator itlist;
00127   for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00128     if( (*itlist).priority < prio ) {
00129       // We insert before the current position
00130       break;
00131     }
00132   }
00133 
00134   m_log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis)
00135         << "' with priority " << prio << endmsg;
00136 
00137   llist->insert(itlist, Listener(lis, prio, rethrow, singleShot));
00138 }
00139 // ============================================================================
00140 void IncidentSvc::removeListener 
00141 ( IIncidentListener* lis  , 
00142   const std::string& type ) 
00143 {
00144 
00145   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00146 
00147   if( type == "") {
00148     // remove Listener from all the lists
00149     ListenerMap::iterator itmap;
00150     for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();)
00151     {
00152       // since the current entry may be eventually deleted
00153       // we need to keep a memory of the next index before 
00154       // calling recursively this method
00155       ListenerMap::iterator itmap_old = itmap;
00156       itmap++;
00157       removeListener( lis, (*itmap_old).first );
00158     }
00159   }
00160   else {
00161     ListenerMap::iterator itmap = m_listenerMap.find( type );
00162 
00163     if( itmap == m_listenerMap.end() ) {
00164       // if not found the incident type then return
00165       return;
00166     }
00167     else {
00168       ListenerList* llist = (*itmap).second;
00169       ListenerList::iterator itlist;
00170       bool justScheduleForRemoval = ( 0!= m_currentIncidentType )
00171                                     && (type == *m_currentIncidentType);
00172       // loop over all the entries in the Listener list 
00173       // to remove all of them than matches
00174       // the listener address. Remember the next index 
00175       // before erasing the current one
00176       for( itlist = llist->begin(); itlist != llist->end(); ) {
00177         if( (*itlist).iListener == lis || lis == 0) {
00178           if (justScheduleForRemoval) {
00179             (itlist++)->singleShot = true; // remove it as soon as it is safe
00180           }
00181           else {
00182             m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
00183                 << getListenerName(lis) << "'" << endmsg;
00184             itlist = llist->erase(itlist); // remove from the list now
00185           }
00186         }
00187         else {
00188           itlist++;
00189         }
00190       }
00191       if( llist->size() == 0) {
00192         delete llist;
00193         m_listenerMap.erase(itmap);
00194       }
00195     }
00196   }
00197 }
00198 // ============================================================================
00199 namespace {
00202   struct listenerToBeRemoved{
00203     inline bool operator() (const IncidentSvc::Listener& l) {
00204       return l.singleShot;
00205     }
00206   };
00207 }
00208 // ============================================================================
00209 void IncidentSvc::i_fireIncident 
00210 ( const Incident&    incident     , 
00211   const std::string& listenerType ) 
00212 {
00213   
00214   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00215   
00216   ListenerMap::iterator itmap = m_listenerMap.find( listenerType );
00217   if ( m_listenerMap.end() == itmap ) return;
00218   
00219   // setting this pointer will avoid that a call to removeListener() during
00220   // the loop triggers a segfault
00221   m_currentIncidentType = &(incident.type());
00222   
00223   ListenerList* llist = (*itmap).second;
00224   ListenerList::iterator itlist;
00225   bool weHaveToCleanUp = false;
00226   // loop over all registered Listeners
00227 
00228   const bool verbose =  MSG::VERBOSE >= outputLevel() ;
00229   
00230   for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) 
00231   {
00232     
00233     if ( verbose )
00234     {
00235       m_log 
00236         << MSG::VERBOSE 
00237         << "Calling '" << getListenerName((*itlist).iListener)
00238         << "' for incident [" << incident.type() << "]" << endmsg;
00239     }
00240     
00241     // handle exceptions if they occur
00242     try {
00243       (*itlist).iListener->handle(incident);
00244     }
00245     catch( const GaudiException& exc ) {
00246       m_log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught"
00247           " handling incident" << m_currentIncidentType << endmsg;
00248       m_log << MSG::ERROR <<  exc  << endmsg;
00249       if ( (*itlist).rethrow ) { throw (exc); }
00250     }
00251     catch( const std::exception& exc ) {
00252       m_log << MSG::ERROR << "Standard std::exception is caught"
00253           " handling incident" << m_currentIncidentType << endmsg;
00254       m_log << MSG::ERROR << exc.what()  << endmsg;
00255       if ( (*itlist).rethrow ) { throw (exc); }
00256     }
00257     catch(...) {
00258       m_log << MSG::ERROR << "UNKNOWN Exception is caught"
00259           " handling incident" << m_currentIncidentType << endmsg;
00260       if ( (*itlist).rethrow ) { throw; }
00261     }
00262     // check if at least one of the listeners is a one-shot
00263     weHaveToCleanUp |= itlist->singleShot;
00264   }
00265   if (weHaveToCleanUp) {
00266     // remove all the listeners that need to be removed from the list
00267     llist->remove_if( listenerToBeRemoved() );
00268     // if the list is empty, we can remove it
00269     if( llist->size() == 0) {
00270       delete llist;
00271       m_listenerMap.erase(itmap);
00272     }
00273   }
00274 
00275   m_currentIncidentType = 0;
00276 }
00277 // ============================================================================
00278 void IncidentSvc::fireIncident( const Incident& incident ) 
00279 {
00280   
00281   Gaudi::Utils::LockedChrono timer ( m_timer , m_timerLock ) ;
00282   
00283   // Call specific listeners
00284   i_fireIncident(incident, incident.type());
00285   // Try listeners registered for ALL incidents
00286   if ( incident.type() != "ALL" ){ // avoid double calls if somebody fires the incident "ALL"
00287     i_fireIncident(incident, "ALL");
00288   }
00289 }
00290 // ============================================================================
00291 // The END
00292 // ============================================================================

Generated at Fri Jan 22 20:28:06 2010 for Gaudi Framework, version v21r7 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004