IncidentSvc.cpp
Go to the documentation of this file.00001
00002
00003 #ifdef _WIN32
00004
00005 #define NOMSG
00006 #define NOGDI
00007 #endif
00008
00009
00010 #include "GaudiKernel/MsgStream.h"
00011 #include "GaudiKernel/ISvcLocator.h"
00012 #include "GaudiKernel/SmartIF.h"
00013 #include "GaudiKernel/IIncidentListener.h"
00014 #include "GaudiKernel/Incident.h"
00015 #include "GaudiKernel/GaudiException.h"
00016 #include "IncidentSvc.h"
00017
00018
00019
00020 DECLARE_SERVICE_FACTORY(IncidentSvc)
00021
00022 namespace {
00023
00024 std::string getListenerName(IIncidentListener* lis)
00025 {
00026 SmartIF<INamedInterface> iNamed(lis);
00027 if (iNamed.isValid()) return iNamed->name();
00028 else return "<unknown>";
00029 }
00030 }
00031
00032
00033
00034
00035
00036 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc )
00037 : base_class(name, svc),
00038 m_currentIncidentType(0),
00039 m_log(msgSvc(), name)
00040 {
00041 }
00042
00043 IncidentSvc::~IncidentSvc() {
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 }
00052
00053
00054
00055
00056
00057 StatusCode IncidentSvc::initialize() {
00058
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
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 }
00076
00077 StatusCode IncidentSvc::finalize() {
00078
00079 StatusCode sc = Service::finalize();
00080 if ( sc.isFailure() ) {
00081 return sc;
00082 }
00083
00084 return StatusCode::SUCCESS;
00085 }
00086
00087
00088
00089
00090
00091 void IncidentSvc::addListener(IIncidentListener* lis, const std::string& type,
00092 long prio, bool rethrow, bool singleShot) {
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
00100 ListenerMap::iterator itMap = m_listenerMap.find( ltype );
00101 if( itMap == m_listenerMap.end() ) {
00102
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
00110 ListenerList::iterator itlist;
00111 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00112 if( (*itlist).priority < prio ) {
00113
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 }
00123
00124 void IncidentSvc::removeListener(IIncidentListener* lis, const std::string& type) {
00125
00126 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
00127
00128 if( type == "") {
00129
00130 ListenerMap::iterator itmap;
00131 for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();) {
00132
00133
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
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
00152
00153 for( itlist = llist->begin(); itlist != llist->end(); ) {
00154 if( (*itlist).iListener == lis || lis == 0) {
00155 if (justScheduleForRemoval) {
00156 (itlist++)->singleShot = true;
00157 }
00158 else {
00159 m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
00160 << getListenerName(lis) << "'" << endmsg;
00161 itlist = llist->erase(itlist);
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 }
00175
00176 namespace {
00179 struct listenerToBeRemoved{
00180 inline bool operator() (const IncidentSvc::Listener& l) {
00181 return l.singleShot;
00182 }
00183 };
00184 }
00185
00186 void IncidentSvc::i_fireIncident( const Incident& incident, const std::string& listenerType ) {
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
00194
00195 m_currentIncidentType = &(incident.type());
00196
00197 ListenerList* llist = (*itmap).second;
00198 ListenerList::iterator itlist;
00199 bool weHaveToCleanUp = false;
00200
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
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
00227 weHaveToCleanUp |= itlist->singleShot;
00228 }
00229 if (weHaveToCleanUp) {
00230
00231 llist->remove_if( listenerToBeRemoved() );
00232
00233 if( llist->size() == 0) {
00234 delete llist;
00235 m_listenerMap.erase(itmap);
00236 }
00237 }
00238
00239 m_currentIncidentType = 0;
00240 }
00241
00242 void IncidentSvc::fireIncident( const Incident& incident ) {
00243
00244
00245 i_fireIncident(incident, incident.type());
00246
00247 if ( incident.type() != "ALL" ){
00248 i_fireIncident(incident, "ALL");
00249 }
00250 }