Gaudi Framework, version v21r6

Home   Generated: 11 Nov 2009

IncidentSvc Class Reference

#include <IncidentSvc.h>

Inheritance diagram for IncidentSvc:

Inheritance graph
[legend]
Collaboration diagram for IncidentSvc:

Collaboration graph
[legend]

List of all members.


Detailed Description

Default implementation of the IIncidentSvc interface.

This implementation is thread-safe with the following features:

Definition at line 28 of file IncidentSvc.h.


Public Types

typedef std::list< ListenerListenerList
typedef std::map< std::string,
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::stringm_currentIncidentType
 Incident being fired.
MsgStream m_log
 Internal MsgStream.
boost::recursive_mutex m_listenerMapMutex
 Mutex to synchronize access to m_listenerMap.

Classes

struct  Listener

Member Typedef Documentation

Definition at line 44 of file IncidentSvc.h.

Definition at line 45 of file IncidentSvc.h.


Constructor & Destructor Documentation

IncidentSvc::IncidentSvc ( const std::string name,
ISvcLocator svc 
)

Definition at line 36 of file IncidentSvc.cpp.

00037   : base_class(name, svc),
00038     m_currentIncidentType(0),
00039     m_log(msgSvc(), name)
00040 {
00041 }

IncidentSvc::~IncidentSvc (  )  [virtual]

Definition at line 43 of file IncidentSvc.cpp.

00043                           {
00044   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00045 
00046   for (ListenerMap::iterator i = m_listenerMap.begin();
00047        i != m_listenerMap.end();
00048        ++i) {
00049     delete i->second;
00050   }
00051 }


Member Function Documentation

StatusCode IncidentSvc::initialize (  )  [virtual]

Reimplemented from Service.

Definition at line 57 of file IncidentSvc.cpp.

00057                                    {
00058   // initialize the Service Base class
00059   StatusCode sc = Service::initialize();
00060   if ( sc.isFailure() ) {
00061     return sc;
00062   }
00063 
00064   m_log.setLevel(outputLevel());
00065   m_currentIncidentType = 0;
00066 
00067   // set my own (IncidentSvc) properties via the jobOptionService
00068   sc = setProperties();
00069   if ( sc.isFailure() ) {
00070     m_log << MSG::ERROR << "Could not set my properties" << endmsg;
00071     return sc;
00072   }
00073 
00074   return StatusCode::SUCCESS;
00075 }

StatusCode IncidentSvc::finalize ( void   )  [virtual]

Reimplemented from Service.

Definition at line 77 of file IncidentSvc.cpp.

00077                                  {
00078   // Finalize this specific service
00079   StatusCode sc = Service::finalize();
00080   if ( sc.isFailure() ) {
00081     return sc;
00082   }
00083 
00084   return StatusCode::SUCCESS;
00085 }

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 91 of file IncidentSvc.cpp.

00092                                                                         {
00093 
00094   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00095 
00096   std::string ltype;
00097   if( type == "" ) ltype = "ALL";
00098   else             ltype = type;
00099   // find if the type already exists
00100   ListenerMap::iterator itMap = m_listenerMap.find( ltype );
00101   if( itMap == m_listenerMap.end() ) {
00102     // if not found, create and insert now a list of listeners
00103     ListenerList* newlist = new ListenerList();
00104     std::pair<ListenerMap::iterator, bool> p;
00105     p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist));
00106     if( p.second ) itMap = p.first;
00107   }
00108   ListenerList* llist = (*itMap).second;
00109   // add Listener in the ListenerList according to the priority
00110   ListenerList::iterator itlist;
00111   for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00112     if( (*itlist).priority < prio ) {
00113       // We insert before the current position
00114       break;
00115     }
00116   }
00117 
00118   m_log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis)
00119         << "' with priority " << prio << endmsg;
00120 
00121   llist->insert(itlist, Listener(lis, prio, rethrow, singleShot));
00122 }

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

Remove listener.

Parameters:
lis Listener address
type Incident type

Implements IIncidentSvc.

Definition at line 124 of file IncidentSvc.cpp.

00124                                                                               {
00125 
00126   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00127 
00128   if( type == "") {
00129     // remove Listener from all the lists
00130     ListenerMap::iterator itmap;
00131     for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();) {
00132       // since the current entry may be eventually deleted
00133       // we need to keep a memory of the next index before calling recursively this method
00134       ListenerMap::iterator itmap_old = itmap;
00135       itmap++;
00136       removeListener( lis, (*itmap_old).first );
00137     }
00138   }
00139   else {
00140     ListenerMap::iterator itmap = m_listenerMap.find( type );
00141 
00142     if( itmap == m_listenerMap.end() ) {
00143       // if not found the incident type then return
00144       return;
00145     }
00146     else {
00147       ListenerList* llist = (*itmap).second;
00148       ListenerList::iterator itlist;
00149       bool justScheduleForRemoval = ( 0!= m_currentIncidentType )
00150                                     && (type == *m_currentIncidentType);
00151       // loop over all the entries in the Listener list to remove all of them than matches
00152       // the listener address. Remember the next index before erasing the current one
00153       for( itlist = llist->begin(); itlist != llist->end(); ) {
00154         if( (*itlist).iListener == lis || lis == 0) {
00155           if (justScheduleForRemoval) {
00156             (itlist++)->singleShot = true; // remove it as soon as it is safe
00157           }
00158           else {
00159             m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
00160                 << getListenerName(lis) << "'" << endmsg;
00161             itlist = llist->erase(itlist); // remove from the list now
00162           }
00163         }
00164         else {
00165           itlist++;
00166         }
00167       }
00168       if( llist->size() == 0) {
00169         delete llist;
00170         m_listenerMap.erase(itmap);
00171       }
00172     }
00173   }
00174 }

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

Fire an Incident.

Parameters:
Incident being fired

Implements IIncidentSvc.

Definition at line 242 of file IncidentSvc.cpp.

00242                                                          {
00243 
00244   // Call specific listeners
00245   i_fireIncident(incident, incident.type());
00246   // Try listeners registered for ALL incidents
00247   if ( incident.type() != "ALL" ){ // avoid double calls if somebody fires the incident "ALL"
00248     i_fireIncident(incident, "ALL");
00249   }
00250 }

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

Internal function to allow incidents listening to all events.

Definition at line 186 of file IncidentSvc.cpp.

00186                                                                                           {
00187 
00188   boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00189 
00190   ListenerMap::iterator itmap = m_listenerMap.find( listenerType );
00191   if ( m_listenerMap.end() == itmap ) return;
00192 
00193   // setting this pointer will avoid that a call to removeListener() during
00194   // the loop triggers a segfault
00195   m_currentIncidentType = &(incident.type());
00196 
00197   ListenerList* llist = (*itmap).second;
00198   ListenerList::iterator itlist;
00199   bool weHaveToCleanUp = false;
00200   // loop over all registered Listeners
00201   for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00202     m_log << MSG::VERBOSE << "Calling '" << getListenerName((*itlist).iListener)
00203           << "' for incident [" << incident.type() << "]" << endmsg;
00204 
00205     // handle exceptions if they occur
00206     try {
00207       (*itlist).iListener->handle(incident);
00208     }
00209     catch( const GaudiException& exc ) {
00210       m_log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught"
00211           " handling incident" << m_currentIncidentType << endmsg;
00212       m_log << MSG::ERROR <<  exc  << endmsg;
00213       if ( (*itlist).rethrow ) { throw (exc); }
00214     }
00215     catch( const std::exception& exc ) {
00216       m_log << MSG::ERROR << "Standard std::exception is caught"
00217           " handling incident" << m_currentIncidentType << endmsg;
00218       m_log << MSG::ERROR << exc.what()  << endmsg;
00219       if ( (*itlist).rethrow ) { throw (exc); }
00220     }
00221     catch(...) {
00222       m_log << MSG::ERROR << "UNKNOWN Exception is caught"
00223           " handling incident" << m_currentIncidentType << endmsg;
00224       if ( (*itlist).rethrow ) { throw; }
00225     }
00226     // check if at least one of the listeners is a one-shot
00227     weHaveToCleanUp |= itlist->singleShot;
00228   }
00229   if (weHaveToCleanUp) {
00230     // remove all the listeners that need to be removed from the list
00231     llist->remove_if( listenerToBeRemoved() );
00232     // if the list is empty, we can remove it
00233     if( llist->size() == 0) {
00234       delete llist;
00235       m_listenerMap.erase(itmap);
00236     }
00237   }
00238 
00239   m_currentIncidentType = 0;
00240 }


Member Data Documentation

List of auditor names.

Definition at line 70 of file IncidentSvc.h.

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 74 of file IncidentSvc.h.

Internal MsgStream.

Definition at line 77 of file IncidentSvc.h.

boost::recursive_mutex IncidentSvc::m_listenerMapMutex [private]

Mutex to synchronize access to m_listenerMap.

Definition at line 80 of file IncidentSvc.h.


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

Generated at Wed Nov 11 16:33:49 2009 for Gaudi Framework, version v21r6 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004