| # Gaudi Framework, version v21r11 |

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