00001 #include "otsdaq-core/CoreSupervisors/CoreSupervisorBase.h"
00002
00003
00004
00005
00006
00007
00008 #include <iostream>
00009
00010 using namespace ots;
00011
00012
00013
00014
00015 const std::string CoreSupervisorBase::WORK_LOOP_DONE = "Done";
00016 const std::string CoreSupervisorBase::WORK_LOOP_WORKING = "Working";
00017
00018
00019 CoreSupervisorBase::CoreSupervisorBase(xdaq::ApplicationStub * s)
00020 throw (xdaq::exception::Exception)
00021 : xdaq::Application (s)
00022 , SOAPMessenger (this)
00023 , stateMachineWorkLoopManager_ (toolbox::task::bind(this, &CoreSupervisorBase::stateMachineThread, "StateMachine"))
00024 , stateMachineSemaphore_ (toolbox::BSem::FULL)
00025 , theConfigurationManager_ (new ConfigurationManager)
00026 , XDAQContextConfigurationName_ (theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getConfigurationName())
00027 , supervisorConfigurationPath_ ("INITIALIZED INSIDE THE CONTRUCTOR BECAUSE IT NEEDS supervisorContextUID_ and supervisorApplicationUID_")
00028 , supervisorContextUID_ ("INITIALIZED INSIDE THE CONTRUCTOR TO LAUNCH AN EXCEPTION")
00029 , supervisorApplicationUID_ ("INITIALIZED INSIDE THE CONTRUCTOR TO LAUNCH AN EXCEPTION")
00030 , supervisorClass_ (getApplicationDescriptor()->getClassName())
00031 , supervisorClassNoNamespace_ (supervisorClass_.substr(supervisorClass_.find_last_of(":")+1, supervisorClass_.length()-supervisorClass_.find_last_of(":")))
00032 , theRemoteWebUsers_ (this)
00033 , LOCK_REQUIRED_ (false)
00034 , USER_PERMISSIONS_THRESHOLD_ (1)
00035 {
00036 INIT_MF("CoreSupervisorBase");
00037
00038 __COUT__ << "Begin!" << std::endl;
00039
00040 xgi::bind (this, &CoreSupervisorBase::DefaultWrapper, "Default" );
00041 xgi::bind (this, &CoreSupervisorBase::requestWrapper, "Request");
00042 xgi::bind (this, &CoreSupervisorBase::stateMachineXgiHandler, "StateMachineXgiHandler");
00043
00044 xoap::bind(this, &CoreSupervisorBase::stateMachineStateRequest, "StateMachineStateRequest", XDAQ_NS_URI );
00045 xoap::bind(this, &CoreSupervisorBase::stateMachineErrorMessageRequest, "StateMachineErrorMessageRequest", XDAQ_NS_URI );
00046
00047 xoap::bind(this, &CoreSupervisorBase::workLoopStatusRequestWrapper, "WorkLoopStatusRequest", XDAQ_NS_URI );
00048
00049 try
00050 {
00051 supervisorContextUID_ = theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getContextUID(
00052 getApplicationContext()->getContextDescriptor()->getURL());
00053 }
00054 catch(...)
00055 {
00056 __COUT_ERR__ << "XDAQ Supervisor could not access it's configuration through the Configuration Context Group." <<
00057 " The XDAQContextConfigurationName = " << XDAQContextConfigurationName_ <<
00058 ". The supervisorApplicationUID = " << supervisorApplicationUID_ << std::endl;
00059 throw;
00060 }
00061 try
00062 {
00063 supervisorApplicationUID_ = theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getApplicationUID
00064 (
00065 getApplicationContext()->getContextDescriptor()->getURL(),
00066 getApplicationDescriptor()->getLocalId()
00067 );
00068 }
00069 catch(...)
00070 {
00071 __COUT_ERR__ << "XDAQ Supervisor could not access it's configuration through the Configuration Application Group."
00072 << " The supervisorApplicationUID = " << supervisorApplicationUID_ << std::endl;
00073 throw;
00074 }
00075 supervisorConfigurationPath_ = "/" + supervisorContextUID_ + "/LinkToApplicationConfiguration/" + supervisorApplicationUID_ + "/LinkToSupervisorConfiguration";
00076
00077 setStateMachineName(supervisorApplicationUID_);
00078
00079 allSupervisorInfo_.init(getApplicationContext());
00080 __COUT__ << "Name = " << allSupervisorInfo_.getSupervisorInfo(this).getName();
00081
00082
00083 __COUT__ << "Initializing..." << std::endl;
00084
00085 setSupervisorPropertyDefaults();
00086
00087
00088 {
00089
00090 __COUT__ << "Looking for " <<
00091 supervisorContextUID_ << "/" << supervisorApplicationUID_ <<
00092 " supervisor security settings..." << __E__;
00093
00094 ConfigurationTree appNode = theConfigurationManager_->getSupervisorNode(
00095 supervisorContextUID_, supervisorApplicationUID_);
00096 try
00097 {
00098 auto children = appNode.getNode("LinkToPropertyConfiguration").getChildren();
00099
00100 for(auto& child:children)
00101 {
00102 if(child.second.getNode("Status").getValue<bool>() == false) continue;
00103
00104 auto propertyName = child.second.getNode("PropertyName");
00105
00106 if(propertyName.getValue() ==
00107 supervisorProperties_.fieldRequireLock)
00108 {
00109 LOCK_REQUIRED_ = child.second.getNode("PropertyValue").getValue<bool>();
00110 __COUTV__(LOCK_REQUIRED_);
00111 }
00112 else if(propertyName.getValue() ==
00113 supervisorProperties_.fieldUserPermissionsThreshold)
00114 {
00115 USER_PERMISSIONS_THRESHOLD_ = child.second.getNode("PropertyValue").getValue<uint8_t>();
00116 __COUTV__(USER_PERMISSIONS_THRESHOLD_);
00117 }
00118 }
00119 }
00120 catch(...)
00121 {
00122 __COUT__ << "No supervisor security settings found, going with defaults." << __E__;
00123 }
00124 }
00125 }
00126
00127
00128 CoreSupervisorBase::~CoreSupervisorBase(void)
00129 {
00130 destroy();
00131 }
00132
00133
00134
00135
00136 void CoreSupervisorBase::setSupervisorPropertyDefaults(void)
00137 {
00138
00139
00140 __COUT__ << "Using base class property defaults..." << std::endl;
00141
00142 LOCK_REQUIRED_ = false;
00143 USER_PERMISSIONS_THRESHOLD_ = 1;
00144 USER_GROUPS_ALLOWED_ = "";
00145 USER_GROUPS_DISALLOWED_ = "";
00146
00147 __COUTV__(LOCK_REQUIRED_);
00148 __COUTV__(USER_PERMISSIONS_THRESHOLD_);
00149 __COUTV__(USER_GROUPS_ALLOWED_);
00150 __COUTV__(USER_GROUPS_DISALLOWED_);
00151 }
00152
00153
00154 void CoreSupervisorBase::destroy(void)
00155 {
00156 __COUT__ << "Destroying..." << std::endl;
00157 for(auto& it: theStateMachineImplementation_)
00158 delete it;
00159 theStateMachineImplementation_.clear();
00160 }
00161
00162
00163
00164 void CoreSupervisorBase::DefaultWrapper(xgi::Input * in, xgi::Output * out )
00165 throw (xgi::exception::Exception)
00166 {
00167 return Default(in,out);
00168 }
00169
00170
00171 void CoreSupervisorBase::Default(xgi::Input * in, xgi::Output * out )
00172 throw (xgi::exception::Exception)
00173 {
00174 __COUT__<< "Supervisor class " << supervisorClass_ << std::endl;
00175
00176 std::stringstream pagess;
00177 pagess << "/WebPath/html/" <<
00178 supervisorClassNoNamespace_ << ".html?urn=" <<
00179 this->getApplicationDescriptor()->getLocalId();
00180
00181 __COUT__<< "Default page = " << pagess.str() << std::endl;
00182
00183 *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='" <<
00184 pagess.str() <<
00185 "'></frameset></html>";
00186 }
00187
00188
00189
00190 void CoreSupervisorBase::requestWrapper(xgi::Input * in, xgi::Output * out )
00191 throw (xgi::exception::Exception)
00192 {
00193 return request(in,out);
00194 }
00195
00196
00197 void CoreSupervisorBase::request(xgi::Input * in, xgi::Output * out )
00198 throw (xgi::exception::Exception)
00199 {
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 }
00216
00217
00218 void CoreSupervisorBase::stateMachineXgiHandler(xgi::Input * in, xgi::Output * out )
00219 throw (xgi::exception::Exception)
00220 {}
00221
00222
00223 void CoreSupervisorBase::stateMachineResultXgiHandler(xgi::Input* in, xgi::Output* out )
00224 throw (xgi::exception::Exception)
00225 {}
00226
00227
00228 xoap::MessageReference CoreSupervisorBase::stateMachineXoapHandler(xoap::MessageReference message )
00229 throw (xoap::exception::Exception)
00230 {
00231 __COUT__<< "Soap Handler!" << std::endl;
00232 stateMachineWorkLoopManager_.removeProcessedRequests();
00233 stateMachineWorkLoopManager_.processRequest(message);
00234 __COUT__<< "Done - Soap Handler!" << std::endl;
00235 return message;
00236 }
00237
00238
00239 xoap::MessageReference CoreSupervisorBase::stateMachineResultXoapHandler(xoap::MessageReference message )
00240 throw (xoap::exception::Exception)
00241 {
00242 __COUT__<< "Soap Handler!" << std::endl;
00243
00244
00245 __COUT__<< "Done - Soap Handler!" << std::endl;
00246 return message;
00247 }
00248
00249
00250
00251 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequestWrapper(xoap::MessageReference message)
00252 throw (xoap::exception::Exception)
00253 {
00254
00255 return workLoopStatusRequest(message);
00256 }
00257
00258
00259 xoap::MessageReference CoreSupervisorBase::workLoopStatusRequest(xoap::MessageReference message)
00260 throw (xoap::exception::Exception)
00261 {
00262
00263 return SOAPUtilities::makeSOAPMessageReference(CoreSupervisorBase::WORK_LOOP_DONE);
00264 }
00265
00266
00267 bool CoreSupervisorBase::stateMachineThread(toolbox::task::WorkLoop* workLoop)
00268 {
00269 stateMachineSemaphore_.take();
00270 __COUT__<< "Re-sending message..." << SOAPUtilities::translate(stateMachineWorkLoopManager_.getMessage(workLoop)).getCommand() << std::endl;
00271 std::string reply = send(this->getApplicationDescriptor(),stateMachineWorkLoopManager_.getMessage(workLoop));
00272 stateMachineWorkLoopManager_.report(workLoop, reply, 100, true);
00273 __COUT__<< "Done with message" << std::endl;
00274 stateMachineSemaphore_.give();
00275 return false;
00276
00277 }
00278
00279
00280 xoap::MessageReference CoreSupervisorBase::stateMachineStateRequest(xoap::MessageReference message)
00281 throw (xoap::exception::Exception)
00282 {
00283 __COUT__<< "theStateMachine_.getCurrentStateName() = " << theStateMachine_.getCurrentStateName() << std::endl;
00284 return SOAPUtilities::makeSOAPMessageReference(theStateMachine_.getCurrentStateName());
00285 }
00286
00287
00288 xoap::MessageReference CoreSupervisorBase::stateMachineErrorMessageRequest(xoap::MessageReference message)
00289 throw (xoap::exception::Exception)
00290 {
00291 __COUT__<< "theStateMachine_.getErrorMessage() = " << theStateMachine_.getErrorMessage() << std::endl;
00292
00293 SOAPParameters retParameters;
00294 retParameters.addParameter("ErrorMessage",theStateMachine_.getErrorMessage());
00295 return SOAPUtilities::makeSOAPMessageReference("stateMachineErrorMessageRequestReply",retParameters);
00296 }
00297
00298
00299 void CoreSupervisorBase::stateInitial(toolbox::fsm::FiniteStateMachine& fsm)
00300 throw (toolbox::fsm::exception::Exception)
00301 {
00302 __COUT__ << "CoreSupervisorBase::stateInitial" << std::endl;
00303 }
00304
00305
00306 void CoreSupervisorBase::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
00307 throw (toolbox::fsm::exception::Exception)
00308 {
00309 __COUT__ << "CoreSupervisorBase::stateHalted" << std::endl;
00310 }
00311
00312
00313 void CoreSupervisorBase::stateRunning(toolbox::fsm::FiniteStateMachine& fsm)
00314 throw (toolbox::fsm::exception::Exception)
00315 {
00316 __COUT__ << "CoreSupervisorBase::stateRunning" << std::endl;
00317 }
00318
00319
00320 void CoreSupervisorBase::stateConfigured(toolbox::fsm::FiniteStateMachine& fsm)
00321 throw (toolbox::fsm::exception::Exception)
00322 {
00323 __COUT__ << "CoreSupervisorBase::stateConfigured" << std::endl;
00324 }
00325
00326
00327 void CoreSupervisorBase::statePaused(toolbox::fsm::FiniteStateMachine& fsm)
00328 throw (toolbox::fsm::exception::Exception)
00329 {
00330 __COUT__ << "CoreSupervisorBase::statePaused" << std::endl;
00331 }
00332
00333
00334 void CoreSupervisorBase::inError (toolbox::fsm::FiniteStateMachine & fsm)
00335 throw (toolbox::fsm::exception::Exception)
00336 {
00337 __COUT__<< "Fsm current state: " << theStateMachine_.getCurrentStateName()<< std::endl;
00338
00339 }
00340
00341
00342 void CoreSupervisorBase::enteringError (toolbox::Event::Reference e)
00343 throw (toolbox::fsm::exception::Exception)
00344 {
00345 __COUT__<< "Fsm current state: " << theStateMachine_.getCurrentStateName()
00346 << "\n\nError Message: " <<
00347 theStateMachine_.getErrorMessage() << std::endl;
00348 toolbox::fsm::FailedEvent& failedEvent = dynamic_cast<toolbox::fsm::FailedEvent&>(*e);
00349 std::ostringstream error;
00350 error << "Failure performing transition from "
00351 << failedEvent.getFromState()
00352 << " to "
00353 << failedEvent.getToState()
00354 << " exception: " << failedEvent.getException().what();
00355 __COUT_ERR__<< error.str() << std::endl;
00356
00357
00358 }
00359
00360
00361 void CoreSupervisorBase::transitionConfiguring(toolbox::Event::Reference e)
00362 throw (toolbox::fsm::exception::Exception)
00363 {
00364 __COUT__ << "transitionConfiguring" << std::endl;
00365
00366 std::pair<std::string , ConfigurationGroupKey> theGroup(
00367 SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).
00368 getParameters().getValue("ConfigurationGroupName"),
00369 ConfigurationGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).
00370 getParameters().getValue("ConfigurationGroupKey")));
00371
00372 __COUT__ << "Configuration group name: " << theGroup.first << " key: " <<
00373 theGroup.second << std::endl;
00374
00375 theConfigurationManager_->loadConfigurationGroup(
00376 theGroup.first,
00377 theGroup.second, true);
00378
00379
00380
00381
00382 try
00383 {
00384 for(auto& it: theStateMachineImplementation_)
00385 it->configure();
00386 }
00387 catch(const std::runtime_error& e)
00388 {
00389 __SS__ << "Error was caught while configuring: " << e.what() << std::endl;
00390 __COUT_ERR__ << "\n" << ss.str();
00391 theStateMachine_.setErrorMessage(ss.str());
00392 throw toolbox::fsm::exception::Exception(
00393 "Transition Error" ,
00394 ss.str() ,
00395 "CoreSupervisorBase::transitionConfiguring" ,
00396 __LINE__ ,
00397 __FUNCTION__
00398 );
00399 }
00400
00401 }
00402
00403
00404
00405
00406 void CoreSupervisorBase::transitionHalting(toolbox::Event::Reference e)
00407 throw (toolbox::fsm::exception::Exception)
00408 {
00409 __COUT__ << "transitionHalting" << std::endl;
00410
00411 for(auto& it: theStateMachineImplementation_)
00412 {
00413 try
00414 {
00415 it->halt();
00416 }
00417 catch(const std::runtime_error& e)
00418 {
00419
00420 if(theStateMachine_.getProvenanceStateName() ==
00421 RunControlStateMachine::FAILED_STATE_NAME)
00422 {
00423 __COUT_INFO__ << "Error was caught while halting (but ignoring because previous state was '" <<
00424 RunControlStateMachine::FAILED_STATE_NAME << "'): " << e.what() << std::endl;
00425 }
00426 else
00427 {
00428 __SS__ << "Error was caught while halting: " << e.what() << std::endl;
00429 __COUT_ERR__ << "\n" << ss.str();
00430 theStateMachine_.setErrorMessage(ss.str());
00431 throw toolbox::fsm::exception::Exception(
00432 "Transition Error" ,
00433 ss.str() ,
00434 "CoreSupervisorBase::transitionHalting" ,
00435 __LINE__ ,
00436 __FUNCTION__
00437 );
00438 }
00439 }
00440 }
00441 }
00442
00443
00444 void CoreSupervisorBase::transitionInitializing(toolbox::Event::Reference e)
00445 throw (toolbox::fsm::exception::Exception)
00446 {
00447 __COUT__ << "transitionInitializing" << std::endl;
00448
00449
00450
00451 }
00452
00453
00454 void CoreSupervisorBase::transitionPausing(toolbox::Event::Reference e)
00455 throw (toolbox::fsm::exception::Exception)
00456 {
00457 __COUT__ << "transitionPausing" << std::endl;
00458
00459 try
00460 {
00461 for(auto& it: theStateMachineImplementation_)
00462 it->pause();
00463 }
00464 catch(const std::runtime_error& e)
00465 {
00466 __SS__ << "Error was caught while pausing: " << e.what() << std::endl;
00467 __COUT_ERR__ << "\n" << ss.str();
00468 theStateMachine_.setErrorMessage(ss.str());
00469 throw toolbox::fsm::exception::Exception(
00470 "Transition Error" ,
00471 ss.str() ,
00472 "CoreSupervisorBase::transitionPausing" ,
00473 __LINE__ ,
00474 __FUNCTION__
00475 );
00476 }
00477 }
00478
00479
00480 void CoreSupervisorBase::transitionResuming(toolbox::Event::Reference e)
00481 throw (toolbox::fsm::exception::Exception)
00482 {
00483
00484
00485
00486 __COUT__ << "transitionResuming" << std::endl;
00487
00488 try
00489 {
00490 for(auto& it: theStateMachineImplementation_)
00491 it->resume();
00492 }
00493 catch(const std::runtime_error& e)
00494 {
00495 __SS__ << "Error was caught while resuming: " << e.what() << std::endl;
00496 __COUT_ERR__ << "\n" << ss.str();
00497 theStateMachine_.setErrorMessage(ss.str());
00498 throw toolbox::fsm::exception::Exception(
00499 "Transition Error" ,
00500 ss.str() ,
00501 "CoreSupervisorBase::transitionResuming" ,
00502 __LINE__ ,
00503 __FUNCTION__
00504 );
00505 }
00506 }
00507
00508
00509 void CoreSupervisorBase::transitionStarting(toolbox::Event::Reference e)
00510 throw (toolbox::fsm::exception::Exception)
00511 {
00512
00513
00514
00515 __COUT__ << "transitionStarting" << std::endl;
00516
00517 try
00518 {
00519 for(auto& it: theStateMachineImplementation_)
00520 it->start(SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).getParameters().getValue("RunNumber"));
00521 }
00522 catch(const std::runtime_error& e)
00523 {
00524 __SS__ << "Error was caught while starting: " << e.what() << std::endl;
00525 __COUT_ERR__ << "\n" << ss.str();
00526 theStateMachine_.setErrorMessage(ss.str());
00527 throw toolbox::fsm::exception::Exception(
00528 "Transition Error" ,
00529 ss.str() ,
00530 "CoreSupervisorBase::transitionStarting" ,
00531 __LINE__ ,
00532 __FUNCTION__
00533 );
00534 }
00535 }
00536
00537
00538 void CoreSupervisorBase::transitionStopping(toolbox::Event::Reference e)
00539 throw (toolbox::fsm::exception::Exception)
00540 {
00541 __COUT__ << "transitionStopping" << std::endl;
00542
00543 try
00544 {
00545 for(auto& it: theStateMachineImplementation_)
00546 it->stop();
00547 }
00548 catch(const std::runtime_error& e)
00549 {
00550 __SS__ << "Error was caught while pausing: " << e.what() << std::endl;
00551 __COUT_ERR__ << "\n" << ss.str();
00552 theStateMachine_.setErrorMessage(ss.str());
00553 throw toolbox::fsm::exception::Exception(
00554 "Transition Error" ,
00555 ss.str() ,
00556 "CoreSupervisorBase::transitionStopping" ,
00557 __LINE__ ,
00558 __FUNCTION__
00559 );
00560 }
00561 }