|
Gaudi Framework, version v21r11 |
| Home | Generated: 30 Sep 2010 |
#include <IncidentSvc.h>
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 |
This implementation is thread-safe with the following features:
Definition at line 37 of file IncidentSvc.h.
| 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.
| IncidentSvc::IncidentSvc | ( | const std::string & | name, | |
| ISvcLocator * | svc | |||
| ) |
Definition at line 45 of file IncidentSvc.cpp.
00046 : base_class(name, svc) 00047 , m_currentIncidentType(0) 00048 , m_log(msgSvc(), name) 00049 , m_timer() 00050 , m_timerLock ( false ) 00051 {}
| IncidentSvc::~IncidentSvc | ( | ) | [virtual] |
Definition at line 53 of file IncidentSvc.cpp.
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 }
| StatusCode IncidentSvc::initialize | ( | ) | [virtual] |
Reimplemented from Service.
Definition at line 66 of file IncidentSvc.cpp.
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 }
| StatusCode IncidentSvc::finalize | ( | ) | [virtual] |
Reimplemented from Service.
Definition at line 88 of file IncidentSvc.cpp.
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 }
| void IncidentSvc::addListener | ( | IIncidentListener * | lis, | |
| const std::string & | type = "", |
|||
| long | priority = 0, |
|||
| bool | rethrow = false, |
|||
| bool | singleShot = false | |||
| ) | [virtual] |
Add listener.
Implements IIncidentSvc.
Definition at line 106 of file IncidentSvc.cpp.
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 }
| void IncidentSvc::removeListener | ( | IIncidentListener * | lis, | |
| const std::string & | type = "" | |||
| ) | [virtual] |
Remove listener.
Implements IIncidentSvc.
Definition at line 142 of file IncidentSvc.cpp.
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 }
| void IncidentSvc::fireIncident | ( | const Incident & | incident | ) | [virtual] |
Fire an Incident.
| Incident | being fired |
Implements IIncidentSvc.
Definition at line 286 of file IncidentSvc.cpp.
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 }
| void IncidentSvc::i_fireIncident | ( | const Incident & | incident, | |
| const std::string & | type | |||
| ) | [private] |
Internal function to allow incidents listening to all events.
Definition at line 211 of file IncidentSvc.cpp.
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 }
ListenerMap IncidentSvc::m_listenerMap [private] |
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] |
boost::recursive_mutex IncidentSvc::m_listenerMapMutex [private] |
ChronoEntity IncidentSvc::m_timer [mutable, private] |
bool IncidentSvc::m_timerLock [mutable, private] |
Definition at line 104 of file IncidentSvc.h.