| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 2012

# IncidentSvc.cpp

Go to the documentation of this file.

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

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines