![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Header: /local/reps/Gaudi/GaudiSvc/src/IncidentSvc/IncidentSvc.cpp,v 1.10 2008/02/08 17:23:35 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 // Constructors and Desctructors 00028 //============================================================================================ 00029 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc ) 00030 : Service(name, svc),m_currentIncidentType(0) { 00031 } 00032 00033 IncidentSvc::~IncidentSvc() { 00034 for (ListenerMap::iterator i = m_listenerMap.begin(); 00035 i != m_listenerMap.end(); 00036 ++i) { 00037 delete i->second; 00038 } 00039 } 00040 00041 //============================================================================================ 00042 // Inherited Service overrides: 00043 //============================================================================================ 00044 // 00045 StatusCode IncidentSvc::initialize() { 00046 // initialize the Service Base class 00047 StatusCode sc = Service::initialize(); 00048 if ( sc.isFailure() ) { 00049 return sc; 00050 } 00051 00052 MsgStream log( msgSvc(), name() ); 00053 00054 // set my own (IncidentSvc) properties via the jobOptionService 00055 sc = setProperties(); 00056 if ( sc.isFailure() ) { 00057 log << MSG::ERROR << "Could not set my properties" << endreq; 00058 return sc; 00059 } 00060 00061 return StatusCode::SUCCESS; 00062 } 00063 00064 StatusCode IncidentSvc::finalize() { 00065 // Finalize this specific service 00066 StatusCode sc = Service::finalize(); 00067 if ( sc.isFailure() ) { 00068 return sc; 00069 } 00070 00071 return StatusCode::SUCCESS; 00072 } 00073 00074 StatusCode IncidentSvc::queryInterface( const InterfaceID& riid, void** ppvInterface ) { 00075 if ( IID_IIncidentSvc == riid ) { 00076 *ppvInterface = (IIncidentSvc*)this; 00077 } 00078 else { 00079 // Interface is not directly available: try out a base class 00080 return Service::queryInterface(riid, ppvInterface); 00081 } 00082 addRef(); 00083 return StatusCode::SUCCESS; 00084 } 00085 00086 //============================================================================================ 00087 // Inherited IIncidentSvc overrides: 00088 //============================================================================================ 00089 // 00090 void IncidentSvc::addListener(IIncidentListener* lis, const std::string& type, 00091 long prio, bool rethrow, bool singleShot) { 00092 00093 std::string ltype; 00094 if( type == "" ) ltype = "ALL"; 00095 else ltype = type; 00096 // find if the type already exists 00097 ListenerMap::iterator itMap = m_listenerMap.find( ltype ); 00098 if( itMap == m_listenerMap.end() ) { 00099 // if not found, create and insert now a list of listeners 00100 ListenerList* newlist = new ListenerList(); 00101 std::pair<ListenerMap::iterator, bool> p; 00102 p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist)); 00103 if( p.second ) itMap = p.first; 00104 } 00105 ListenerList* llist = (*itMap).second; 00106 // add Listener in the ListenerList according to the priority 00107 ListenerList::iterator itlist; 00108 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) { 00109 if( (*itlist).priority < prio ) { 00110 // We insert before the current position 00111 break; 00112 } 00113 } 00114 00115 MsgStream log ( msgSvc() , name()); 00116 log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis) 00117 << "' with priority " << prio << endreq; 00118 00119 llist->insert(itlist, Listener(lis, prio, rethrow, singleShot)); 00120 return; 00121 } 00122 00123 void IncidentSvc::removeListener(IIncidentListener* lis, const std::string& type) { 00124 00125 MsgStream log ( msgSvc() , name()); 00126 if( type == "") { 00127 // remove Listener from all the lists 00128 ListenerMap::iterator itmap; 00129 for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();) { 00130 // since the current entry may be eventually deleted 00131 // we need to keep a memory of the next index before calling recursivelly this method 00132 ListenerMap::iterator itmap_old = itmap; 00133 itmap++; 00134 removeListener( lis, (*itmap_old).first ); 00135 } 00136 } 00137 else { 00138 ListenerMap::iterator itmap = m_listenerMap.find( type ); 00139 if( itmap == m_listenerMap.end() ) { 00140 // if not found the incident type then return 00141 return; 00142 } 00143 else { 00144 ListenerList* llist = (*itmap).second; 00145 ListenerList::iterator itlist; 00146 bool justScheduleForRemoval = ( 0!= m_currentIncidentType ) 00147 && (type == *m_currentIncidentType); 00148 // loop over all the entries in the Listener list to remove all of them than matches 00149 // the listener address. Remember the next index before erasing the current one 00150 for( itlist = llist->begin(); itlist != llist->end(); ) { 00151 if( (*itlist).iListener == lis || lis == 0) { 00152 if (justScheduleForRemoval) { 00153 (itlist++)->singleShot = true; // remove it as soon as it is safe 00154 } 00155 else { 00156 log << MSG::DEBUG << "Removing [" << type << "] listener '" 00157 << getListenerName(lis) << "'" << endreq; 00158 itlist = llist->erase(itlist); // remove from the list now 00159 } 00160 } 00161 else { 00162 itlist++; 00163 } 00164 } 00165 if( llist->size() == 0) { 00166 delete llist; 00167 m_listenerMap.erase(itmap); 00168 } 00169 } 00170 } 00171 return; 00172 } 00173 00174 namespace { 00177 struct listenerToBeRemoved{ 00178 inline bool operator() (const IncidentSvc::Listener& l) { 00179 return l.singleShot; 00180 } 00181 }; 00182 } 00183 00184 void IncidentSvc::fireIncident( const Incident& incident ) { 00185 // setting this pointer will avoid that a call to removeListener() during 00186 // the loop triggers a segfault 00187 m_currentIncidentType = &(incident.type()); 00188 00189 MsgStream log ( msgSvc() , name()); 00190 ListenerMap::iterator itmap = m_listenerMap.find( incident.type() ); 00191 if( itmap != m_listenerMap.end() ) { 00192 ListenerList* llist = (*itmap).second; 00193 ListenerList::iterator itlist; 00194 bool weHaveToCleanUp = false; 00195 // loop over all registered Listeners 00196 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) { 00197 log << MSG::VERBOSE << "Calling '" << getListenerName((*itlist).iListener) 00198 << "' for incident [" << incident.type() << "]" << endreq; 00199 00200 // handle exceptions if they occur 00201 try { 00202 (*itlist).iListener->handle(incident); 00203 } 00204 catch( const GaudiException& exc ) { 00205 log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught " << endreq; 00206 log << MSG::ERROR << exc << endreq; 00207 if ( (*itlist).rethrow ) { throw (exc); } 00208 } 00209 catch( const std::exception& exc ) { 00210 log << MSG::ERROR << "Standard std::exception is caught " << endreq; 00211 log << MSG::ERROR << exc.what() << endreq; 00212 if ( (*itlist).rethrow ) { throw (exc); } 00213 } 00214 catch(...) { 00215 log << MSG::ERROR << "UNKNOWN Exception is caught " << endreq; 00216 if ( (*itlist).rethrow ) { throw; } 00217 } 00218 // check if at least one of the listeners is a one-shot 00219 weHaveToCleanUp |= itlist->singleShot; 00220 } 00221 if (weHaveToCleanUp) { 00222 // remove all the listeners that need to be removed from the list 00223 llist->remove_if( listenerToBeRemoved() ); 00224 // if the list is empty, we can remove it 00225 if( llist->size() == 0) { 00226 delete llist; 00227 m_listenerMap.erase(itmap); 00228 } 00229 } 00230 } 00231 m_currentIncidentType = NULL; 00232 return; 00233 }