00001
00002 #include "ApplicationMgr.h"
00003 #include "ServiceManager.h"
00004 #include "AlgorithmManager.h"
00005 #include "DLLClassManager.h"
00006
00007 #include "GaudiKernel/TypeNameString.h"
00008 #include "GaudiKernel/IService.h"
00009 #include "GaudiKernel/IRunable.h"
00010 #include "GaudiKernel/IMessageSvc.h"
00011 #include "GaudiKernel/IJobOptionsSvc.h"
00012
00013 #include "GaudiKernel/SmartIF.h"
00014 #include "GaudiKernel/MsgStream.h"
00015 #include "GaudiKernel/PropertyMgr.h"
00016 #include "GaudiKernel/ObjectFactory.h"
00017
00018 #include "GaudiKernel/GaudiException.h"
00019 #include "GaudiKernel/ThreadGaudi.h"
00020
00021 #include "GaudiKernel/StatusCode.h"
00022 #include "GaudiKernel/Time.h"
00023 #include "GaudiKernel/System.h"
00024
00025 #include "GaudiKernel/AppReturnCode.h"
00026
00027 #include "GaudiCoreSvcVersion.h"
00028
00029
00030 using System::getEnv;
00031 using System::isEnvSet;
00032
00033 #include <algorithm>
00034 #include <cassert>
00035 #include <ctime>
00036 #include <limits>
00037
00038 static const char* s_eventloop = "EventLoop";
00039 static const char* s_runable = "Runable";
00040
00041 #define ON_DEBUG if (UNLIKELY(m_outputLevel <= MSG::DEBUG))
00042 #define ON_VERBOSE if (UNLIKELY(m_outputLevel <= MSG::VERBOSE))
00043
00044 DECLARE_OBJECT_FACTORY(ApplicationMgr)
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 ApplicationMgr::ApplicationMgr(IInterface*): base_class() {
00055
00056 addRef();
00057
00058
00059 m_messageSvc = 0;
00060 m_jobOptionsSvc = 0;
00061
00062
00063 m_managers[IService::interfaceID().id()] = new ServiceManager(this);
00064 m_managers[IAlgorithm::interfaceID().id()] = new AlgorithmManager(this);
00065
00066 m_svcLocator = svcManager();
00067
00068
00069
00070 m_classManager = new DLLClassManager(this);
00071 m_propertyMgr = new PropertyMgr(this);
00072
00073 m_name = "ApplicationMgr";
00074 m_state = Gaudi::StateMachine::OFFLINE;
00075 m_targetState = Gaudi::StateMachine::OFFLINE;
00076
00077 m_propertyMgr->declareProperty("Go", m_SIGo = 0 );
00078 m_propertyMgr->declareProperty("Exit", m_SIExit = 0 );
00079 m_propertyMgr->declareProperty("Dlls", m_dllNameList );
00080 m_propertyMgr->declareProperty("ExtSvc", m_extSvcNameList );
00081 m_propertyMgr->declareProperty("CreateSvc", m_createSvcNameList );
00082 m_propertyMgr->declareProperty("ExtSvcCreates", m_extSvcCreates=true );
00083
00084 m_propertyMgr->declareProperty("SvcMapping", m_svcMapping );
00085 m_propertyMgr->declareProperty("SvcOptMapping", m_svcOptMapping );
00086
00087 m_propertyMgr->declareProperty("TopAlg", m_topAlgNameList );
00088 m_propertyMgr->declareProperty("OutStream", m_outStreamNameList );
00089 m_propertyMgr->declareProperty("OutStreamType", m_outStreamType = "OutputStream" );
00090 m_propertyMgr->declareProperty("MessageSvcType",m_messageSvcType= "MessageSvc" );
00091 m_propertyMgr->declareProperty("JobOptionsSvcType",
00092 m_jobOptionsSvcType = "JobOptionsSvc" );
00093 m_propertyMgr->declareProperty( s_runable, m_runableType = "AppMgrRunable");
00094 m_propertyMgr->declareProperty( s_eventloop, m_eventLoopMgr = "EventLoopMgr");
00095
00096 m_propertyMgr->declareProperty("HistogramPersistency", m_histPersName="NONE");
00097
00098
00099 m_propertyMgr->declareProperty("JobOptionsType", m_jobOptionsType = "FILE");
00100 m_propertyMgr->declareProperty("JobOptionsPath", m_jobOptionsPath = "");
00101 m_propertyMgr->declareProperty("EvtMax", m_evtMax = -1);
00102 m_propertyMgr->declareProperty("EvtSel", m_evtsel );
00103 m_propertyMgr->declareProperty("OutputLevel", m_outputLevel = MSG::INFO);
00104
00105 m_propertyMgr->declareProperty("MultiThreadExtSvc", m_multiThreadSvcNameList);
00106 m_propertyMgr->declareProperty("NoOfThreads", m_noOfEvtThreads = 0);
00107 m_propertyMgr->declareProperty("AppName", m_appName = "ApplicationMgr");
00108 m_propertyMgr->declareProperty("AppVersion", m_appVersion = "");
00109
00110 m_propertyMgr->declareProperty("AuditTools", m_auditTools = false);
00111 m_propertyMgr->declareProperty("AuditServices", m_auditSvcs = false);
00112 m_propertyMgr->declareProperty("AuditAlgorithms", m_auditAlgs = false);
00113
00114 m_propertyMgr->declareProperty("ActivateHistory", m_actHistory = false);
00115 m_propertyMgr->declareProperty("StatusCodeCheck", m_codeCheck = false);
00116
00117 m_propertyMgr->declareProperty("Environment", m_environment);
00118
00119
00120 m_propertyMgr->declareProperty("InitializationLoopCheck", m_loopCheck = true)
00121 ->declareUpdateHandler(&ApplicationMgr::initLoopCheckHndlr, this);
00122 svcManager()->setLoopCheckEnabled(m_loopCheck);
00123
00124
00125 m_propertyMgr->declareProperty
00126 ( "PropertiesPrint",
00127 m_propertiesPrint = false,
00128 "Flag to activate the printout of properties" );
00129
00130 m_propertyMgr->declareProperty("ReflexPluginDebugLevel", m_reflexDebugLevel = 0 );
00131
00132 m_propertyMgr->declareProperty("StopOnSignal", m_stopOnSignal = false,
00133 "Flag to enable/disable the signal handler that schedule a stop of the event loop");
00134
00135 m_propertyMgr->declareProperty("StalledEventMonitoring", m_stalledEventMonitoring = false,
00136 "Flag to enable/disable the monitoring and reporting of stalled events");
00137
00138 m_propertyMgr->declareProperty("ReturnCode", m_returnCode = 0,
00139 "Return code of the application. Set internally in case of error conditions.");
00140
00141
00142 m_SIGo.declareUpdateHandler ( &ApplicationMgr::SIGoHandler , this );
00143 m_SIExit.declareUpdateHandler( &ApplicationMgr::SIExitHandler , this );
00144 m_topAlgNameList.declareUpdateHandler(&ApplicationMgr::evtLoopPropertyHandler, this);
00145 m_outStreamNameList.declareUpdateHandler(&ApplicationMgr::evtLoopPropertyHandler, this);
00146 m_outStreamType.declareUpdateHandler(&ApplicationMgr::evtLoopPropertyHandler, this);
00147 m_reflexDebugLevel.declareUpdateHandler(&ApplicationMgr::reflexDebugPropertyHandler, this);
00148 m_svcMapping.push_back("EvtDataSvc/EventDataSvc");
00149 m_svcMapping.push_back("DetDataSvc/DetectorDataSvc");
00150 m_svcMapping.push_back("HistogramSvc/HistogramDataSvc");
00151 m_svcMapping.push_back("HbookCnv::PersSvc/HbookHistSvc");
00152 m_svcMapping.push_back("RootHistCnv::PersSvc/RootHistSvc");
00153 m_svcMapping.push_back("EvtPersistencySvc/EventPersistencySvc");
00154 m_svcMapping.push_back("DetPersistencySvc/DetectorPersistencySvc");
00155 m_svcMapping.push_back("HistogramPersistencySvc/HistogramPersistencySvc");
00156 }
00157
00158
00159
00160
00161 ApplicationMgr::~ApplicationMgr() {
00162 if( m_classManager ) m_classManager->release();
00163 if( m_propertyMgr ) m_propertyMgr->release();
00164 if( m_messageSvc ) m_messageSvc->release();
00165 if( m_jobOptionsSvc ) m_jobOptionsSvc->release();
00166 }
00167
00168
00169
00170
00171 StatusCode ApplicationMgr::queryInterface
00172 ( const InterfaceID& iid ,
00173 void** ppvi )
00174 {
00175 if ( 0 == ppvi ) { return StatusCode::FAILURE ; }
00176
00177
00178 StatusCode sc = base_class::queryInterface(iid,ppvi);
00179 if (sc.isSuccess()) return sc;
00180
00181
00182 if ( ISvcLocator ::interfaceID() . versionMatch ( iid ) )
00183 { return serviceLocator()-> queryInterface ( iid , ppvi ) ; }
00184 else if ( ISvcManager ::interfaceID() . versionMatch ( iid ) )
00185 { return svcManager() -> queryInterface ( iid , ppvi ) ; }
00186 else if ( IAlgManager ::interfaceID() . versionMatch ( iid ) )
00187 { return algManager() -> queryInterface ( iid , ppvi ) ; }
00188 else if ( IClassManager ::interfaceID() . versionMatch ( iid ) )
00189 { return m_classManager -> queryInterface ( iid , ppvi ) ; }
00190 else if ( IProperty ::interfaceID() . versionMatch ( iid ) )
00191 { return m_propertyMgr -> queryInterface ( iid , ppvi ) ; }
00192 else if ( IMessageSvc ::interfaceID() . versionMatch ( iid ) )
00193 {
00194 *ppvi = reinterpret_cast<void*>(m_messageSvc.get());
00195 if (m_messageSvc) {
00196 m_messageSvc->addRef();
00197 }
00198
00199
00200 return StatusCode::SUCCESS;
00201 }
00202 *ppvi = 0;
00203 return StatusCode::FAILURE;
00204 }
00205
00206
00207
00208
00209 StatusCode ApplicationMgr::i_startup() {
00210 StatusCode sc;
00211
00212
00213 m_classManager->loadModule("").ignore();
00214
00215
00216 SmartIF<IService> msgsvc = svcManager()->createService(Gaudi::Utils::TypeNameString("MessageSvc", m_messageSvcType));
00217 if( !msgsvc.isValid() ) {
00218 fatal() << "Error creating MessageSvc of type " << m_messageSvcType << endmsg;
00219 return sc;
00220 }
00221
00222 SmartIF<IService> jobsvc = svcManager()->createService(Gaudi::Utils::TypeNameString("JobOptionsSvc", m_jobOptionsSvcType));
00223 if( !jobsvc.isValid() ) {
00224 fatal() << "Error creating JobOptionsSvc" << endmsg;
00225 return sc;
00226 }
00227
00228 SmartIF<IProperty> jobOptsIProp(jobsvc);
00229 if ( !jobOptsIProp.isValid() ) {
00230 fatal() << "Error locating JobOptionsSvc" << endmsg;
00231 return sc;
00232 }
00233 sc = jobOptsIProp->setProperty( StringProperty("TYPE", m_jobOptionsType) );
00234 if( !sc.isSuccess() ) {
00235 fatal() << "Error setting TYPE option in JobOptionsSvc" << endmsg;
00236 return sc;
00237 }
00238
00239 if ( m_jobOptionsPath != "") {
00240 sc = jobOptsIProp->setProperty( StringProperty("PATH", m_jobOptionsPath) );
00241 if( !sc.isSuccess() ) {
00242 fatal() << "Error setting PATH option in JobOptionsSvc" << endmsg;
00243 return sc;
00244 }
00245 }
00246 else if ( isEnvSet("JOBOPTPATH") ) {
00247 sc = jobOptsIProp->setProperty (StringProperty("PATH",
00248 getEnv("JOBOPTPATH")));
00249 if( !sc.isSuccess() ) {
00250 fatal()
00251 << "Error setting PATH option in JobOptionsSvc from env"
00252 << endmsg;
00253 return sc;
00254 }
00255 }
00256 else {
00257 sc = jobOptsIProp->setProperty (StringProperty("PATH",
00258 "../options/job.opts"));
00259 if( !sc.isSuccess() ) {
00260 fatal()
00261 << "Error setting PATH option in JobOptionsSvc to default"
00262 << endmsg;
00263 return sc;
00264 }
00265 }
00266 jobOptsIProp->release();
00267
00268
00269
00270 SmartIF<IProperty> msgSvcIProp(msgsvc);
00271 msgSvcIProp->setProperty( IntegerProperty("OutputLevel", m_outputLevel)).ignore();
00272 msgSvcIProp->release();
00273
00274 sc = jobsvc->sysInitialize();
00275 if( !sc.isSuccess() ) {
00276 fatal() << "Error initializing JobOptionsSvc" << endmsg;
00277 return sc;
00278 }
00279 sc = msgsvc->sysInitialize();
00280 if( !sc.isSuccess() ) {
00281 fatal() << "Error initializing MessageSvc" << endmsg;
00282 return sc;
00283 }
00284
00285
00286 m_messageSvc = m_svcLocator->service("MessageSvc");
00287 if( !m_messageSvc.isValid() ) {
00288 fatal() << "Error retrieving MessageSvc." << endmsg;
00289 return sc;
00290 }
00291 m_jobOptionsSvc = m_svcLocator->service("JobOptionsSvc");
00292 if( !m_jobOptionsSvc.isValid() ) {
00293 fatal() << "Error retrieving JobOptionsSvc." << endmsg;
00294 return sc;
00295 }
00296
00297 return sc;
00298 }
00299
00300
00301
00302
00303 StatusCode ApplicationMgr::configure() {
00304
00305 MsgStream tlog( m_messageSvc, name() );
00306 if( Gaudi::StateMachine::CONFIGURED == m_state ) {
00307 tlog << MSG::INFO << "Already Configured" << endmsg;
00308 return StatusCode::SUCCESS;
00309 }
00310 else if( Gaudi::StateMachine::OFFLINE != m_state ) {
00311 tlog << MSG::FATAL
00312 << "configure: Invalid state \"" << m_state << "\"" << endmsg;
00313 return StatusCode::FAILURE;
00314 }
00315 m_targetState = Gaudi::StateMachine::CONFIGURED;
00316
00317 StatusCode sc;
00318 sc = i_startup();
00319 if ( !sc.isSuccess() ) {
00320 return sc;
00321 }
00322
00323 MsgStream log( m_messageSvc, name() );
00324
00325
00326 if (log.level() <= MSG::DEBUG)
00327 log << MSG::DEBUG << "Getting my own properties" << endmsg;
00328 sc = m_jobOptionsSvc->setMyProperties( name(), m_propertyMgr );
00329 if( !sc.isSuccess() ) {
00330 log << MSG::WARNING << "Problems getting my properties from JobOptionsSvc"
00331 << endmsg;
00332 return sc;
00333 }
00334
00335
00336 if( m_outputLevel != MSG::NIL && !m_appName.empty() ) {
00337 assert(m_messageSvc != 0);
00338 m_messageSvc->setOutputLevel( name(), m_outputLevel );
00339
00340 log << MSG::ALWAYS
00341 << std::endl
00342 << "=================================================================="
00343 << "=================================================================="
00344 << std::endl
00345 << " "
00346 << " Welcome to " << m_appName;
00347
00348 if( "" != m_appVersion ) {
00349 log << MSG::ALWAYS << " version " << m_appVersion;
00350 }
00351 else {
00352 log << MSG::ALWAYS
00353 << " (GaudiCoreSvc "
00354 << "v" << GAUDICORESVC_MAJOR_VERSION
00355 << "r" << GAUDICORESVC_MINOR_VERSION
00356 #if GAUDICORESVC_PATCH_VERSION
00357 << "p" << GAUDICORESVC_PATCH_VERSION
00358 #endif
00359 << ")";
00360 }
00361
00362
00363 log << MSG::ALWAYS
00364 << std::endl
00365 << " "
00366 << " running on " << System::hostName()
00367 << " on " << Gaudi::Time::current().format(true) << std::endl
00368 << "=================================================================="
00369 << "=================================================================="
00370 << endmsg;
00371 }
00372
00373
00374 if ( m_propertiesPrint )
00375 {
00376 typedef std::vector<Property*> Properties;
00377 const Properties& properties = m_propertyMgr->getProperties() ;
00378 log << MSG::ALWAYS
00379 << "List of ALL properties of "
00380 << System::typeinfoName ( typeid( *this ) ) << "/" << this->name()
00381 << " #properties = " << properties.size() << endmsg ;
00382 for ( Properties::const_iterator property = properties.begin() ;
00383 properties.end() != property ; ++property )
00384 { log << "Property ['Name': Value] = " << ( **property) << endmsg ; }
00385 }
00386
00387
00388 if (m_codeCheck) {
00389 StatusCode::enableChecking();
00390 sc = addMultiSvc("StatusCodeSvc", -9999);
00391 if ( sc.isFailure() ) {
00392 log << MSG::FATAL << "Error adding StatusCodeSvc for multiple threads" << endmsg;
00393 return StatusCode::FAILURE;
00394 }
00395 } else {
00396 StatusCode::disableChecking();
00397 }
00398
00399
00400 std::map<std::string,std::string>::iterator var;
00401 for ( var = m_environment.begin(); var != m_environment.end(); ++var ) {
00402 const std::string &name = var->first;
00403 const std::string &value = var->second;
00404 std::string old = System::getEnv(name.c_str());
00405 const MSG::Level lvl = (!old.empty() && (old != "UNKNOWN" ))
00406 ? MSG::WARNING
00407 : MSG::DEBUG;
00408 if (UNLIKELY(m_outputLevel <= lvl))
00409 log << lvl << "Setting " << name << " = " << value << endmsg;
00410 System::setEnv(name,value);
00411 }
00412
00413
00414 VectorName::const_iterator j;
00415 for(j=m_svcMapping.begin(); j != m_svcMapping.end(); ++j) {
00416 Gaudi::Utils::TypeNameString itm(*j);
00417 if ( declareMultiSvcType(itm.name(), itm.type()).isFailure() ) {
00418 log << MSG::ERROR << "configure: declaring svc type:'" << *j << "' failed." << endmsg;
00419 return StatusCode::FAILURE;
00420 }
00421 }
00422 for(j=m_svcOptMapping.begin(); j != m_svcOptMapping.end(); ++j) {
00423 Gaudi::Utils::TypeNameString itm(*j);
00424 if ( declareMultiSvcType(itm.name(), itm.type()).isFailure() ) {
00425 log << MSG::ERROR << "configure: declaring svc type:'" << *j << "' failed." << endmsg;
00426 return StatusCode::FAILURE;
00427 }
00428 }
00429
00430
00431
00432 sc = decodeDllNameList( );
00433 if ( sc.isFailure( ) ) {
00434 log << MSG::ERROR << "Failure loading declared DLL's" << endmsg;
00435 return sc;
00436 }
00437
00438
00439
00440 sc = decodeExtSvcNameList();
00441 if ( sc.isFailure( ) ) {
00442 log << MSG::ERROR << "Failure during external service association" << endmsg;
00443 return sc;
00444 }
00445
00446 sc = decodeMultiThreadSvcNameList( );
00447 if ( sc.isFailure( ) ) {
00448 log << MSG::ERROR << "Failure during multi thread service creation"
00449 << endmsg;
00450 return sc;
00451 }
00452
00453 sc = decodeCreateSvcNameList();
00454 if ( sc.isFailure( ) ) {
00455 log << MSG::ERROR << "Failure during external service creation" << endmsg;
00456 return sc;
00457 }
00458
00459
00460
00461
00462
00463 Gaudi::Utils::TypeNameString evtloop_item(m_eventLoopMgr);
00464 sc = addMultiSvc(evtloop_item, 100);
00465 if( !sc.isSuccess() ) {
00466 log << MSG::FATAL << "Error adding :" << m_eventLoopMgr << endmsg;
00467 return sc;
00468 }
00469
00470 if (m_noOfEvtThreads == 0) {
00471 m_runable = m_svcLocator->service(m_runableType);
00472 if( !m_runable.isValid() ) {
00473 log << MSG::FATAL
00474 << "Error retrieving Runable:" << m_runableType
00475 << "\n Check option ApplicationMgr." << s_runable << endmsg;
00476 return sc;
00477 }
00478 m_processingMgr = m_svcLocator->service(evtloop_item);
00479 if( !m_processingMgr.isValid() ) {
00480 log << MSG::FATAL
00481 << "Error retrieving Processing manager:" << m_eventLoopMgr
00482 << "\n Check option ApplicationMgr." << s_eventloop
00483 << "\n No events will be processed." << endmsg;
00484 return sc;
00485 }
00486 }
00487
00488
00489 m_extSvcNameList.declareUpdateHandler (&ApplicationMgr::extSvcNameListHandler,
00490 this);
00491 m_createSvcNameList.declareUpdateHandler (&ApplicationMgr::createSvcNameListHandler,
00492 this);
00493 m_multiThreadSvcNameList.declareUpdateHandler
00494 (&ApplicationMgr::multiThreadSvcNameListHandler, this);
00495 m_dllNameList.declareUpdateHandler (&ApplicationMgr::dllNameListHandler,
00496 this );
00497
00498 if (m_actHistory) {
00499
00500 sc = svcManager()->addService("HistorySvc",std::numeric_limits<int>::max());
00501 if ( sc.isFailure() ) {
00502 log << MSG::FATAL << "Error adding HistorySvc" << endmsg;
00503 return StatusCode::FAILURE;
00504 }
00505
00506 if (m_noOfEvtThreads > 0) {
00507 sc = addMultiSvc("HistorySvc",std::numeric_limits<int>::max());
00508 if ( sc.isFailure() ) {
00509 log << MSG::FATAL << "Error adding HistorySvc for multiple threads"
00510 << endmsg;
00511 return StatusCode::FAILURE;
00512 }
00513 }
00514 }
00515
00516 log << MSG::INFO << "Application Manager Configured successfully" << endmsg;
00517 m_state = m_targetState;
00518 return StatusCode::SUCCESS;
00519 }
00520
00521
00522
00523
00524 StatusCode ApplicationMgr::initialize() {
00525
00526 MsgStream log( m_messageSvc, name() );
00527 StatusCode sc;
00528
00529
00530
00531 if (m_stopOnSignal) {
00532
00533 std::string svcname("Gaudi::Utils::StopSignalHandler");
00534 sc = svcManager()->addService(svcname);
00535 if ( sc.isFailure() ) {
00536 log << MSG::INFO << "Cannot instantiate " << svcname << "signals will be ignored" << endmsg;
00537 }
00538 }
00539
00540 if (m_stalledEventMonitoring) {
00541
00542 std::string svcname("StalledEventMonitor");
00543 sc = svcManager()->addService(svcname);
00544 if ( sc.isFailure() ) {
00545 log << MSG::INFO << "Cannot instantiate " << svcname << "signals will be ignored" << endmsg;
00546 }
00547 }
00548
00549 if( m_state == Gaudi::StateMachine::INITIALIZED ) {
00550 log << MSG::INFO << "Already Initialized!" << endmsg;
00551 return StatusCode::SUCCESS;
00552 }
00553 else if( m_state != Gaudi::StateMachine::CONFIGURED ) {
00554 log << MSG::FATAL
00555 << "initialize: Invalid state \"" << m_state << "\"" << endmsg;
00556 return StatusCode::FAILURE;
00557 }
00558 m_targetState = Gaudi::StateMachine::INITIALIZED;
00559
00560
00561
00562
00563 sc = svcManager()->initialize();
00564 if( !sc.isSuccess() ) return sc;
00565
00566
00567
00568
00569 log << MSG::INFO << "Application Manager Initialized successfully" << endmsg;
00570 m_state = m_targetState;
00571
00572 return sc;
00573 }
00574
00575
00576
00577
00578 StatusCode ApplicationMgr::start() {
00579
00580 MsgStream log( m_messageSvc, name() );
00581 StatusCode sc;
00582
00583 if( m_state == Gaudi::StateMachine::RUNNING ) {
00584 log << MSG::INFO << "Already Initialized!" << endmsg;
00585 return StatusCode::SUCCESS;
00586 }
00587 else if( m_state != Gaudi::StateMachine::INITIALIZED ) {
00588 log << MSG::FATAL
00589 << "start: Invalid state \"" << m_state << "\"" << endmsg;
00590 return StatusCode::FAILURE;
00591 }
00592 m_targetState = Gaudi::StateMachine::RUNNING;
00593
00594
00595
00596
00597 sc = svcManager()->start();
00598 if( !sc.isSuccess() ) return sc;
00599
00600
00601
00602
00603 log << MSG::INFO << "Application Manager Started successfully" << endmsg;
00604 m_state = m_targetState;
00605
00606 return sc;
00607 }
00608
00609
00610
00611
00612 StatusCode ApplicationMgr::nextEvent(int maxevt) {
00613 if( m_state != Gaudi::StateMachine::RUNNING ) {
00614 MsgStream log( m_messageSvc, name() );
00615 log << MSG::FATAL << "nextEvent: Invalid state \"" << m_state << "\""
00616 << endmsg;
00617 return StatusCode::FAILURE;
00618 }
00619 if (!m_processingMgr.isValid()) {
00620 MsgStream log( m_messageSvc, name() );
00621 log << MSG::FATAL << "No event processing manager specified. Check option:"
00622 << s_eventloop << endmsg;
00623 return StatusCode::FAILURE;
00624 }
00625 return m_processingMgr->nextEvent(maxevt);
00626 }
00627
00628
00629
00630
00631 StatusCode ApplicationMgr::stop() {
00632
00633 MsgStream log( m_messageSvc, name() );
00634 StatusCode sc;
00635
00636 if( m_state == Gaudi::StateMachine::INITIALIZED ) {
00637 log << MSG::INFO << "Already Initialized!" << endmsg;
00638 return StatusCode::SUCCESS;
00639 }
00640 else if( m_state != Gaudi::StateMachine::RUNNING ) {
00641 log << MSG::FATAL
00642 << "stop: Invalid state \"" << m_state << "\"" << endmsg;
00643 return StatusCode::FAILURE;
00644 }
00645 m_targetState = Gaudi::StateMachine::INITIALIZED;
00646
00647
00648 sc = algManager()->stop();
00649 if( !sc.isSuccess() ) return sc;
00650
00651
00652
00653
00654 sc = svcManager()->stop();
00655 if( !sc.isSuccess() ) return sc;
00656
00657
00658
00659
00660 log << MSG::INFO << "Application Manager Stopped successfully" << endmsg;
00661 m_state = m_targetState;
00662
00663 return sc;
00664 }
00665
00666
00667
00668
00669 StatusCode ApplicationMgr::finalize() {
00670 MsgStream log( m_messageSvc, name() );
00671 if( m_state == Gaudi::StateMachine::CONFIGURED ) {
00672 log << MSG::INFO << "Already Finalized" << endmsg;
00673 return StatusCode::SUCCESS;
00674 }
00675 else if( m_state != Gaudi::StateMachine::INITIALIZED ) {
00676 log << MSG::FATAL << "finalize: Invalid state \"" << m_state << "\""
00677 << endmsg;
00678 return StatusCode::FAILURE;
00679 }
00680 m_targetState = Gaudi::StateMachine::CONFIGURED;
00681
00682
00683 m_svcLocator->service<IProperty>("MessageSvc")->setProperty(BooleanProperty("enableSuppression", false)).ignore();
00684
00685
00686 StatusCode sc = algManager()->finalize();
00687 if (sc.isFailure()) {
00688 log << MSG::WARNING << "Failed to finalize an algorithm." << endmsg;
00689 m_returnCode = Gaudi::ReturnCode::FinalizationFailure;
00690 }
00691
00692
00693 sc = svcManager()->finalize();
00694 if (sc.isFailure()) {
00695 log << MSG::WARNING << "Failed to finalize a service." << endmsg;
00696 m_returnCode = Gaudi::ReturnCode::FinalizationFailure;
00697 }
00698
00699
00700
00701
00702 if (m_codeCheck) {
00703 StatusCode::disableChecking();
00704 }
00705
00706 if (sc.isSuccess()) {
00707 log << MSG::INFO << "Application Manager Finalized successfully" << endmsg;
00708 } else {
00709 log << MSG::ERROR << "Application Manager failed to finalize" << endmsg;
00710 }
00711
00712 m_state = m_targetState;
00713 return sc;
00714 }
00715
00716
00717
00718
00719 StatusCode ApplicationMgr::terminate() {
00720 MsgStream log( m_messageSvc, name() );
00721
00722 if( m_state == Gaudi::StateMachine::OFFLINE ) {
00723 log << MSG::INFO << "Already Offline" << endmsg;
00724 return StatusCode::SUCCESS;
00725 }
00726 else if( m_state != Gaudi::StateMachine::CONFIGURED ) {
00727 log << MSG::FATAL << "terminate: Invalid state \"" << m_state << "\""
00728 << endmsg;
00729 return StatusCode::FAILURE;
00730 }
00731
00732 m_targetState = Gaudi::StateMachine::OFFLINE;
00733
00734 if (m_returnCode.value() == Gaudi::ReturnCode::Success) {
00735 log << MSG::INFO << "Application Manager Terminated successfully" << endmsg;
00736 } else {
00737 log << MSG::ERROR << "Application Manager Terminated with error code " << m_returnCode.value() << endmsg;
00738 }
00739
00740 {
00741 SmartIF<IProperty> prop(m_messageSvc);
00742 if (prop.isValid()) {
00743 prop->setProperty(BooleanProperty("AuditFinalize", false)).ignore();
00744 }
00745 }
00746 {
00747 SmartIF<IProperty> prop(m_jobOptionsSvc);
00748 if (prop.isValid()) {
00749 prop->setProperty(BooleanProperty("AuditFinalize", false)).ignore();
00750 }
00751 }
00752
00753
00754 SmartIF<IService> svc(m_messageSvc);
00755 if ( !svc.isValid() ) {
00756 log << MSG::ERROR << "Could not get the IService interface of the MessageSvc" << endmsg;
00757 } else {
00758 svc->sysFinalize().ignore();
00759 }
00760
00761
00762 svc = m_jobOptionsSvc;
00763 if ( !svc.isValid() ) {
00764 log << MSG::ERROR << "Could not get the IService interface of the JobOptionsSvc" << endmsg;
00765 } else {
00766 svc->sysFinalize().ignore();
00767 }
00768
00769 m_state = m_targetState;
00770 return StatusCode::SUCCESS;
00771 }
00772
00773
00774
00775
00776 StatusCode ApplicationMgr::GoToState(Gaudi::StateMachine::State state, bool ignoreFailures) {
00777 StatusCode sc = StatusCode(StatusCode::SUCCESS,true);
00778
00779 switch (state) {
00780
00781 case Gaudi::StateMachine::OFFLINE:
00782 switch (m_state) {
00783 case Gaudi::StateMachine::OFFLINE : return StatusCode::SUCCESS; break;
00784 case Gaudi::StateMachine::CONFIGURED : return terminate(); break;
00785 default:
00786 sc = GoToState(Gaudi::StateMachine::CONFIGURED);
00787 if (sc.isSuccess()) {
00788 return terminate();
00789 } break;
00790 } break;
00791
00792 case Gaudi::StateMachine::CONFIGURED:
00793 switch (m_state) {
00794 case Gaudi::StateMachine::CONFIGURED : return StatusCode::SUCCESS; break;
00795 case Gaudi::StateMachine::OFFLINE : return configure(); break;
00796 case Gaudi::StateMachine::INITIALIZED : return finalize(); break;
00797 default:
00798 sc = GoToState(Gaudi::StateMachine::INITIALIZED);
00799 if (sc.isSuccess()) {
00800 return finalize();
00801 } break;
00802 } break;
00803
00804 case Gaudi::StateMachine::INITIALIZED:
00805 switch (m_state) {
00806 case Gaudi::StateMachine::INITIALIZED : return StatusCode::SUCCESS; break;
00807 case Gaudi::StateMachine::CONFIGURED : return initialize(); break;
00808 case Gaudi::StateMachine::RUNNING : return stop(); break;
00809 default:
00810 sc = GoToState(Gaudi::StateMachine::CONFIGURED);
00811 if (sc.isSuccess()) {
00812 return initialize();
00813 } break;
00814 } break;
00815
00816 case Gaudi::StateMachine::RUNNING:
00817 switch (m_state) {
00818 case Gaudi::StateMachine::RUNNING : return StatusCode::SUCCESS; break;
00819 case Gaudi::StateMachine::INITIALIZED : return start(); break;
00820 default:
00821 sc = GoToState(Gaudi::StateMachine::INITIALIZED);
00822 if (sc.isSuccess()) {
00823 return start();
00824 } break;
00825 } break;
00826
00827 }
00828
00829
00830
00831 if (ignoreFailures){
00832
00833 m_state = state;
00834 return StatusCode::SUCCESS;
00835 }
00836
00837 return sc;
00838 }
00839
00840
00841
00842
00843 StatusCode ApplicationMgr::run() {
00844 StatusCode sc = StatusCode::SUCCESS;
00845
00846 sc = GoToState(Gaudi::StateMachine::RUNNING);
00847 if ( sc.isSuccess() ) {
00848 MsgStream log(m_messageSvc, name());
00849 if ( m_runable != 0 ) {
00850 sc = m_runable->run();
00851 if ( !sc.isSuccess() ) {
00852 log << MSG::FATAL << "Application execution failed. Ending the job."
00853 << endmsg;
00854 }
00855 } else {
00856 log << MSG::FATAL << "Application has no runable object. Check option:"
00857 << s_runable << endmsg;
00858 }
00859 }
00860 if (sc.isSuccess()) {
00861 sc = GoToState(Gaudi::StateMachine::OFFLINE);
00862 }
00863
00864 if (sc.isFailure()) {
00865 GoToState(Gaudi::StateMachine::OFFLINE,true).ignore();
00866 }
00867 return sc;
00868 }
00869
00870
00871
00872
00873 StatusCode ApplicationMgr::executeEvent(void* par) {
00874 MsgStream log( m_messageSvc, name() );
00875 if( m_state == Gaudi::StateMachine::RUNNING ) {
00876 if ( m_processingMgr.isValid() ) {
00877 return m_processingMgr->executeEvent(par);
00878 }
00879 }
00880 log << MSG::FATAL << "executeEvent: Invalid state \"" << FSMState() << "\""
00881 <<endmsg;
00882 return StatusCode::FAILURE;
00883 }
00884
00885
00886
00887
00888 StatusCode ApplicationMgr::executeRun(int evtmax) {
00889 MsgStream log( m_messageSvc, name() );
00890 if( m_state == Gaudi::StateMachine::RUNNING ) {
00891 if ( m_processingMgr.isValid() ) {
00892 return m_processingMgr->executeRun(evtmax);
00893 }
00894 log << MSG::WARNING << "No EventLoop Manager specified " << endmsg;
00895 return StatusCode::SUCCESS;
00896 }
00897 log << MSG::FATAL << "executeRun: Invalid state \"" << FSMState() << "\""
00898 << endmsg;
00899 return StatusCode::FAILURE;
00900 }
00901
00902
00903
00904
00905 StatusCode ApplicationMgr::stopRun() {
00906 MsgStream log( m_messageSvc, name() );
00907 if( m_state == Gaudi::StateMachine::RUNNING ) {
00908 if ( m_processingMgr.isValid() ) {
00909 return m_processingMgr->stopRun();
00910 }
00911 log << MSG::WARNING << "No EventLoop Manager specified " << endmsg;
00912 return StatusCode::SUCCESS;
00913 }
00914 log << MSG::FATAL << "stopRun: Invalid state \"" << FSMState() << "\""
00915 << endmsg;
00916 return StatusCode::FAILURE;
00917 }
00918
00919 const std::string& ApplicationMgr::name() const {
00920 return m_name;
00921 }
00922
00923
00924 Gaudi::StateMachine::State ApplicationMgr::FSMState( ) const {
00925 return m_state;
00926 }
00927
00928 Gaudi::StateMachine::State ApplicationMgr::targetFSMState( ) const {
00929 return m_targetState;
00930 }
00931
00932
00933
00934
00935
00936 StatusCode ApplicationMgr::reinitialize() {
00937 StatusCode retval = StatusCode::SUCCESS;
00938 StatusCode sc;
00939 if ( m_state < Gaudi::StateMachine::INITIALIZED ) {
00940 throw GaudiException("Cannot reinitialize application if not INITIALIZED or RUNNING",
00941 "ApplicationMgr::reinitialize", StatusCode::FAILURE);
00942 }
00943 if ( m_state == Gaudi::StateMachine::RUNNING ) {
00944 retval = GoToState(Gaudi::StateMachine::INITIALIZED);
00945 }
00946 sc = svcManager()->reinitialize();
00947 if (sc.isFailure()) retval = sc;
00948 sc = algManager()->reinitialize();
00949 if (sc.isFailure()) retval = sc;
00950 return retval;
00951 }
00952
00953
00954
00955
00956 StatusCode ApplicationMgr::restart() {
00957 StatusCode retval = StatusCode::SUCCESS;
00958 StatusCode sc;
00959 if ( m_state != Gaudi::StateMachine::RUNNING ) {
00960 throw GaudiException("Cannot restart application if not RUNNING",
00961 "ApplicationMgr::restart", StatusCode::FAILURE);
00962 }
00963 sc = svcManager()->restart();
00964 if (sc.isFailure()) retval = sc;
00965 sc = algManager()->restart();
00966 if (sc.isFailure()) retval = sc;
00967 return retval;
00968 }
00969
00970
00971
00972
00973 void ApplicationMgr::SIGoHandler( Property& ) {
00974
00975 MsgStream log (m_messageSvc, name());
00976 StatusCode sc;
00977
00978
00979 sc = reinitialize();
00980
00981 executeRun(m_evtMax);
00982
00983 return;
00984 }
00985
00986
00987
00988
00989 void ApplicationMgr::SIExitHandler( Property& ) {
00990 StatusCode status;
00991 status = finalize();
00992 status = terminate();
00993 ::exit( 0 );
00994 }
00995
00996
00997
00998
00999 void ApplicationMgr::evtLoopPropertyHandler( Property& p ) {
01000 if ( m_processingMgr.isValid() ) {
01001 SmartIF<IProperty> props(m_processingMgr);
01002 if ( props.isValid() ) {
01003 props->setProperty( p ).ignore();
01004 }
01005 }
01006 }
01007
01008
01009
01010
01011 void ApplicationMgr::createSvcNameListHandler( Property& ) {
01012 if ( !(decodeCreateSvcNameList()).isSuccess() ) {
01013 throw GaudiException("Failed to create ext services",
01014 "MinimalEventLoopMgr::createSvcNameListHandler",
01015 StatusCode::FAILURE);
01016 }
01017 }
01018
01019
01020
01021 StatusCode ApplicationMgr::decodeCreateSvcNameList() {
01022 StatusCode result = StatusCode::SUCCESS;
01023 const std::vector<std::string>& theNames = m_createSvcNameList.value( );
01024 VectorName::const_iterator it(theNames.begin());
01025 VectorName::const_iterator et(theNames.end());
01026 while(result.isSuccess() && it != et) {
01027 Gaudi::Utils::TypeNameString item(*it++);
01028 if( (result = svcManager()->addService(item, 10) ).isFailure()) {
01029 MsgStream log( m_messageSvc, m_name );
01030 log << MSG::ERROR << "decodeCreateSvcNameList: Cannot create service "
01031 << item.type() << "/" << item.name() << endmsg;
01032 } else {
01033 ON_DEBUG {
01034 MsgStream log( m_messageSvc, m_name );
01035 log << MSG::DEBUG << "decodeCreateSvcNameList: Created service "
01036 << item.type() << "/" << item.name() << endmsg;
01037 }
01038 }
01039 }
01040 return result;
01041 }
01042
01043
01044
01045
01046 void ApplicationMgr::extSvcNameListHandler( Property& ) {
01047 if ( !(decodeExtSvcNameList( )).isSuccess() ) {
01048 throw GaudiException("Failed to declare ext services",
01049 "MinimalEventLoopMgr::extSvcNameListHandler",
01050 StatusCode::FAILURE);
01051 }
01052 }
01053
01054
01055
01056
01057 StatusCode ApplicationMgr::decodeExtSvcNameList( ) {
01058 StatusCode result = StatusCode::SUCCESS;
01059
01060 std::vector<std::string> theNames = m_extSvcNameList.value( );
01061
01062 VectorName::const_iterator it(theNames.begin());
01063 VectorName::const_iterator et(theNames.end());
01064 while(result.isSuccess() && it != et) {
01065 Gaudi::Utils::TypeNameString item(*it++);
01066 if (m_extSvcCreates == true) {
01067 if ( (result = svcManager()->addService(item, 10)).isFailure()) {
01068 MsgStream log( m_messageSvc, m_name );
01069 log << MSG::ERROR << "decodeExtSvcNameList: Cannot create service "
01070 << item.type() << "/" << item.name() << endmsg;
01071 }
01072 } else {
01073 if( ( result = svcManager()->declareSvcType(item.name(),
01074 item.type()) ).isFailure()) {
01075 MsgStream log( m_messageSvc, m_name );
01076 log << MSG::ERROR << "decodeExtSvcNameList: Cannot declare service "
01077 << item.type() << "/" << item.name() << endmsg;
01078 }
01079 }
01080 }
01081 return result;
01082 }
01083
01084
01085
01086
01087 void ApplicationMgr::multiThreadSvcNameListHandler( Property& ) {
01088 if ( !(decodeMultiThreadSvcNameList( )).isSuccess() ) {
01089 throw GaudiException("Failed to create copies of mt services",
01090 "MinimalEventLoopMgr::multiThreadSvcNameListHandler",
01091 StatusCode::FAILURE);
01092 }
01093
01094 }
01095
01096
01097
01098
01099 StatusCode ApplicationMgr::decodeMultiThreadSvcNameList( ) {
01100 StatusCode result = StatusCode::SUCCESS;
01101 const std::vector<std::string>& theNames = m_multiThreadSvcNameList.value( );
01102 for(int iCopy=0; iCopy<m_noOfEvtThreads; ++iCopy) {
01103 for (VectorName::const_iterator it = theNames.begin();
01104 it != theNames.end();
01105 ++it) {
01106 Gaudi::Utils::TypeNameString item(*it);
01107 result = addMultiSvc(item, 10);
01108
01109 if( result.isFailure() ) {
01110 MsgStream log( m_messageSvc, m_name );
01111 log << MSG::ERROR
01112 << "decodeMultiThreadSvcNameList: Cannot create service "
01113 << item.type() << "/" << item.name() << endmsg;
01114 } else {
01115 ON_VERBOSE {
01116 MsgStream log( m_messageSvc, m_name );
01117 log << MSG::VERBOSE
01118 << "decodeMultiThreadSvcNameList: created service "
01119 << item.type() << "/" << item.name() << endmsg;
01120 }
01121 }
01122 }
01123 }
01124 return result;
01125 }
01126
01127
01128
01129 StatusCode ApplicationMgr::declareMultiSvcType(const std::string& name,
01130 const std::string& type) {
01131 StatusCode result = StatusCode::SUCCESS;
01132 MsgStream log( m_messageSvc, m_name );
01133 if (0 == m_noOfEvtThreads) {
01134 result = svcManager()->declareSvcType(name, type);
01135 if( result.isFailure() ) {
01136 log << MSG::ERROR << "declareMultiSvcType: Cannot declare service "
01137 << type << "/" << name << endmsg;
01138 } else {
01139 ON_VERBOSE
01140 log << MSG::VERBOSE << "declareMultiSvcType: declared service "
01141 << type << "/" << name << endmsg;
01142 }
01143 } else {
01144 for(int iCopy=0; iCopy<m_noOfEvtThreads; ++iCopy) {
01145 std::string thrName(name + getGaudiThreadIDfromID(iCopy));
01146 result = svcManager()->declareSvcType(thrName, type);
01147 if( result.isFailure() ) {
01148 log << MSG::ERROR << "declareMultiSvcType: Cannot declare service "
01149 << type << "/" << thrName << endmsg;
01150 } else {
01151 ON_VERBOSE
01152 log << MSG::VERBOSE << "declareMultiSvcType: declared service "
01153 << type << "/" << thrName << endmsg;
01154 }
01155 }
01156 }
01157 return result;
01158 }
01159
01160
01161
01162 StatusCode ApplicationMgr::addMultiSvc(const Gaudi::Utils::TypeNameString &typeName,
01163 int prio) {
01164 using Gaudi::Utils::TypeNameString;
01165 StatusCode result = StatusCode::SUCCESS;
01166 MsgStream log( m_messageSvc, m_name );
01167 if (0 == m_noOfEvtThreads) {
01168 result = svcManager()->addService(typeName, prio);
01169
01170 if( result.isFailure() ) {
01171 log << MSG::ERROR << "addMultiSvc: Cannot add service "
01172 << typeName.type() << "/" << typeName.name() << endmsg;
01173 } else {
01174 ON_VERBOSE
01175 log << MSG::VERBOSE << "addMultiSvc: added service "
01176 << typeName.type() << "/" << typeName.name() << endmsg;
01177 }
01178 } else {
01179 for(int iCopy=0; iCopy<m_noOfEvtThreads; ++iCopy) {
01180 const std::string &type = typeName.type();
01181 std::string thrName(typeName.name() + getGaudiThreadIDfromID(iCopy));
01182 result = svcManager()->addService(TypeNameString(thrName, type), prio);
01183 if( result.isFailure() ) {
01184 log << MSG::ERROR << "addMultiSvc: Cannot add service "
01185 << type << "/" << thrName << endmsg;
01186 } else {
01187 ON_VERBOSE
01188 log << MSG::VERBOSE << "addMultiSvc: added service "
01189 << type << "/" << thrName << endmsg;
01190 }
01191 }
01192 }
01193 return result;
01194 }
01195
01196
01197
01198
01199 void ApplicationMgr::dllNameListHandler( Property& ) {
01200 if ( !(decodeDllNameList( )).isSuccess() ) {
01201 throw GaudiException("Failed to load DLLs.",
01202 "MinimalEventLoopMgr::dllNameListHandler",
01203 StatusCode::FAILURE);
01204 }
01205 }
01206
01207
01208
01209
01210 StatusCode ApplicationMgr::decodeDllNameList() {
01211
01212 MsgStream log( m_messageSvc, m_name );
01213 StatusCode result = StatusCode::SUCCESS;
01214
01215
01216
01217 std::vector<std::string> newList;
01218 std::map<std::string,unsigned int> dllInList, duplicateList;
01219 {for ( std::vector<std::string>::const_iterator it = m_dllNameList.value().begin();
01220 it != m_dllNameList.value().end(); ++it ) {
01221 if ( 0 == dllInList[*it] ) {
01222 newList.push_back(*it);
01223 } else { ++duplicateList[*it]; }
01224 ++dllInList[*it];
01225 }}
01226
01227
01228
01229 ON_DEBUG if ( !duplicateList.empty() ) {
01230 log << MSG::DEBUG << "Removed duplicate entries for modules : ";
01231 for ( std::map<std::string,unsigned int>::const_iterator it = duplicateList.begin();
01232 it != duplicateList.end(); ++it ) {
01233 log << it->first << "(" << 1+it->second << ")";
01234 if ( it != --duplicateList.end() ) log << ", ";
01235 }
01236 log << endmsg;
01237 }
01238
01239
01240 const std::vector<std::string>& theNames = newList;
01241
01242
01243 ON_DEBUG log << MSG::DEBUG << "Loading declared DLL's" << endmsg;
01244
01245 std::vector<std::string> successNames, failNames;
01246 std::vector<std::string>::const_iterator it;
01247
01248 for (it = theNames.begin(); it != theNames.end(); it++) {
01249 if (std::find (m_okDlls.rbegin(), m_okDlls.rend(), *it) == m_okDlls.rend()){
01250
01251 StatusCode status = m_classManager->loadModule( (*it) );
01252 if( status.isFailure() ) {
01253 failNames.push_back(*it);
01254 result = StatusCode::FAILURE;
01255 }
01256 else {
01257 successNames.push_back(*it);
01258 }
01259 }
01260 }
01261
01262
01263 if ( !successNames.empty() ) {
01264 log << MSG::INFO << "Successfully loaded modules : ";
01265 for (it = successNames.begin(); it != successNames.end(); it++) {
01266 log<< (*it);
01267 if( (it+1) != successNames.end()) log << ", ";
01268
01269 m_okDlls.push_back( *it );
01270 }
01271 log << endmsg;
01272 }
01273
01274 if ( result == StatusCode::FAILURE ) {
01275 log << MSG::WARNING << "Failed to load modules: ";
01276 for (it = failNames.begin(); it != failNames.end(); it++) {
01277 log<< (*it);
01278 if( (it+1) != failNames.end()) log << ", ";
01279 }
01280 log << endmsg;
01281 }
01282 return result;
01283 }
01284
01285
01286
01287
01288 void ApplicationMgr::reflexDebugPropertyHandler( Property& )
01289 {
01290
01291 MsgStream log (m_messageSvc, name());
01292 log << MSG::INFO
01293 << "Updating ROOT::Reflex::PluginService::SetDebug(level) to level="
01294 << (int)m_reflexDebugLevel
01295 << endmsg;
01296 ROOT::Reflex::PluginService::SetDebug(m_reflexDebugLevel);
01297 }
01298
01299
01300
01301
01302 void ApplicationMgr::initLoopCheckHndlr(Property&) {
01303 svcManager()->setLoopCheckEnabled(m_loopCheck);
01304 }