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 #include "GaudiKernel/AppReturnCode.h"
00021
00022
00023
00024 #include "IncidentSvc.h"
00025
00026
00027
00028 DECLARE_SERVICE_FACTORY(IncidentSvc)
00029
00030 namespace
00031 {
00032
00033 static const std::string s_unknown = "<unknown>" ;
00034
00035 inline const std::string& getListenerName ( IIncidentListener* lis )
00036 {
00037 SmartIF<INamedInterface> iNamed(lis);
00038 return iNamed.isValid() ? iNamed->name() : s_unknown ;
00039 }
00040
00041 }
00042
00043
00044
00045 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc )
00046 : base_class(name, svc)
00047 , m_currentIncidentType(0)
00048 , m_log(msgSvc(), name)
00049 , m_timer()
00050 , m_timerLock ( false )
00051 {}
00052
00053 IncidentSvc::~IncidentSvc()
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 }
00063
00064
00065
00066 StatusCode IncidentSvc::initialize()
00067 {
00068
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
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 }
00087
00088 StatusCode IncidentSvc::finalize()
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
00097 StatusCode sc = Service::finalize();
00098 if ( sc.isFailure() ) { return sc; }
00099
00100 return StatusCode::SUCCESS;
00101 }
00102
00103
00104
00105 void IncidentSvc::addListener
00106 ( IIncidentListener* lis ,
00107 const std::string& type ,
00108 long prio, bool rethrow, bool singleShot)
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
00117 ListenerMap::iterator itMap = m_listenerMap.find( ltype );
00118 if( itMap == m_listenerMap.end() ) {
00119
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
00127 ListenerList::iterator itlist;
00128 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00129 if( (*itlist).priority < prio ) {
00130
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 }
00140
00141 void IncidentSvc::removeListener
00142 ( IIncidentListener* lis ,
00143 const std::string& type )
00144 {
00145
00146 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00147
00148 if( type == "") {
00149
00150 ListenerMap::iterator itmap;
00151 for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();)
00152 {
00153
00154
00155
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
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
00174
00175
00176
00177 for( itlist = llist->begin(); itlist != llist->end(); ) {
00178 if( (*itlist).iListener == lis || lis == 0) {
00179 if (justScheduleForRemoval) {
00180 (itlist++)->singleShot = true;
00181 }
00182 else {
00183 m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
00184 << getListenerName(lis) << "'" << endmsg;
00185 itlist = llist->erase(itlist);
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 }
00199
00200 namespace {
00203 struct listenerToBeRemoved{
00204 inline bool operator() (const IncidentSvc::Listener& l) {
00205 return l.singleShot;
00206 }
00207 };
00208 }
00209
00210 void IncidentSvc::i_fireIncident
00211 ( const Incident& incident ,
00212 const std::string& listenerType )
00213 {
00214
00215 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00216
00217
00218 if (incident.type() == IncidentType::FailInputFile) {
00219
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
00228
00229 m_currentIncidentType = &(incident.type());
00230
00231 ListenerList* llist = (*itmap).second;
00232 ListenerList::iterator itlist;
00233 bool weHaveToCleanUp = false;
00234
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
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
00271 weHaveToCleanUp |= itlist->singleShot;
00272 }
00273 if (weHaveToCleanUp) {
00274
00275 llist->remove_if( listenerToBeRemoved() );
00276
00277 if( llist->size() == 0) {
00278 delete llist;
00279 m_listenerMap.erase(itmap);
00280 }
00281 }
00282
00283 m_currentIncidentType = 0;
00284 }
00285
00286 void IncidentSvc::fireIncident( const Incident& incident )
00287 {
00288
00289 Gaudi::Utils::LockedChrono timer ( m_timer , m_timerLock ) ;
00290
00291
00292 i_fireIncident(incident, incident.type());
00293
00294 if ( incident.type() != "ALL" ){
00295 i_fireIncident(incident, "ALL");
00296 }
00297
00298 }
00299
00300
00301