| # Gaudi Framework, version v21r10p1 |

Home |  | Generated: 29 Jul 2010

# IncidentSvc Class Reference

Default implementation of the IIncidentSvc interface. More...

`#include <IncidentSvc.h>`

Inheritance diagram for IncidentSvc:

[legend]
Collaboration diagram for IncidentSvc:

[legend]

List of all members.

## Public Types
typedef std::list< Listener > | ListenerList
typedef GaudiUtils::HashMap < Gaudi::StringKey, ListenerList * > | ListenerMap
## Public Member Functions
virtual StatusCode | initialize ()
virtual StatusCode | finalize ()
virtual void | addListener (IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)
| Add listener.
virtual void | removeListener (IIncidentListener *lis, const std::string &type="")
| Remove listener.
virtual void | fireIncident (const Incident &incident)
| Fire an Incident.
| IncidentSvc (const std::string &name, ISvcLocator *svc)
virtual | ~IncidentSvc ()
## Private Member Functions
void | i_fireIncident (const Incident &incident, const std::string &type)
| Internal function to allow incidents listening to all events.
## Private Attributes
ListenerMap | m_listenerMap
| List of auditor names.
const std::string * | m_currentIncidentType
| Incident being fired.
MsgStream | m_log
| Internal MsgStream.
boost::recursive_mutex | m_listenerMapMutex
| Mutex to synchronize access to m_listenerMap.
ChronoEntity | m_timer
| timer & it's lock
bool | m_timerLock
## Classes
struct | Listener

## Detailed Description

Default implementation of the IIncidentSvc interface.

This implementation is thread-safe with the following features:

- Calls to fireIncident(), addListener() and removeListener() are synchronized across threads.
- Calls to IIncidentListener::handle() are serialized, i.e. at any time there is at most one incident handler being executed across all threads.

Definition at line 37 of file IncidentSvc.h.

## Member Typedef Documentation

typedef std::list<Listener> IncidentSvc::ListenerList

Definition at line 55 of file IncidentSvc.h.

typedef GaudiUtils::HashMap<Gaudi::StringKey, ListenerList*> IncidentSvc::ListenerMap

Definition at line 57 of file IncidentSvc.h.

## Constructor & Destructor Documentation

IncidentSvc::IncidentSvc | ( | const std::string & | name,
|  | ISvcLocator * | svc |
| ) |  |  |

Definition at line 44 of file IncidentSvc.cpp.

    00045   : base_class(name, svc)
    00046   , m_currentIncidentType(0)
    00047   , m_log(msgSvc(), name)
    00048   , m_timer()
    00049   , m_timerLock ( false )
    00050 {}

IncidentSvc::~IncidentSvc | ( |  | ) | `[virtual]`

Definition at line 52 of file IncidentSvc.cpp.

    00053 {
    00054   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
    00055
    00056   for (ListenerMap::iterator i = m_listenerMap.begin();
    00057        i != m_listenerMap.end();
    00058        ++i) {
    00059     delete i->second;
    00060   }
    00061 }

## Member Function Documentation

StatusCode IncidentSvc::initialize | ( |  | ) | `[virtual]`

Reimplemented from Service.

Definition at line 65 of file IncidentSvc.cpp.

    00066 {
    00067   // initialize the Service Base class
    00068   StatusCode sc = Service::initialize();
    00069   if ( sc.isFailure() ) {
    00070     return sc;
    00071   }
    00072
    00073   m_log.setLevel(outputLevel());
    00074   m_currentIncidentType = 0;
    00075
    00076   // set my own (IncidentSvc) properties via the jobOptionService
    00077   sc = setProperties();
    00078   if ( sc.isFailure() )
    00079   {
    00080     m_log << MSG::ERROR << "Could not set my properties" << endmsg;
    00081     return sc;
    00082   }
    00083
    00084   return StatusCode::SUCCESS;
    00085 }

StatusCode IncidentSvc::finalize | ( |  | ) | `[virtual]`

Reimplemented from Service.

Definition at line 87 of file IncidentSvc.cpp.

    00088 {
    00089   m_log
    00090     << MSG::DEBUG
    00091     << m_timer.outputUserTime
    00092     ( "Incident  timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
    00093     << m_timer.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
    00094
    00095   // Finalize this specific service
    00096   StatusCode sc = Service::finalize();
    00097   if ( sc.isFailure() ) { return sc; }
    00098
    00099   return StatusCode::SUCCESS;
    00100 }

void IncidentSvc::addListener | ( | IIncidentListener * | lis,
|  | const std::string & | type = `""`,
|  | long | priority = `0`,
|  | bool | rethrow = `false`,
|  | bool | singleShot = `false` |
| ) |  |  | `[virtual]`

Add listener.

Parameters:

  | lis | Listener address
  | type | Incident type
  | priority | Priority in handling incident

Implements IIncidentSvc.

Definition at line 105 of file IncidentSvc.cpp.

    00108 {
    00109
    00110   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
    00111
    00112   std::string ltype;
    00113   if( type == "" ) ltype = "ALL";
    00114   else             ltype = type;
    00115   // find if the type already exists
    00116   ListenerMap::iterator itMap = m_listenerMap.find( ltype );
    00117   if( itMap == m_listenerMap.end() ) {
    00118     // if not found, create and insert now a list of listeners
    00119     ListenerList* newlist = new ListenerList();
    00120     std::pair<ListenerMap::iterator, bool> p;
    00121     p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist));
    00122     if( p.second ) itMap = p.first;
    00123   }
    00124   ListenerList* llist = (*itMap).second;
    00125   // add Listener in the ListenerList according to the priority
    00126   ListenerList::iterator itlist;
    00127   for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
    00128     if( (*itlist).priority < prio ) {
    00129       // We insert before the current position
    00130       break;
    00131     }
    00132   }
    00133
    00134   m_log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis)
    00135         << "' with priority " << prio << endmsg;
    00136
    00137   llist->insert(itlist, Listener(lis, prio, rethrow, singleShot));
    00138 }

void IncidentSvc::removeListener | ( | IIncidentListener * | lis,
|  | const std::string & | type = `""` |
| ) |  |  | `[virtual]`

Remove listener.

Parameters:

  | lis | Listener address
  | type | Incident type

Implements IIncidentSvc.

Definition at line 141 of file IncidentSvc.cpp.

    00143 {
    00144
    00145   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
    00146
    00147   if( type == "") {
    00148     // remove Listener from all the lists
    00149     ListenerMap::iterator itmap;
    00150     for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();)
    00151     {
    00152       // since the current entry may be eventually deleted
    00153       // we need to keep a memory of the next index before
    00154       // calling recursively this method
    00155       ListenerMap::iterator itmap_old = itmap;
    00156       itmap++;
    00157       removeListener( lis, (*itmap_old).first );
    00158     }
    00159   }
    00160   else {
    00161     ListenerMap::iterator itmap = m_listenerMap.find( type );
    00162
    00163     if( itmap == m_listenerMap.end() ) {
    00164       // if not found the incident type then return
    00165       return;
    00166     }
    00167     else {
    00168       ListenerList* llist = (*itmap).second;
    00169       ListenerList::iterator itlist;
    00170       bool justScheduleForRemoval = ( 0!= m_currentIncidentType )
    00171                                     && (type == *m_currentIncidentType);
    00172       // loop over all the entries in the Listener list
    00173       // to remove all of them than matches
    00174       // the listener address. Remember the next index
    00175       // before erasing the current one
    00176       for( itlist = llist->begin(); itlist != llist->end(); ) {
    00177         if( (*itlist).iListener == lis || lis == 0) {
    00178           if (justScheduleForRemoval) {
    00179             (itlist++)->singleShot = true; // remove it as soon as it is safe
    00180           }
    00181           else {
    00182             m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
    00183                 << getListenerName(lis) << "'" << endmsg;
    00184             itlist = llist->erase(itlist); // remove from the list now
    00185           }
    00186         }
    00187         else {
    00188           itlist++;
    00189         }
    00190       }
    00191       if( llist->size() == 0) {
    00192         delete llist;
    00193         m_listenerMap.erase(itmap);
    00194       }
    00195     }
    00196   }
    00197 }

void IncidentSvc::fireIncident | ( | const Incident & | incident | ) | `[virtual]`

Fire an Incident.

Parameters:

  | Incident | being fired

Implements IIncidentSvc.

Definition at line 278 of file IncidentSvc.cpp.

    00279 {
    00280
    00281   Gaudi::Utils::LockedChrono timer ( m_timer , m_timerLock ) ;
    00282
    00283   // Call specific listeners
    00284   i_fireIncident(incident, incident.type());
    00285   // Try listeners registered for ALL incidents
    00286   if ( incident.type() != "ALL" ){ // avoid double calls if somebody fires the incident "ALL"
    00287     i_fireIncident(incident, "ALL");
    00288   }
    00289 }

void IncidentSvc::i_fireIncident | ( | const Incident & | incident,
|  | const std::string & | type |
| ) |  |  | `[private]`

Internal function to allow incidents listening to all events.

Definition at line 210 of file IncidentSvc.cpp.

    00212 {
    00213
    00214   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
    00215
    00216   ListenerMap::iterator itmap = m_listenerMap.find( listenerType );
    00217   if ( m_listenerMap.end() == itmap ) return;
    00218
    00219   // setting this pointer will avoid that a call to removeListener() during
    00220   // the loop triggers a segfault
    00221   m_currentIncidentType = &(incident.type());
    00222
    00223   ListenerList* llist = (*itmap).second;
    00224   ListenerList::iterator itlist;
    00225   bool weHaveToCleanUp = false;
    00226   // loop over all registered Listeners
    00227
    00228   const bool verbose =  MSG::VERBOSE >= outputLevel() ;
    00229
    00230   for( itlist = llist->begin(); itlist != llist->end(); itlist++ )
    00231   {
    00232
    00233     if ( verbose )
    00234     {
    00235       m_log
    00236         << MSG::VERBOSE
    00237         << "Calling '" << getListenerName((*itlist).iListener)
    00238         << "' for incident [" << incident.type() << "]" << endmsg;
    00239     }
    00240
    00241     // handle exceptions if they occur
    00242     try {
    00243       (*itlist).iListener->handle(incident);
    00244     }
    00245     catch( const GaudiException& exc ) {
    00246       m_log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught"
    00247           " handling incident" << m_currentIncidentType << endmsg;
    00248       m_log << MSG::ERROR <<  exc  << endmsg;
    00249       if ( (*itlist).rethrow ) { throw (exc); }
    00250     }
    00251     catch( const std::exception& exc ) {
    00252       m_log << MSG::ERROR << "Standard std::exception is caught"
    00253           " handling incident" << m_currentIncidentType << endmsg;
    00254       m_log << MSG::ERROR << exc.what()  << endmsg;
    00255       if ( (*itlist).rethrow ) { throw (exc); }
    00256     }
    00257     catch(...) {
    00258       m_log << MSG::ERROR << "UNKNOWN Exception is caught"
    00259           " handling incident" << m_currentIncidentType << endmsg;
    00260       if ( (*itlist).rethrow ) { throw; }
    00261     }
    00262     // check if at least one of the listeners is a one-shot
    00263     weHaveToCleanUp |= itlist->singleShot;
    00264   }
    00265   if (weHaveToCleanUp) {
    00266     // remove all the listeners that need to be removed from the list
    00267     llist->remove_if( listenerToBeRemoved() );
    00268     // if the list is empty, we can remove it
    00269     if( llist->size() == 0) {
    00270       delete llist;
    00271       m_listenerMap.erase(itmap);
    00272     }
    00273   }
    00274
    00275   m_currentIncidentType = 0;
    00276 }

## Member Data Documentation

ListenerMap IncidentSvc::m_listenerMap`[private]`

List of auditor names.

Definition at line 90 of file IncidentSvc.h.

const std::string* IncidentSvc::m_currentIncidentType`[private]`

Incident being fired.

It is used to know if we can safely remove a listener or we have to schedule its removal for later.

Definition at line 94 of file IncidentSvc.h.

MsgStream IncidentSvc::m_log`[private]`

Internal MsgStream.

Definition at line 97 of file IncidentSvc.h.

boost::recursive_mutex IncidentSvc::m_listenerMapMutex`[private]`

Mutex to synchronize access to m_listenerMap.

Definition at line 100 of file IncidentSvc.h.

ChronoEntity IncidentSvc::m_timer`[mutable, private]`

timer & it's lock

Definition at line 103 of file IncidentSvc.h.

bool IncidentSvc::m_timerLock`[mutable, private]`

Definition at line 104 of file IncidentSvc.h.

The documentation for this class was generated from the following files:

- /afs/cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v21r10p1/GaudiSvc/src/IncidentSvc/IncidentSvc.h
- /afs/cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v21r10p1/GaudiSvc/src/IncidentSvc/IncidentSvc.cpp