| # Gaudi Framework, version v22r2 |

Home |  | Generated: Tue May 10 2011

Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes

# IncidentSvc Class Reference

Default implementation of the IIncidentSvc interface. More...

`#include <IncidentSvc.h>`

Inheritance diagram for IncidentSvc:
[legend]
Collaboration diagram for IncidentSvc:
[legend]

List of all members.

## Classes
struct | Listener
## Public Types
typedef std::list< Listener > | ListenerList
typedef GaudiUtils::HashMap < Gaudi::StringKey, ListenerList * > | ListenerMap
## Public Member Functions
virtual StatusCode | initialize ()
virtual StatusCode | finalize ()
virtual void | addListener (IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)
| Add listener.
virtual void | removeListener (IIncidentListener *lis, const std::string &type="")
| Remove listener.
virtual void | fireIncident (const Incident &incident)
| Fire an Incident.
| IncidentSvc (const std::string &name, ISvcLocator *svc)
virtual | ~IncidentSvc ()
## Private Member Functions
void | i_fireIncident (const Incident &incident, const std::string &type)
| Internal function to allow incidents listening to all events.
## Private Attributes
ListenerMap | m_listenerMap
| List of auditor names.
const std::string * | m_currentIncidentType
| Incident being fired.
MsgStream | m_log
| Internal MsgStream.
boost::recursive_mutex | m_listenerMapMutex
| Mutex to synchronize access to m_listenerMap.
ChronoEntity | m_timer
| timer & it's lock
bool | m_timerLock

## Detailed Description

Default implementation of the IIncidentSvc interface.

This implementation is thread-safe with the following features:

- Calls to fireIncident(), addListener() and removeListener() are synchronized across threads.
- Calls to IIncidentListener::handle() are serialized, i.e. at any time there is at most one incident handler being executed across all threads.

Definition at line 37 of file IncidentSvc.h.

## Member Typedef Documentation

typedef std::list<Listener> IncidentSvc::ListenerList

Definition at line 55 of file IncidentSvc.h.

typedef GaudiUtils::HashMap<Gaudi::StringKey, ListenerList*> IncidentSvc::ListenerMap

Definition at line 57 of file IncidentSvc.h.

## Constructor & Destructor Documentation

IncidentSvc::IncidentSvc | ( | const std::string & | name,
|  | ISvcLocator * | svc
| ) |  |

Definition at line 45 of file IncidentSvc.cpp.

      : base_class(name, svc)
      , m_currentIncidentType(0)
      , m_log(msgSvc(), name)
      , m_timer()
      , m_timerLock ( false )
    {}

IncidentSvc::~IncidentSvc | ( | ) | `[virtual]`

Definition at line 53 of file IncidentSvc.cpp.

    {
      boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);

      for (ListenerMap::iterator i = m_listenerMap.begin();
           i != m_listenerMap.end();
           ++i) {
        delete i->second;
      }
    }

## Member Function Documentation

void IncidentSvc::addListener | ( | IIncidentListener * | lis,
|  | const std::string & | type = `""`,
|  | long | priority = `0`,
|  | bool | rethrow = `false`,
|  | bool | singleShot = `false`
| ) |  | `[virtual]`

Add listener.

Parameters:

  lis | Listener address
  type | Incident type
  priority | Priority in handling incident

Implements IIncidentSvc.

Definition at line 106 of file IncidentSvc.cpp.

    {

      boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);

      std::string ltype;
      if( type == "" ) ltype = "ALL";
      else             ltype = type;
      // find if the type already exists
      ListenerMap::iterator itMap = m_listenerMap.find( ltype );
      if( itMap == m_listenerMap.end() ) {
        // if not found, create and insert now a list of listeners
        ListenerList* newlist = new ListenerList();
        std::pair<ListenerMap::iterator, bool> p;
        p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist));
        if( p.second ) itMap = p.first;
      }
      ListenerList* llist = (*itMap).second;
      // add Listener in the ListenerList according to the priority
      ListenerList::iterator itlist;
      for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
        if( (*itlist).priority < prio ) {
          // We insert before the current position
          break;
        }
      }

      m_log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis)
            << "' with priority " << prio << endmsg;

      llist->insert(itlist, Listener(lis, prio, rethrow, singleShot));
    }

StatusCode IncidentSvc::finalize | ( | void | ) | `[virtual]`

Reimplemented from Service.

Definition at line 88 of file IncidentSvc.cpp.

    {
      m_log
        << MSG::DEBUG
        << m_timer.outputUserTime
        ( "Incident  timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
        << m_timer.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;

      // Finalize this specific service
      StatusCode sc = Service::finalize();
      if ( sc.isFailure() ) { return sc; }

      return StatusCode::SUCCESS;
    }

void IncidentSvc::fireIncident | ( | const Incident & | incident ) | `[virtual]`

Fire an Incident.

Parameters:

  Incident | being fired

Implements IIncidentSvc.

Definition at line 286 of file IncidentSvc.cpp.

    {

      Gaudi::Utils::LockedChrono timer ( m_timer , m_timerLock ) ;

      // Call specific listeners
      i_fireIncident(incident, incident.type());
      // Try listeners registered for ALL incidents
      if ( incident.type() != "ALL" ){ // avoid double calls if somebody fires the incident "ALL"
        i_fireIncident(incident, "ALL");
      }

    }

void IncidentSvc::i_fireIncident | ( | const Incident & | incident,
|  | const std::string & | type
| ) |  | `[private]`

Internal function to allow incidents listening to all events.

Definition at line 211 of file IncidentSvc.cpp.

    {

      boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);

      // Special case: FailInputFile incident must set the application return code
      if (incident.type() == IncidentType::FailInputFile) {
        // Set the return code to Gaudi::ReturnCode::FailInput (2)
        SmartIF<IProperty> appmgr(serviceLocator());
        Gaudi::setAppReturnCode(appmgr, Gaudi::ReturnCode::FailInput).ignore();
      }

      ListenerMap::iterator itmap = m_listenerMap.find( listenerType );
      if ( m_listenerMap.end() == itmap ) return;

      // setting this pointer will avoid that a call to removeListener() during
      // the loop triggers a segfault
      m_currentIncidentType = &(incident.type());

      ListenerList* llist = (*itmap).second;
      ListenerList::iterator itlist;
      bool weHaveToCleanUp = false;
      // loop over all registered Listeners

      const bool verbose =  MSG::VERBOSE >= outputLevel() ;

      for( itlist = llist->begin(); itlist != llist->end(); itlist++ )
      {

        if ( verbose )
        {
          m_log
            << MSG::VERBOSE
            << "Calling '" << getListenerName((*itlist).iListener)
            << "' for incident [" << incident.type() << "]" << endmsg;
        }

        // handle exceptions if they occur
        try {
          (*itlist).iListener->handle(incident);
        }
        catch( const GaudiException& exc ) {
          m_log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught"
              " handling incident" << m_currentIncidentType << endmsg;
          m_log << MSG::ERROR <<  exc  << endmsg;
          if ( (*itlist).rethrow ) { throw (exc); }
        }
        catch( const std::exception& exc ) {
          m_log << MSG::ERROR << "Standard std::exception is caught"
              " handling incident" << m_currentIncidentType << endmsg;
          m_log << MSG::ERROR << exc.what()  << endmsg;
          if ( (*itlist).rethrow ) { throw (exc); }
        }
        catch(...) {
          m_log << MSG::ERROR << "UNKNOWN Exception is caught"
              " handling incident" << m_currentIncidentType << endmsg;
          if ( (*itlist).rethrow ) { throw; }
        }
        // check if at least one of the listeners is a one-shot
        weHaveToCleanUp |= itlist->singleShot;
      }
      if (weHaveToCleanUp) {
        // remove all the listeners that need to be removed from the list
        llist->remove_if( listenerToBeRemoved() );
        // if the list is empty, we can remove it
        if( llist->size() == 0) {
          delete llist;
          m_listenerMap.erase(itmap);
        }
      }

      m_currentIncidentType = 0;
    }

StatusCode IncidentSvc::initialize | ( | ) | `[virtual]`

Reimplemented from Service.

Definition at line 66 of file IncidentSvc.cpp.

    {
      // initialize the Service Base class
      StatusCode sc = Service::initialize();
      if ( sc.isFailure() ) {
        return sc;
      }

      m_log.setLevel(outputLevel());
      m_currentIncidentType = 0;

      // set my own (IncidentSvc) properties via the jobOptionService
      sc = setProperties();
      if ( sc.isFailure() )
      {
        m_log << MSG::ERROR << "Could not set my properties" << endmsg;
        return sc;
      }

      return StatusCode::SUCCESS;
    }

void IncidentSvc::removeListener | ( | IIncidentListener * | lis,
|  | const std::string & | type = `""`
| ) |  | `[virtual]`

Remove listener.

Parameters:

  lis | Listener address
  type | Incident type

Implements IIncidentSvc.

Definition at line 142 of file IncidentSvc.cpp.

    {

      boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex);

      if( type == "") {
        // remove Listener from all the lists
        ListenerMap::iterator itmap;
        for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();)
        {
          // since the current entry may be eventually deleted
          // we need to keep a memory of the next index before
          // calling recursively this method
          ListenerMap::iterator itmap_old = itmap;
          itmap++;
          removeListener( lis, (*itmap_old).first );
        }
      }
      else {
        ListenerMap::iterator itmap = m_listenerMap.find( type );

        if( itmap == m_listenerMap.end() ) {
          // if not found the incident type then return
          return;
        }
        else {
          ListenerList* llist = (*itmap).second;
          ListenerList::iterator itlist;
          bool justScheduleForRemoval = ( 0!= m_currentIncidentType )
                                        && (type == *m_currentIncidentType);
          // loop over all the entries in the Listener list
          // to remove all of them than matches
          // the listener address. Remember the next index
          // before erasing the current one
          for( itlist = llist->begin(); itlist != llist->end(); ) {
            if( (*itlist).iListener == lis || lis == 0) {
              if (justScheduleForRemoval) {
                (itlist++)->singleShot = true; // remove it as soon as it is safe
              }
              else {
                m_log << MSG::DEBUG << "Removing [" << type << "] listener '"
                    << getListenerName(lis) << "'" << endmsg;
                itlist = llist->erase(itlist); // remove from the list now
              }
            }
            else {
              itlist++;
            }
          }
          if( llist->size() == 0) {
            delete llist;
            m_listenerMap.erase(itmap);
          }
        }
      }
    }

## Member Data Documentation

const std::string* IncidentSvc::m_currentIncidentType`[private]`

Incident being fired.

It is used to know if we can safely remove a listener or we have to schedule its removal for later.

Definition at line 94 of file IncidentSvc.h.

ListenerMap IncidentSvc::m_listenerMap`[private]`

List of auditor names.

Definition at line 90 of file IncidentSvc.h.

boost::recursive_mutex IncidentSvc::m_listenerMapMutex`[private]`

Mutex to synchronize access to m_listenerMap.

Definition at line 100 of file IncidentSvc.h.

MsgStream IncidentSvc::m_log`[private]`

Internal MsgStream.

Definition at line 97 of file IncidentSvc.h.

ChronoEntity IncidentSvc::m_timer`[mutable, private]`

timer & it's lock

Definition at line 103 of file IncidentSvc.h.

bool IncidentSvc::m_timerLock`[mutable, private]`

Definition at line 104 of file IncidentSvc.h.

The documentation for this class was generated from the following files:

- /afs/.cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v22r2/GaudiSvc/src/IncidentSvc/IncidentSvc.h
- /afs/.cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v22r2/GaudiSvc/src/IncidentSvc/IncidentSvc.cpp

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines