Gaudi Framework, version v21r8

Home   Generated: 17 Mar 2010

EventLoopMgr.cpp

Go to the documentation of this file.
00001 // $Id: EventLoopMgr.cpp,v 1.26 2008/10/09 13:40:18 marcocle Exp $
00002 #define  GAUDISVC_EVENTLOOPMGR_CPP
00003 
00004 #include "GaudiKernel/SmartIF.h"
00005 #include "GaudiKernel/Incident.h"
00006 #include "GaudiKernel/MsgStream.h"
00007 #include "GaudiKernel/SvcFactory.h"
00008 #include "GaudiKernel/DataObject.h"
00009 #include "GaudiKernel/IIncidentSvc.h"
00010 #include "GaudiKernel/IEvtSelector.h"
00011 #include "GaudiKernel/IDataManagerSvc.h"
00012 #include "GaudiKernel/IDataProviderSvc.h"
00013 #include "GaudiKernel/IConversionSvc.h"
00014 
00015 #include "HistogramAgent.h"
00016 #include "EventLoopMgr.h"
00017 
00018 #include "GaudiKernel/WatchdogThread.h"
00019 
00020 #include <csignal>
00021 
00022 namespace {
00026   class SignalHandler {
00027   public:
00028 #ifdef _WIN32
00029     typedef void (__cdecl *handler_t)(int);
00030 #else
00031     typedef struct sigaction handler_t;
00032 #endif
00033 
00035     static SignalHandler &instance() {
00036       static SignalHandler sh;
00037       return sh;
00038     }
00039 
00042     void monitorSignal(int signum) {
00043       if (!m_monitored[signum]) {
00044         handler_t sa;
00045         handler_t oldact;
00046 #ifdef _WIN32
00047         sa = SignalHandler::dispatcher;
00048         oldact = signal(signum, sa);
00049 #else
00050         sa.sa_handler = SignalHandler::dispatcher;
00051         sigemptyset(&sa.sa_mask);
00052         sa.sa_flags = 0;
00053         sigaction(signum, &sa, &oldact);
00054 #endif
00055         m_oldActions[signum] = oldact;
00056         m_monitored[signum] = true;
00057       }
00058     }
00059 
00062     void ignoreSignal(int signum) {
00063       if (m_monitored[signum]) {
00064 #ifdef _WIN32
00065         (void) signal(signum, m_oldActions[signum]);
00066 #else
00067         sigaction(signum, &m_oldActions[signum], 0);
00068 #endif
00069         m_oldActions[signum] = m_defaultAction;
00070         m_monitored[signum] = false;
00071       }
00072     }
00073 
00075     bool gotSignal(int signum) const {
00076       return m_caught[signum] != 0;
00077     }
00078 
00080     void setSignal(int signum) {
00081       m_caught[signum] = 1;
00082     }
00083 
00085     void clearSignal(int signum) {
00086       m_caught[signum] = 0;
00087     }
00088 
00089   private:
00091     SignalHandler(){
00092 #ifdef _WIN32
00093       m_defaultAction = SIG_DFL;
00094 #else
00095       m_defaultAction.sa_handler = SIG_DFL;
00096       sigemptyset(&m_defaultAction.sa_mask);
00097       m_defaultAction.sa_flags = 0;
00098 #endif
00099       for(int i = 0; i < NSIG; ++i){
00100         m_caught[i] = 0;
00101         m_monitored[i] = false;
00102         m_oldActions[i] = m_defaultAction;
00103       }
00104     }
00105 
00107     bool             m_monitored[NSIG];
00109     sig_atomic_t     m_caught[NSIG];
00111     handler_t        m_defaultAction;
00113     handler_t        m_oldActions[NSIG];
00114 
00116     static void dispatcher(int signum);
00117   };
00118 
00119   // Implementation of the signal handler function.
00120   void SignalHandler::dispatcher(int signum){
00121     instance().m_caught[signum] = 1;
00122   }
00123 
00125   class EventWatchdog: public WatchdogThread {
00126   public:
00127     EventWatchdog(const SmartIF<IMessageSvc> &msgSvc,
00128                   const std::string &name,
00129                   boost::posix_time::time_duration timeout,
00130                   bool autostart = false):
00131         WatchdogThread(timeout, autostart),
00132         log(msgSvc, name),
00133         m_counter(0) {}
00134     virtual ~EventWatchdog() {}
00135   private:
00136     MsgStream log;
00137     long m_counter;
00138     void action() {
00139       if (!m_counter) {
00140         log << MSG::WARNING << "More than " << getTimeout().total_seconds()
00141             << "s to process an event." << endmsg;
00142       }
00143       else if (m_counter < 2) {
00144         log << MSG::WARNING << "Other " << getTimeout().total_seconds()
00145             << "s and we are still on the same event." << endmsg;
00146       }
00147       else if (m_counter < 3) {
00148         log << MSG::WARNING << "We are still at the same point:" << endmsg;
00149         // log << MSG::WARNING << "*** stack trace ***" << endmsg;
00150         log << MSG::WARNING << "I'm not going to print other messages for this event." << endmsg;
00151       }
00152       ++m_counter;
00153     }
00154     void onPing() {
00155       if (m_counter) {
00156         if (m_counter >= 3)
00157           log << MSG::INFO << "Starting a new event after ~"
00158               << m_counter * getTimeout().total_seconds() << "s" << endmsg;
00159         m_counter = 0;
00160       }
00161     }
00162     void onStop() {
00163       if (m_counter >= 3)
00164         log << MSG::INFO << "The last event took ~"
00165         << m_counter * getTimeout().total_seconds() << "s" << endmsg;
00166     }
00167   };
00168 }
00169 
00170 
00171 // Instantiation of a static factory class used by clients to create instances of this service
00172 DECLARE_SERVICE_FACTORY(EventLoopMgr)
00173 
00174 //--------------------------------------------------------------------------------------------
00175 // Standard Constructor
00176 //--------------------------------------------------------------------------------------------
00177 EventLoopMgr::EventLoopMgr(const std::string& nam, ISvcLocator* svcLoc)
00178 : MinimalEventLoopMgr(nam, svcLoc)
00179 {
00180   m_histoDataMgrSvc   = 0;
00181   m_histoPersSvc      = 0;
00182   m_evtDataMgrSvc     = 0;
00183   m_evtDataSvc        = 0;
00184   m_evtSelector       = 0;
00185   m_evtContext        = 0;
00186   m_endEventFired     = true;
00187 
00188   // Declare properties
00189   declareProperty("HistogramPersistency", m_histPersName = "");
00190   declareProperty("EvtSel", m_evtsel );
00191   declareProperty("Warnings",m_warnings=true,
00192                   "Set this property to false to suppress warning messages");
00193 
00194   declareProperty("HandleSIGINT", m_handleSIGINT = true,
00195                   "Intercept the SIGINT signal (CTRL-C) and stop the event loop.");
00196   declareProperty("HandleSIGXCPU", m_handleSIGXCPU = true,
00197                   "Intercept the SIGXCPU signal and stop the event loop (ignored on Windows).");
00198   declareProperty("EventTimeout", m_eventTimeout = 600,
00199                   "Number of seconds allowed to process a single event (0 to disable the check)");
00200 }
00201 
00202 //--------------------------------------------------------------------------------------------
00203 // Standard Destructor
00204 //--------------------------------------------------------------------------------------------
00205 EventLoopMgr::~EventLoopMgr()   {
00206   if( m_histoDataMgrSvc ) m_histoDataMgrSvc->release();
00207   if( m_histoPersSvc ) m_histoPersSvc->release();
00208   if( m_evtDataMgrSvc ) m_evtDataMgrSvc->release();
00209   if( m_evtDataSvc ) m_evtDataSvc->release();
00210   if( m_evtSelector ) m_evtSelector->release();
00211   if( m_evtContext ) delete m_evtContext;
00212 }
00213 
00214 //--------------------------------------------------------------------------------------------
00215 // implementation of IAppMgrUI::initialize
00216 //--------------------------------------------------------------------------------------------
00217 StatusCode EventLoopMgr::initialize()    {
00218   // Initialize the base class
00219   StatusCode sc = MinimalEventLoopMgr::initialize();
00220   MsgStream log(msgSvc(), name());
00221   if( !sc.isSuccess() ) {
00222     log << MSG::DEBUG << "Error Initializing base class MinimalEventLoopMgr." << endmsg;
00223     return sc;
00224   }
00225 
00226   // Setup access to event data services
00227   m_evtDataMgrSvc = serviceLocator()->service("EventDataSvc");
00228   if( !m_evtDataMgrSvc.isValid() )  {
00229     log << MSG::FATAL << "Error retrieving EventDataSvc interface IDataManagerSvc." << endmsg;
00230     return StatusCode::FAILURE;
00231   }
00232   m_evtDataSvc = serviceLocator()->service("EventDataSvc");
00233   if( !m_evtDataSvc.isValid() )  {
00234     log << MSG::FATAL << "Error retrieving EventDataSvc interface IDataProviderSvc." << endmsg;
00235     return StatusCode::FAILURE;
00236   }
00237 
00238   // Obtain the IProperty of the ApplicationMgr
00239   SmartIF<IProperty> prpMgr(serviceLocator());
00240   if ( ! prpMgr.isValid() )   {
00241     log << MSG::FATAL << "IProperty interface not found in ApplicationMgr." << endmsg;
00242     return StatusCode::FAILURE;
00243   }
00244   else {
00245     m_appMgrProperty = prpMgr;
00246   }
00247 
00248   // We do not expect a Event Selector necessarily being declared
00249   setProperty(m_appMgrProperty->getProperty("EvtSel")).ignore();
00250 
00251   if( m_evtsel != "NONE" || m_evtsel.length() == 0) {
00252     m_evtSelector = serviceLocator()->service("EventSelector");
00253     if( m_evtSelector.isValid() ) {
00254       // Setup Event Selector
00255       sc=m_evtSelector->createContext(m_evtContext);
00256       if( !sc.isSuccess() )   {
00257         log << MSG::FATAL << "Can not create the event selector Context." << endmsg;
00258         return sc;
00259       }
00260     }
00261     else {
00262       log << MSG::FATAL << "EventSelector not found." << endmsg;
00263       return sc;
00264     }
00265   }
00266   else {
00267     m_evtSelector = 0;
00268     m_evtContext = 0;
00269     if ( m_warnings ) {
00270       log << MSG::WARNING << "Unable to locate service \"EventSelector\" " << endmsg;
00271       log << MSG::WARNING << "No events will be processed from external input." << endmsg;
00272     }
00273   }
00274 
00275   // Setup access to histogramming services
00276   m_histoDataMgrSvc = serviceLocator()->service("HistogramDataSvc");
00277   if( !m_histoDataMgrSvc.isValid() )  {
00278     log << MSG::FATAL << "Error retrieving HistogramDataSvc." << endmsg;
00279     return sc;
00280   }
00281   // Setup histogram persistency
00282   m_histoPersSvc = serviceLocator()->service("HistogramPersistencySvc");
00283   if( !m_histoPersSvc.isValid() ) {
00284     log << MSG::WARNING << "Histograms cannot not be saved - though required." << endmsg;
00285     return sc;
00286   }
00287 
00288   if (m_eventTimeout) {
00289     m_watchdog = std::auto_ptr<WatchdogThread>(
00290         new EventWatchdog(msgSvc(),
00291             "EventWatchdog",
00292             boost::posix_time::seconds(m_eventTimeout)));
00293   }
00294 
00295   if (m_handleSIGINT) SignalHandler::instance().monitorSignal(SIGINT);
00296 #ifndef _WIN32
00297   if (m_handleSIGXCPU) SignalHandler::instance().monitorSignal(SIGXCPU);
00298 #endif
00299   return StatusCode::SUCCESS;
00300 }
00301 //--------------------------------------------------------------------------------------------
00302 // implementation of IService::reinitialize
00303 //--------------------------------------------------------------------------------------------
00304 StatusCode EventLoopMgr::reinitialize() {
00305   MsgStream log(msgSvc(), name());
00306 
00307   // Initialize the base class
00308   StatusCode sc = MinimalEventLoopMgr::reinitialize();
00309   if( !sc.isSuccess() ) {
00310     log << MSG::DEBUG << "Error Initializing base class MinimalEventLoopMgr." << endmsg;
00311     return sc;
00312   }
00313 
00314   // Check to see whether a new Event Selector has been specified
00315   setProperty(m_appMgrProperty->getProperty("EvtSel"));
00316   if( m_evtsel != "NONE" || m_evtsel.length() == 0) {
00317     SmartIF<IService> theSvc(serviceLocator()->service("EventSelector"));
00318     SmartIF<IEvtSelector> theEvtSel(theSvc);
00319     if( theEvtSel.isValid() && ( theEvtSel.get() != m_evtSelector.get() ) ) {
00320       // Setup Event Selector
00321       if ( m_evtSelector.get() && m_evtContext ) {
00322         // Need to release context before switching to new event selector
00323         m_evtSelector->releaseContext(m_evtContext);
00324         m_evtContext = 0;
00325       }
00326       m_evtSelector = theEvtSel;
00327       if (theSvc->FSMState() == Gaudi::StateMachine::INITIALIZED) {
00328         sc = theSvc->reinitialize();
00329         if( !sc.isSuccess() ) {
00330           log << MSG::ERROR << "Failure Reinitializing EventSelector "
00331               << theSvc->name( ) << endmsg;
00332           return sc;
00333         }
00334       }
00335       else {
00336         sc = theSvc->sysInitialize();
00337         if( !sc.isSuccess() ) {
00338           log << MSG::ERROR << "Failure Initializing EventSelector "
00339               << theSvc->name( ) << endmsg;
00340           return sc;
00341         }
00342       }
00343       sc = m_evtSelector->createContext(m_evtContext);
00344       if( !sc.isSuccess() ) {
00345         log << MSG::ERROR << "Can not create Context "
00346             << theSvc->name( ) << endmsg;
00347         return sc;
00348       }
00349       log << MSG::INFO << "EventSelector service changed to "
00350           << theSvc->name( ) << endmsg;
00351     }
00352     else if ( m_evtSelector.isValid() ) {
00353       if ( m_evtContext ) {
00354         m_evtSelector->releaseContext(m_evtContext);
00355         m_evtContext = 0;
00356       }
00357       sc = m_evtSelector->createContext(m_evtContext);
00358       if( !sc.isSuccess() ) {
00359         log << MSG::ERROR << "Can not create Context "
00360             << theSvc->name( ) << endmsg;
00361         return sc;
00362       }
00363     }
00364   }
00365   else if ( m_evtSelector.isValid() && m_evtContext ) {
00366     m_evtSelector->releaseContext(m_evtContext);
00367     m_evtSelector = 0;
00368     m_evtContext = 0;
00369   }
00370   return StatusCode::SUCCESS;
00371 }
00372 
00373 
00374 //--------------------------------------------------------------------------------------------
00375 // implementation of IService::stop
00376 //--------------------------------------------------------------------------------------------
00377 StatusCode EventLoopMgr::stop()    {
00378   if ( ! m_endEventFired ) {
00379     // Fire pending EndEvent incident
00380     m_incidentSvc->fireIncident(Incident(name(),IncidentType::EndEvent));
00381     m_endEventFired = true;
00382   }
00383   return MinimalEventLoopMgr::stop();
00384 }
00385 
00386 //--------------------------------------------------------------------------------------------
00387 // implementation of IAppMgrUI::finalize
00388 //--------------------------------------------------------------------------------------------
00389 StatusCode EventLoopMgr::finalize()    {
00390   StatusCode sc;
00391   MsgStream log(msgSvc(), name());
00392 
00393   // Finalize base class
00394   sc = MinimalEventLoopMgr::finalize();
00395   if (! sc.isSuccess()) {
00396     log << MSG::ERROR << "Error finalizing base class" << endmsg;
00397     return sc;
00398   }
00399 
00400   if (m_handleSIGINT) SignalHandler::instance().ignoreSignal(SIGINT);
00401 #ifndef _WIN32
00402   if (m_handleSIGXCPU) SignalHandler::instance().ignoreSignal(SIGXCPU);
00403 #endif
00404 
00405   // Save Histograms Now
00406   if ( m_histoPersSvc != 0 )    {
00407     HistogramAgent agent;
00408     sc = m_histoDataMgrSvc->traverseTree( &agent );
00409     if( sc.isSuccess() )   {
00410       IDataSelector* objects = agent.selectedObjects();
00411       // skip /stat entry!
00412       if ( objects->size() > 0 )    {
00413         IDataSelector::iterator i;
00414         for ( i = objects->begin(); i != objects->end(); i++ )    {
00415           IOpaqueAddress* pAddr = 0;
00416           StatusCode iret = m_histoPersSvc->createRep(*i, pAddr);
00417           if ( iret.isSuccess() )     {
00418             (*i)->registry()->setAddress(pAddr);
00419           }
00420           else  {
00421             sc = iret;
00422           }
00423         }
00424         for ( i = objects->begin(); i != objects->end(); i++ )    {
00425           IRegistry* reg = (*i)->registry();
00426           StatusCode iret = m_histoPersSvc->fillRepRefs(reg->address(), *i);
00427           if ( !iret.isSuccess() )    {
00428             sc = iret;
00429           }
00430         }
00431       }
00432       if ( sc.isSuccess() )    {
00433         log << MSG::INFO << "Histograms converted successfully according to request." << endmsg;
00434       }
00435       else  {
00436         log << MSG::ERROR << "Error while saving Histograms." << endmsg;
00437       }
00438     }
00439     else {
00440       log << MSG::ERROR << "Error while traversing Histogram data store" << endmsg;
00441     }
00442   }
00443 
00444   // Release event selector context
00445   if ( m_evtSelector && m_evtContext )   {
00446     m_evtSelector->releaseContext(m_evtContext).ignore();
00447     m_evtContext = 0;
00448   }
00449 
00450   // Release all interfaces...
00451   m_histoDataMgrSvc = 0;
00452   m_histoPersSvc    = 0;
00453 
00454   m_evtSelector     = 0;
00455   m_evtDataSvc      = 0;
00456   m_evtDataMgrSvc   = 0;
00457 
00458   return StatusCode::SUCCESS;
00459 }
00460 
00461 
00462 //--------------------------------------------------------------------------------------------
00463 // executeEvent(void* par)
00464 //--------------------------------------------------------------------------------------------
00465 StatusCode EventLoopMgr::executeEvent(void* par)    {
00466 
00467   // Fire BeginEvent "Incident"
00468   m_incidentSvc->fireIncident(Incident(name(),IncidentType::BeginEvent));
00469   // An incident may schedule a stop, in which case is better to exit before the actual execution.
00470   if ( m_scheduledStop ) {
00471     MsgStream  log( msgSvc(), name() );
00472     log << MSG::ALWAYS << "Terminating event processing loop due to a stop scheduled by an incident listener" << endmsg;
00473     return StatusCode::SUCCESS;
00474   }
00475 
00476   // Execute Algorithms
00477   StatusCode sc = MinimalEventLoopMgr::executeEvent(par);
00478 
00479   // Check if there was an error processing current event
00480   if( !sc.isSuccess() ){
00481     MsgStream log( msgSvc(), name() );
00482     log << MSG::ERROR << "Terminating event processing loop due to errors" << endmsg;
00483   }
00484   return sc;
00485 }
00486 
00487 //--------------------------------------------------------------------------------------------
00488 // IEventProcessing::executeRun
00489 //--------------------------------------------------------------------------------------------
00490 StatusCode EventLoopMgr::executeRun( int maxevt )    {
00491   StatusCode  sc;
00492   // initialize the base class
00493   sc = MinimalEventLoopMgr::executeRun(maxevt);
00494   return sc;
00495 }
00496 
00497 //--------------------------------------------------------------------------------------------
00498 // implementation of IAppMgrUI::nextEvent
00499 //--------------------------------------------------------------------------------------------
00500 StatusCode EventLoopMgr::nextEvent(int maxevt)   {
00501   static int        total_nevt = 0;
00502   DataObject*       pObject = 0;
00503   StatusCode        sc(StatusCode::SUCCESS, true);
00504   MsgStream         log( msgSvc(), name() );
00505 
00506   if (m_watchdog.get()) m_watchdog->start();
00507 
00508   // loop over events if the maxevt (received as input) if different from -1.
00509   // if evtmax is -1 it means infinite loop
00510   for( int nevt = 0; (maxevt == -1 ? true : nevt < maxevt);  nevt++, total_nevt++) {
00511     if (m_watchdog.get()) m_watchdog->ping();
00512 
00513     if (
00514         SignalHandler::instance().gotSignal(SIGINT)
00515 #ifndef _WIN32              
00516         or SignalHandler::instance().gotSignal(SIGXCPU)
00517 #endif
00518         ){
00519       log << MSG::ALWAYS << "Stop of event loop after receiving a ";
00520       if (SignalHandler::instance().gotSignal(SIGINT)) {
00521         log << "SIGINT";
00522       }
00523 #ifndef _WIN32
00524       else {
00525         log << "SIGXCPU";
00526       }
00527 #endif
00528       log << " signal" << endmsg;
00529       // Clear the signal flags
00530       if (SignalHandler::instance().gotSignal(SIGINT))
00531         SignalHandler::instance().clearSignal(SIGINT);
00532 #ifndef _WIN32
00533       if (SignalHandler::instance().gotSignal(SIGXCPU))
00534         SignalHandler::instance().clearSignal(SIGXCPU);
00535 #endif
00536       break;
00537     }
00538 
00539     // Check if there is a scheduled stop issued by some algorithm/service
00540     if ( m_scheduledStop ) {
00541       m_scheduledStop = false;
00542       log << MSG::ALWAYS << "Terminating event processing loop due to scheduled stop" << endmsg;
00543       break;
00544     }
00545     // Clear the event store, if used in the event loop
00546     if( 0 != total_nevt ) {
00547 
00548       if ( ! m_endEventFired ) {
00549         // Fire EndEvent "Incident" (it is considered part of the clearing of the TS)
00550         m_incidentSvc->fireIncident(Incident(name(),IncidentType::EndEvent));
00551         m_endEventFired = true;
00552       }
00553       sc = m_evtDataMgrSvc->clearStore();
00554       if( !sc.isSuccess() )  {
00555         log << MSG::DEBUG << "Clear of Event data store failed" << endmsg;
00556       }
00557     }
00558 
00559     // Setup event in the event store
00560     if( m_evtContext ) {
00561       IOpaqueAddress* addr = 0;
00562       // Only if there is a EventSelector
00563       sc = getEventRoot(addr);
00564       if( !sc.isSuccess() )  {
00565         log << MSG::INFO << "No more events in event selection " << endmsg;
00566         break;
00567       }
00568       // Set root clears the event data store first
00569       sc = m_evtDataMgrSvc->setRoot ("/Event", addr);
00570       if( !sc.isSuccess() )  {
00571         log << MSG::WARNING << "Error declaring event root address." << endmsg;
00572         continue;
00573       }
00574       sc = m_evtDataSvc->retrieveObject("/Event", pObject);
00575       if( !sc.isSuccess() ) {
00576         log << MSG::WARNING << "Unable to retrieve Event root object" << endmsg;
00577         break;
00578       }
00579     }
00580     else {
00581       sc = m_evtDataMgrSvc->setRoot ("/Event", new DataObject());
00582       if( !sc.isSuccess() )  {
00583         log << MSG::WARNING << "Error declaring event root DataObject" << endmsg;
00584       }
00585     }
00586     // Execute event for all required algorithms
00587     sc = executeEvent(NULL);
00588     m_endEventFired = false;
00589     if( !sc.isSuccess() ){
00590       log << MSG::ERROR << "Terminating event processing loop due to errors" << endmsg;
00591       break;
00592     }
00593   }
00594   if (m_watchdog.get()) m_watchdog->stop();
00595   return StatusCode::SUCCESS;
00596 }
00597 
00599 StatusCode EventLoopMgr::getEventRoot(IOpaqueAddress*& refpAddr)  {
00600   refpAddr = 0;
00601   StatusCode sc = m_evtSelector->next(*m_evtContext);
00602   if ( !sc.isSuccess() )  {
00603     return sc;
00604   }
00605   // Create root address and assign address to data service
00606   sc = m_evtSelector->createAddress(*m_evtContext,refpAddr);
00607   if( !sc.isSuccess() )  {
00608     sc = m_evtSelector->next(*m_evtContext);
00609     if ( sc.isSuccess() )  {
00610       sc = m_evtSelector->createAddress(*m_evtContext,refpAddr);
00611       if ( !sc.isSuccess() )  {
00612         MsgStream log( msgSvc(), name() );
00613         log << MSG::WARNING << "Error creating IOpaqueAddress." << endmsg;
00614       }
00615     }
00616   }
00617   return sc;
00618 }

Generated at Wed Mar 17 18:06:41 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004