Gaudi Framework, version v23r6

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

Generated at Wed Jan 30 2013 17:13:38 for Gaudi Framework, version v23r6 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004