![]() |
|
|
Generated: 8 Jan 2009 |
00001 // $Header: /tmp/svngaudi/tmp.jEpFh25751/Gaudi/GaudiSvc/src/IncidentSvc/IncidentSvc.cpp,v 1.13 2008/11/10 16:00:23 marcocle Exp $ 00002 00003 // Include Files 00004 #include "GaudiKernel/MsgStream.h" 00005 #include "GaudiKernel/ISvcLocator.h" 00006 #include "GaudiKernel/SmartIF.h" 00007 #include "GaudiKernel/IIncidentListener.h" 00008 #include "GaudiKernel/Incident.h" 00009 #include "GaudiKernel/GaudiException.h" 00010 #include "IncidentSvc.h" 00011 00012 // Instantiation of a static factory class used by clients to create 00013 // instances of this service 00014 DECLARE_SERVICE_FACTORY(IncidentSvc) 00015 00016 namespace { 00017 // Helper to get the name of the listener 00018 std::string getListenerName(IIncidentListener* lis) 00019 { 00020 SmartIF<INamedInterface> iNamed(lis); 00021 if (iNamed.isValid()) return iNamed->name(); 00022 else return "<unknown>"; 00023 } 00024 } 00025 00026 00027 //============================================================================================ 00028 // Constructors and Desctructors 00029 //============================================================================================ 00030 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc ) 00031 : Service(name, svc), 00032 m_currentIncidentType(0), 00033 m_log(msgSvc(), name) 00034 { 00035 } 00036 00037 IncidentSvc::~IncidentSvc() { 00038 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex); 00039 00040 for (ListenerMap::iterator i = m_listenerMap.begin(); 00041 i != m_listenerMap.end(); 00042 ++i) { 00043 delete i->second; 00044 } 00045 } 00046 00047 //============================================================================================ 00048 // Inherited Service overrides: 00049 //============================================================================================ 00050 // 00051 StatusCode IncidentSvc::initialize() { 00052 // initialize the Service Base class 00053 StatusCode sc = Service::initialize(); 00054 if ( sc.isFailure() ) { 00055 return sc; 00056 } 00057 00058 m_log.setLevel(outputLevel()); 00059 m_currentIncidentType = 0; 00060 00061 // set my own (IncidentSvc) properties via the jobOptionService 00062 sc = setProperties(); 00063 if ( sc.isFailure() ) { 00064 m_log << MSG::ERROR << "Could not set my properties" << endreq; 00065 return sc; 00066 } 00067 00068 return StatusCode::SUCCESS; 00069 } 00070 00071 StatusCode IncidentSvc::finalize() { 00072 // Finalize this specific service 00073 StatusCode sc = Service::finalize(); 00074 if ( sc.isFailure() ) { 00075 return sc; 00076 } 00077 00078 return StatusCode::SUCCESS; 00079 } 00080 00081 StatusCode IncidentSvc::queryInterface( const InterfaceID& riid, void** ppvInterface ) { 00082 if ( IID_IIncidentSvc == riid ) { 00083 *ppvInterface = (IIncidentSvc*)this; 00084 } 00085 else { 00086 // Interface is not directly available: try out a base class 00087 return Service::queryInterface(riid, ppvInterface); 00088 } 00089 addRef(); 00090 return StatusCode::SUCCESS; 00091 } 00092 00093 //============================================================================================ 00094 // Inherited IIncidentSvc overrides: 00095 //============================================================================================ 00096 // 00097 void IncidentSvc::addListener(IIncidentListener* lis, const std::string& type, 00098 long prio, bool rethrow, bool singleShot) { 00099 00100 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex); 00101 00102 std::string ltype; 00103 if( type == "" ) ltype = "ALL"; 00104 else ltype = type; 00105 // find if the type already exists 00106 ListenerMap::iterator itMap = m_listenerMap.find( ltype ); 00107 if( itMap == m_listenerMap.end() ) { 00108 // if not found, create and insert now a list of listeners 00109 ListenerList* newlist = new ListenerList(); 00110 std::pair<ListenerMap::iterator, bool> p; 00111 p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist)); 00112 if( p.second ) itMap = p.first; 00113 } 00114 ListenerList* llist = (*itMap).second; 00115 // add Listener in the ListenerList according to the priority 00116 ListenerList::iterator itlist; 00117 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) { 00118 if( (*itlist).priority < prio ) { 00119 // We insert before the current position 00120 break; 00121 } 00122 } 00123 00124 m_log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis) 00125 << "' with priority " << prio << endreq; 00126 00127 llist->insert(itlist, Listener(lis, prio, rethrow, singleShot)); 00128 } 00129 00130 void IncidentSvc::removeListener(IIncidentListener* lis, const std::string& type) { 00131 00132 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex); 00133 00134 if( type == "") { 00135 // remove Listener from all the lists 00136 ListenerMap::iterator itmap; 00137 for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();) { 00138 // since the current entry may be eventually deleted 00139 // we need to keep a memory of the next index before calling recursively this method 00140 ListenerMap::iterator itmap_old = itmap; 00141 itmap++; 00142 removeListener( lis, (*itmap_old).first ); 00143 } 00144 } 00145 else { 00146 ListenerMap::iterator itmap = m_listenerMap.find( type ); 00147 00148 if( itmap == m_listenerMap.end() ) { 00149 // if not found the incident type then return 00150 return; 00151 } 00152 else { 00153 ListenerList* llist = (*itmap).second; 00154 ListenerList::iterator itlist; 00155 bool justScheduleForRemoval = ( 0!= m_currentIncidentType ) 00156 && (type == *m_currentIncidentType); 00157 // loop over all the entries in the Listener list to remove all of them than matches 00158 // the listener address. Remember the next index before erasing the current one 00159 for( itlist = llist->begin(); itlist != llist->end(); ) { 00160 if( (*itlist).iListener == lis || lis == 0) { 00161 if (justScheduleForRemoval) { 00162 (itlist++)->singleShot = true; // remove it as soon as it is safe 00163 } 00164 else { 00165 m_log << MSG::DEBUG << "Removing [" << type << "] listener '" 00166 << getListenerName(lis) << "'" << endreq; 00167 itlist = llist->erase(itlist); // remove from the list now 00168 } 00169 } 00170 else { 00171 itlist++; 00172 } 00173 } 00174 if( llist->size() == 0) { 00175 delete llist; 00176 m_listenerMap.erase(itmap); 00177 } 00178 } 00179 } 00180 } 00181 00182 namespace { 00185 struct listenerToBeRemoved{ 00186 inline bool operator() (const IncidentSvc::Listener& l) { 00187 return l.singleShot; 00188 } 00189 }; 00190 } 00191 00192 void IncidentSvc::i_fireIncident( const Incident& incident, const std::string& listenerType ) { 00193 00194 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex); 00195 00196 ListenerMap::iterator itmap = m_listenerMap.find( listenerType ); 00197 if ( m_listenerMap.end() == itmap ) return; 00198 00199 // setting this pointer will avoid that a call to removeListener() during 00200 // the loop triggers a segfault 00201 m_currentIncidentType = &(incident.type()); 00202 00203 ListenerList* llist = (*itmap).second; 00204 ListenerList::iterator itlist; 00205 bool weHaveToCleanUp = false; 00206 // loop over all registered Listeners 00207 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) { 00208 m_log << MSG::VERBOSE << "Calling '" << getListenerName((*itlist).iListener) 00209 << "' for incident [" << incident.type() << "]" << endreq; 00210 00211 // handle exceptions if they occur 00212 try { 00213 (*itlist).iListener->handle(incident); 00214 } 00215 catch( const GaudiException& exc ) { 00216 m_log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught " << endreq; 00217 m_log << MSG::ERROR << exc << endreq; 00218 if ( (*itlist).rethrow ) { throw (exc); } 00219 } 00220 catch( const std::exception& exc ) { 00221 m_log << MSG::ERROR << "Standard std::exception is caught " << endreq; 00222 m_log << MSG::ERROR << exc.what() << endreq; 00223 if ( (*itlist).rethrow ) { throw (exc); } 00224 } 00225 catch(...) { 00226 m_log << MSG::ERROR << "UNKNOWN Exception is caught " << endreq; 00227 if ( (*itlist).rethrow ) { throw; } 00228 } 00229 // check if at least one of the listeners is a one-shot 00230 weHaveToCleanUp |= itlist->singleShot; 00231 } 00232 if (weHaveToCleanUp) { 00233 // remove all the listeners that need to be removed from the list 00234 llist->remove_if( listenerToBeRemoved() ); 00235 // if the list is empty, we can remove it 00236 if( llist->size() == 0) { 00237 delete llist; 00238 m_listenerMap.erase(itmap); 00239 } 00240 } 00241 00242 m_currentIncidentType = 0; 00243 } 00244 00245 void IncidentSvc::fireIncident( const Incident& incident ) { 00246 00247 // Call specific listeners 00248 i_fireIncident(incident, incident.type()); 00249 // Try listeners registered for ALL incidents 00250 if ( incident.type() != "ALL" ){ // avoid double calls if somebody fires the incident "ALL" 00251 i_fireIncident(incident, "ALL"); 00252 } 00253 }