00001
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
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
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
00172 DECLARE_SERVICE_FACTORY(EventLoopMgr)
00173
00174
00175
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
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
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
00216
00217 StatusCode EventLoopMgr::initialize() {
00218
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
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
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
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
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
00276 m_histoDataMgrSvc = serviceLocator()->service("HistogramDataSvc");
00277 if( !m_histoDataMgrSvc.isValid() ) {
00278 log << MSG::FATAL << "Error retrieving HistogramDataSvc." << endmsg;
00279 return sc;
00280 }
00281
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
00303
00304 StatusCode EventLoopMgr::reinitialize() {
00305 MsgStream log(msgSvc(), name());
00306
00307
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
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
00321 if ( m_evtSelector.get() && m_evtContext ) {
00322
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
00376
00377 StatusCode EventLoopMgr::stop() {
00378 if ( ! m_endEventFired ) {
00379
00380 m_incidentSvc->fireIncident(Incident(name(),IncidentType::EndEvent));
00381 m_endEventFired = true;
00382 }
00383 return MinimalEventLoopMgr::stop();
00384 }
00385
00386
00387
00388
00389 StatusCode EventLoopMgr::finalize() {
00390 StatusCode sc;
00391 MsgStream log(msgSvc(), name());
00392
00393
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
00406 if ( m_histoPersSvc != 0 ) {
00407 HistogramAgent agent;
00408 sc = m_histoDataMgrSvc->traverseTree( &agent );
00409 if( sc.isSuccess() ) {
00410 IDataSelector* objects = agent.selectedObjects();
00411
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
00445 if ( m_evtSelector && m_evtContext ) {
00446 m_evtSelector->releaseContext(m_evtContext).ignore();
00447 m_evtContext = 0;
00448 }
00449
00450
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
00464
00465 StatusCode EventLoopMgr::executeEvent(void* par) {
00466
00467
00468 m_incidentSvc->fireIncident(Incident(name(),IncidentType::BeginEvent));
00469
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
00477 StatusCode sc = MinimalEventLoopMgr::executeEvent(par);
00478
00479
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
00489
00490 StatusCode EventLoopMgr::executeRun( int maxevt ) {
00491 StatusCode sc;
00492
00493 sc = MinimalEventLoopMgr::executeRun(maxevt);
00494 return sc;
00495 }
00496
00497
00498
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
00509
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
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
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
00546 if( 0 != total_nevt ) {
00547
00548 if ( ! m_endEventFired ) {
00549
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
00560 if( m_evtContext ) {
00561 IOpaqueAddress* addr = 0;
00562
00563 sc = getEventRoot(addr);
00564 if( !sc.isSuccess() ) {
00565 log << MSG::INFO << "No more events in event selection " << endmsg;
00566 break;
00567 }
00568
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
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
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 }