| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

# IncidentSvc.cpp

Go to the documentation of this file.

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