Gaudi Framework, version v22r0

Home   Generated: 9 Feb 2011

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 // ============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Wed Feb 9 16:25:02 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004