Gaudi Framework, version v25r0

Home   Generated: Mon Feb 17 2014
 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"
13 #include "GaudiKernel/SmartIF.h"
15 #include "GaudiKernel/Incident.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
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 // ============================================================================
51  : base_class(name, svc)
52  , m_currentIncidentType(0)
53  , m_timer()
54  , m_timerLock ( false )
55 {}
56 // ============================================================================
58 {
59  boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);
60 
62  i != m_listenerMap.end();
63  ++i) {
64  delete i->second;
65  }
66 }
67 // ============================================================================
68 // Inherited Service overrides:
69 // ============================================================================
71 {
72  // initialize the Service Base class
74  if ( sc.isFailure() ) {
75  return sc;
76  }
77 
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 // ============================================================================
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
98  if ( UNLIKELY(sc.isFailure()) ) { return sc; }
99 
100  return StatusCode::SUCCESS;
101 }
102 // ============================================================================
103 // Inherited IIncidentSvc overrides:
104 // ============================================================================
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();
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 // ============================================================================
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 // ============================================================================
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)
224  else
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
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 
311  if (itr == m_listenerMap.end()) return;
312 
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 // ============================================================================

Generated at Mon Feb 17 2014 14:37:41 for Gaudi Framework, version v25r0 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004