Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 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

Generated at Thu Jun 28 2012 23:27:17 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004