| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
IncidentSvc.cpp
Go to the documentation of this file.
1 #ifdef _WIN32
2 // ============================================================================
3 // Avoid conflicts between windows and the message service.
4 // ============================================================================
5 #define NOMSG
6 #define NOGDI
7 #endif
8 // ============================================================================
9 // Include Files
10 // ============================================================================
11 #include "GaudiKernel/MsgStream.h"
12 #include "GaudiKernel/ISvcLocator.h"
13 #include "GaudiKernel/SmartIF.h"
14 #include "GaudiKernel/IIncidentListener.h"
15 #include "GaudiKernel/Incident.h"
16 #include "GaudiKernel/GaudiException.h"
17 #include "GaudiKernel/LockedChrono.h"
18 #include "GaudiKernel/AppReturnCode.h"
19 // ============================================================================
20 // Local
21 // ============================================================================
22 #include "IncidentSvc.h"
23 // ============================================================================
24 // Instantiation of a static factory class used by clients to create
25 // instances of this service
26 DECLARE_COMPONENT(IncidentSvc)
27 // ============================================================================
28 namespace
29 {
30 // ==========================================================================
31 static const std::string s_unknown = "<unknown>" ;
32 // Helper to get the name of the listener
33 inline const std::string& getListenerName ( IIncidentListener* lis )
34 {
35 SmartIF<INamedInterface> iNamed(lis);
36 return iNamed.isValid() ? iNamed->name() : s_unknown ;
37 }
38 // ==========================================================================
39 }
40
41 #define ON_DEBUG if (UNLIKELY(outputLevel() <= MSG::DEBUG))
42 #define ON_VERBOSE if (UNLIKELY(outputLevel() <= MSG::VERBOSE))
43
44 #define DEBMSG ON_DEBUG debug()
45 #define VERMSG ON_VERBOSE verbose()
46
47 // ============================================================================
48 // Constructors and Destructors
49 // ============================================================================
50 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc )
51 : base_class(name, svc)
52 , m_currentIncidentType(0)
53 , m_timer()
54 , m_timerLock ( false )
55 {}
56 // ============================================================================
57 IncidentSvc::~IncidentSvc()
58 {
59 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
60
61 for (ListenerMap::iterator i = m_listenerMap.begin();
62 i != m_listenerMap.end();
63 ++i) {
64 delete i->second;
65 }
66 }
67 // ============================================================================
68 // Inherited Service overrides:
69 // ============================================================================
70 StatusCode IncidentSvc::initialize()
71 {
72 // initialize the Service Base class
73 StatusCode sc = Service::initialize();
74 if ( sc.isFailure() ) {
75 return sc;
76 }
77
78 m_currentIncidentType = 0;
79
80 // set my own (IncidentSvc) properties via the jobOptionService
81 sc = setProperties();
82 if ( UNLIKELY(sc.isFailure()) )
83 {
84 error() << "Could not set my properties" << endmsg;
85 return sc;
86 }
87
88 return StatusCode::SUCCESS;
89 }
90 // ============================================================================
91 StatusCode IncidentSvc::finalize()
92 {
93 DEBMSG << m_timer.outputUserTime( "Incident timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
94 << m_timer.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
95
96 // Finalize this specific service
97 StatusCode sc = Service::finalize();
98 if ( UNLIKELY(sc.isFailure()) ) { return sc; }
99
100 return StatusCode::SUCCESS;
101 }
102 // ============================================================================
103 // Inherited IIncidentSvc overrides:
104 // ============================================================================
105 void IncidentSvc::addListener
106 ( IIncidentListener* lis ,
107 const std::string& type ,
108 long prio, bool rethrow, bool singleShot)
109 {
110
111 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
112
113 std::string ltype;
114 if( type == "" ) ltype = "ALL";
115 else ltype = type;
116 // find if the type already exists
117 ListenerMap::iterator itMap = m_listenerMap.find( ltype );
118 if( itMap == m_listenerMap.end() ) {
119 // if not found, create and insert now a list of listeners
120 ListenerList* newlist = new ListenerList();
121 std::pair<ListenerMap::iterator, bool> p;
122 p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist));
123 if( p.second ) itMap = p.first;
124 }
125 ListenerList* llist = (*itMap).second;
126 // add Listener in the ListenerList according to the priority
127 ListenerList::iterator itlist;
128 for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
129 if( (*itlist).priority < prio ) {
130 // We insert before the current position
131 break;
132 }
133 }
134
135 DEBMSG << "Adding [" << type << "] listener '" << getListenerName(lis)
136 << "' with priority " << prio << endmsg;
137
138 llist->insert(itlist, Listener(lis, prio, rethrow, singleShot));
139 }
140 // ============================================================================
141 void IncidentSvc::removeListener
142 ( IIncidentListener* lis ,
143 const std::string& type )
144 {
145
146 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
147
148 if( type == "") {
149 // remove Listener from all the lists
150 ListenerMap::iterator itmap;
151 for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();)
152 {
153 // since the current entry may be eventually deleted
154 // we need to keep a memory of the next index before
155 // calling recursively this method
156 ListenerMap::iterator itmap_old = itmap;
157 itmap++;
158 removeListener( lis, (*itmap_old).first );
159 }
160 }
161 else {
162 ListenerMap::iterator itmap = m_listenerMap.find( type );
163
164 if( itmap == m_listenerMap.end() ) {
165 // if not found the incident type then return
166 return;
167 }
168 else {
169 ListenerList* llist = (*itmap).second;
170 ListenerList::iterator itlist;
171 bool justScheduleForRemoval = ( 0!= m_currentIncidentType )
172 && (type == *m_currentIncidentType);
173 // loop over all the entries in the Listener list
174 // to remove all of them than matches
175 // the listener address. Remember the next index
176 // before erasing the current one
177 for( itlist = llist->begin(); itlist != llist->end(); ) {
178 if( (*itlist).iListener == lis || lis == 0) {
179 if (justScheduleForRemoval) {
180 (itlist++)->singleShot = true; // remove it as soon as it is safe
181 }
182 else {
183 DEBMSG << "Removing [" << type << "] listener '"
184 << getListenerName(lis) << "'" << endmsg;
185 itlist = llist->erase(itlist); // remove from the list now
186 }
187 }
188 else {
189 itlist++;
190 }
191 }
192 if( llist->size() == 0) {
193 delete llist;
194 m_listenerMap.erase(itmap);
195 }
196 }
197 }
198 }
199 // ============================================================================
200 namespace {
203 struct listenerToBeRemoved{
204 inline bool operator() (const IncidentSvc::Listener& l) {
205 return l.singleShot;
206 }
207 };
208 }
209 // ============================================================================
210 void IncidentSvc::i_fireIncident
211 ( const Incident& incident ,
212 const std::string& listenerType )
213 {
214
215 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
216
217 // Special case: FailInputFile incident must set the application return code
218 if (incident.type() == IncidentType::FailInputFile
219 || incident.type() == IncidentType::CorruptedInputFile) {
220 SmartIF<IProperty> appmgr(serviceLocator());
221 if (incident.type() == IncidentType::FailInputFile)
222 // Set the return code to Gaudi::ReturnCode::FailInput (2)
223 Gaudi::setAppReturnCode(appmgr, Gaudi::ReturnCode::FailInput).ignore();
224 else
225 Gaudi::setAppReturnCode(appmgr, Gaudi::ReturnCode::CorruptedInput).ignore();
226 }
227
228 ListenerMap::iterator itmap = m_listenerMap.find( listenerType );
229 if ( m_listenerMap.end() == itmap ) return;
230
231 // setting this pointer will avoid that a call to removeListener() during
232 // the loop triggers a segfault
233 m_currentIncidentType = &(incident.type());
234
235 ListenerList* llist = (*itmap).second;
236 ListenerList::iterator itlist;
237 bool weHaveToCleanUp = false;
238 // loop over all registered Listeners
239
240 for( itlist = llist->begin(); itlist != llist->end(); itlist++ )
241 {
242
243 VERMSG << "Calling '" << getListenerName((*itlist).iListener)
244 << "' for incident [" << incident.type() << "]" << endmsg;
245
246 // handle exceptions if they occur
247 try {
248 (*itlist).iListener->handle(incident);
249 }
250 catch( const GaudiException& exc ) {
251 error() << "Exception with tag=" << exc.tag() << " is caught"
252 " handling incident" << m_currentIncidentType << endmsg;
253 error() << exc << endmsg;
254 if ( (*itlist).rethrow ) { throw (exc); }
255 }
256 catch( const std::exception& exc ) {
257 error() << "Standard std::exception is caught"
258 " handling incident" << m_currentIncidentType << endmsg;
259 error() << exc.what() << endmsg;
260 if ( (*itlist).rethrow ) { throw (exc); }
261 }
262 catch(...) {
263 error() << "UNKNOWN Exception is caught"
264 " handling incident" << m_currentIncidentType << endmsg;
265 if ( (*itlist).rethrow ) { throw; }
266 }
267 // check if at least one of the listeners is a one-shot
268 weHaveToCleanUp |= itlist->singleShot;
269 }
270 if (weHaveToCleanUp) {
271 // remove all the listeners that need to be removed from the list
272 llist->remove_if( listenerToBeRemoved() );
273 // if the list is empty, we can remove it
274 if( llist->size() == 0) {
275 delete llist;
276 m_listenerMap.erase(itmap);
277 }
278 }
279
280 m_currentIncidentType = 0;
281 }
282 // ============================================================================
283 void IncidentSvc::fireIncident( const Incident& incident )
284 {
285
286 Gaudi::Utils::LockedChrono timer ( m_timer , m_timerLock ) ;
287
288 // Call specific listeners
289 i_fireIncident(incident, incident.type());
290 // Try listeners registered for ALL incidents
291 if ( incident.type() != "ALL" ){ // avoid double calls if somebody fires the incident "ALL"
292 i_fireIncident(incident, "ALL");
293 }
294
295 }
296
297 // ============================================================================
298 void
299 IncidentSvc::getListeners(std::vector<IIncidentListener*>& lis,
300 const std::string& type) const
301 {
302
303 boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
304
305 std::string ltype;
306 if (type == "") { ltype = "ALL"; } else { ltype = type; }
307
308 lis.clear();
309
310 ListenerMap::const_iterator itr=m_listenerMap.find( ltype );
311 if (itr == m_listenerMap.end()) return;
312
313 ListenerList::const_iterator itlist;
314 for (itlist = itr->second->begin(); itlist != itr->second->end(); ++itlist) {
315 lis.push_back(itlist->iListener);
316 }
317
318
319 }
320
321 // ============================================================================
322 // The END
323 // ============================================================================