| # Gaudi Framework, version v20r3
Generated: 24 Nov 2008

# IncidentSvc.cpp

Go to the documentation of this file.

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