Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 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:
Inheritance graph
[legend]
Collaboration diagram for IncidentSvc:
Collaboration graph
[legend]

List of all members.

Classes

struct  Listener

Public Types

typedef std::list< ListenerListenerList
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::stringm_currentIncidentType
 Incident being fired.
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:

Definition at line 37 of file IncidentSvc.h.


Member Typedef Documentation

Definition at line 55 of file IncidentSvc.h.

Definition at line 57 of file IncidentSvc.h.


Constructor & Destructor Documentation

IncidentSvc::IncidentSvc ( const std::string name,
ISvcLocator svc 
)

Definition at line 51 of file IncidentSvc.cpp.

  : base_class(name, svc)
  , m_currentIncidentType(0)
  , m_timer()
  , m_timerLock ( false )
{}
IncidentSvc::~IncidentSvc (  ) [virtual]

Definition at line 58 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:
lisListener address
typeIncident type
priorityPriority in handling incident

Implements IIncidentSvc.

Definition at line 107 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;
    }
  }

  DEBMSG << "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 92 of file IncidentSvc.cpp.

{
  DEBMSG << 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 ( UNLIKELY(sc.isFailure()) ) { return sc; }

  return StatusCode::SUCCESS;
}
void IncidentSvc::fireIncident ( const Incident incident ) [virtual]

Fire an Incident.

Parameters:
Incidentbeing fired

Implements IIncidentSvc.

Definition at line 280 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 212 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

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

    VERMSG << "Calling '" << getListenerName((*itlist).iListener)
           << "' for incident [" << incident.type() << "]" << endmsg;

    // handle exceptions if they occur
    try {
      (*itlist).iListener->handle(incident);
    }
    catch( const GaudiException& exc ) {
      error() << "Exception with tag=" << exc.tag() << " is caught"
                 " handling incident" << m_currentIncidentType << endmsg;
      error() <<  exc  << endmsg;
      if ( (*itlist).rethrow ) { throw (exc); }
    }
    catch( const std::exception& exc ) {
     error() << "Standard std::exception is caught"
          " handling incident" << m_currentIncidentType << endmsg;
      error() << exc.what()  << endmsg;
      if ( (*itlist).rethrow ) { throw (exc); }
    }
    catch(...) {
      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 ( void   ) [virtual]

Reimplemented from Service.

Definition at line 71 of file IncidentSvc.cpp.

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

  m_currentIncidentType = 0;

  // set my own (IncidentSvc) properties via the jobOptionService
  sc = setProperties();
  if ( UNLIKELY(sc.isFailure()) )
  {
    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:
lisListener address
typeIncident type

Implements IIncidentSvc.

Definition at line 143 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 {
            DEBMSG << "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

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.

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 97 of file IncidentSvc.h.

ChronoEntity IncidentSvc::m_timer [mutable, private]

timer & it's lock

Definition at line 100 of file IncidentSvc.h.

bool IncidentSvc::m_timerLock [mutable, private]

Definition at line 101 of file IncidentSvc.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:25:28 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004