IncidentSvc.cpp
Go to the documentation of this file.00001
00002
00003 #ifdef _WIN32
00004
00005
00006
00007 #define NOMSG
00008 #define NOGDI
00009 #endif
00010
00011
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
00021
00022
00023 #include "IncidentSvc.h"
00024
00025
00026
00027 DECLARE_SERVICE_FACTORY(IncidentSvc)
00028
00029 namespace
00030 {
00031
00032 static const std::string s_unknown = "<unknown>" ;
00033
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
00043
00044 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc )
00045 : base_class(name, svc)
00046 , m_currentIncidentType(0)
00047 , m_log(msgSvc(), name)
00048 , m_timer()
00049 , m_timerLock ( false )
00050 {}
00051
00052 IncidentSvc::~IncidentSvc()
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 }
00062
00063
00064
00065 StatusCode IncidentSvc::initialize()
00066 {
00067
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
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 }
00086
00087 StatusCode IncidentSvc::finalize()
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
00096 StatusCode sc = Service::finalize();
00097 if ( sc.isFailure() ) { return sc; }
00098
00099 return StatusCode::SUCCESS;
00100 }
00101
00102
00103
00104 void IncidentSvc::addListener
00105 ( IIncidentListener* lis ,
00106 const std::string& type ,
00107 long prio, bool rethrow, bool singleShot)
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
00116 ListenerMap::iterator itMap = m_listenerMap.find( ltype );
00117 if( itMap == m_listenerMap.end() ) {
00118
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
00126 ListenerList::iterator itlist;
00127 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00128 if( (*itlist).priority < prio ) {
00129
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 }
00139
00140 void IncidentSvc::removeListener
00141 ( IIncidentListener* lis ,
00142 const std::string& type )
00143 {
00144
00145 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00146
00147 if( type == "") {
00148
00149 ListenerMap::iterator itmap;
00150 for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();)
00151 {
00152
00153
00154
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
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
00173
00174
00175
00176 for( itlist = llist->begin(); itlist != llist->end(); ) {
00177 if( (*itlist).iListener == lis || lis == 0) {
00178 if (justScheduleForRemoval) {
00179 (itlist++)->singleShot = true;
00180 }
00181 else {
00182 m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
00183 << getListenerName(lis) << "'" << endmsg;
00184 itlist = llist->erase(itlist);
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 }
00198
00199 namespace {
00202 struct listenerToBeRemoved{
00203 inline bool operator() (const IncidentSvc::Listener& l) {
00204 return l.singleShot;
00205 }
00206 };
00207 }
00208
00209 void IncidentSvc::i_fireIncident
00210 ( const Incident& incident ,
00211 const std::string& listenerType )
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
00220
00221 m_currentIncidentType = &(incident.type());
00222
00223 ListenerList* llist = (*itmap).second;
00224 ListenerList::iterator itlist;
00225 bool weHaveToCleanUp = false;
00226
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
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
00263 weHaveToCleanUp |= itlist->singleShot;
00264 }
00265 if (weHaveToCleanUp) {
00266
00267 llist->remove_if( listenerToBeRemoved() );
00268
00269 if( llist->size() == 0) {
00270 delete llist;
00271 m_listenerMap.erase(itmap);
00272 }
00273 }
00274
00275 m_currentIncidentType = 0;
00276 }
00277
00278 void IncidentSvc::fireIncident( const Incident& incident )
00279 {
00280
00281 Gaudi::Utils::LockedChrono timer ( m_timer , m_timerLock ) ;
00282
00283
00284 i_fireIncident(incident, incident.type());
00285
00286 if ( incident.type() != "ALL" ){
00287 i_fireIncident(incident, "ALL");
00288 }
00289 }
00290
00291
00292