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 // ============================================================================
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 // ============================================================================
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();
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 // ============================================================================
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 
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 
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 // ============================================================================
#define UNLIKELY(x)
Definition: Kernel.h:127
boost::recursive_mutex m_listenerMapMutex
Mutex to synchronize access to m_listenerMap.
Definition: IncidentSvc.h:97
Small smart pointer class with automatic reference counting for IInterface.
Definition: IConverter.h:14
ChronoEntity m_timer
timer & it's lock
Definition: IncidentSvc.h:100
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:26
const std::string & type() const
Access to the incident type.
Definition: Incident.h:34
bool m_timerLock
Definition: IncidentSvc.h:101
def lock
Definition: locker.py:16
virtual StatusCode initialize()
Initialization (from CONFIGURED to INITIALIZED).
Definition: IncidentSvc.cpp:70
std::list< Listener > ListenerList
Definition: IncidentSvc.h:52
const std::string FailInputFile
could not open or read from this file
Definition: Incident.h:78
#define DEBMSG
Definition: IncidentSvc.cpp:44
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:72
IncidentSvc(const std::string &name, ISvcLocator *svc)
Definition: IncidentSvc.cpp:50
virtual StatusCode finalize()
Finalize (from INITIALIZED to CONFIGURED).
Definition: IncidentSvc.cpp:91
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
virtual void getListeners(std::vector< IIncidentListener * > &lis, const std::string &type="") const
iterator end()
Definition: Map.h:131
string type
Definition: gaudirun.py:126
The interface implemented by any class wanting to listen to Incidents.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:30
std::pair< const Gaudi::StringKey, ListenerList * > value_type
Definition: Map.h:94
iterator find(const key_type &key)
Definition: Map.h:148
virtual const std::string & tag() const
name tag for the exception, or exception type
const std::string * m_currentIncidentType
Incident being fired.
Definition: IncidentSvc.h:94
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
Definition: AppReturnCode.h:50
StatusCode setProperties()
Method for setting declared properties to the values specified for the job.
Definition: Service.cpp:371
virtual void removeListener(IIncidentListener *lis, const std::string &type="")
Remove listener.
iterator begin()
Definition: Map.h:130
dictionary l
Definition: gaudirun.py:365
const int CorruptedInput
Definition: AppReturnCode.h:28
std::string outputUserTime() const
print the chrono ;
virtual StatusCode initialize()
Initialization (from CONFIGURED to INITIALIZED).
Definition: Service.cpp:74
Helper object, useful for measurement of CPU-performance of highly-recursive structures, e.g.
Definition: LockedChrono.h:54
#define VERMSG
Definition: IncidentSvc.cpp:45
void i_fireIncident(const Incident &incident, const std::string &type)
Internal function to allow incidents listening to all events.
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)
Add listener.
Base class for all Incidents (computing events).
Definition: Incident.h:16
Templated class to add the standard messaging functionalities.
virtual ~IncidentSvc()
Definition: IncidentSvc.cpp:57
ListenerMap m_listenerMap
List of auditor names.
Definition: IncidentSvc.h:90
Default implementation of the IIncidentSvc interface.
Definition: IncidentSvc.h:34
const int FailInput
Definition: AppReturnCode.h:23
void ignore() const
Definition: StatusCode.h:94
list i
Definition: ana.py:128
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
virtual StatusCode finalize()
Finalize (from INITIALIZED to CONFIGURED).
Definition: Service.cpp:199
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
const std::string CorruptedInputFile
the input file has shown a corruption
Definition: Incident.h:81
virtual void fireIncident(const Incident &incident)
Fire an Incident.