1 #include "otsdaq-core/GatewaySupervisor/GatewaySupervisor.h"
2 #include "otsdaq-core/CgiDataUtilities/CgiDataUtilities.h"
3 #include "otsdaq-core/Macros/CoutMacros.h"
4 #include "otsdaq-core/MessageFacility/MessageFacility.h"
5 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
6 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
7 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
9 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
10 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
11 #include "otsdaq-core/GatewaySupervisor/ARTDAQCommandable.h"
12 #include "otsdaq-core/TablePluginDataFormats/DesktopIconTable.h"
13 #include "otsdaq-core/TablePluginDataFormats/XDAQContextTable.h"
14 #include "otsdaq-core/WorkLoopManager/WorkLoopManager.h"
16 #include "otsdaq-core/NetworkUtilities/TransceiverSocket.h"
18 #include <cgicc/HTMLClasses.h>
19 #include <cgicc/HTMLDoctype.h>
20 #include <cgicc/HTTPCookie.h>
21 #include <cgicc/HTTPHeader.h>
22 #include <xgi/Utils.h>
24 #include <toolbox/fsm/FailedEvent.h>
25 #include <toolbox/task/WorkLoopFactory.h>
26 #include <xdaq/NamespaceURI.h>
27 #include <xoap/Method.h>
36 #define RUN_NUMBER_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/RunNumber/"
37 #define RUN_NUMBER_FILE_NAME "NextRunNumber.txt"
38 #define FSM_LAST_GROUP_ALIAS_PATH \
39 std::string(__ENV__("SERVICE_DATA_PATH")) + "/RunControlData/"
40 #define FSM_LAST_GROUP_ALIAS_FILE_START std::string("FSMLastGroupAlias-")
41 #define FSM_USERS_PREFERENCES_FILETYPE "pref"
44 #define __MF_SUBJECT__ "GatewaySupervisor"
50 : xdaq::Application(s)
56 , theArtdaqCommandable_(this)
57 , stateMachineWorkLoopManager_(toolbox::task::bind(
58 this, &GatewaySupervisor::stateMachineThread, "StateMachine"))
59 , stateMachineSemaphore_(toolbox::BSem::FULL)
60 , infoRequestWorkLoopManager_(
61 toolbox::task::bind(this, &GatewaySupervisor::infoRequestThread, "InfoRequest"))
62 , infoRequestSemaphore_(toolbox::BSem::FULL)
63 , activeStateMachineName_("")
65 , broadcastCommandMessageIndex_(0)
68 INIT_MF(
"GatewaySupervisor");
72 mkdir((std::string(__ENV__(
"SERVICE_DATA_PATH"))).c_str(), 0755);
73 mkdir((FSM_LAST_GROUP_ALIAS_PATH).c_str(), 0755);
74 mkdir((RUN_NUMBER_PATH).c_str(), 0755);
76 securityType_ = theWebUsers_.getSecurity();
78 __COUT__ <<
"Security: " << securityType_ << __E__;
80 xgi::bind(
this, &GatewaySupervisor::Default,
"Default");
81 xgi::bind(
this, &GatewaySupervisor::loginRequest,
"LoginRequest");
82 xgi::bind(
this, &GatewaySupervisor::request,
"Request");
83 xgi::bind(
this, &GatewaySupervisor::stateMachineXgiHandler,
"StateMachineXgiHandler");
84 xgi::bind(
this, &GatewaySupervisor::infoRequestHandler,
"InfoRequestHandler");
86 this, &GatewaySupervisor::infoRequestResultHandler,
"InfoRequestResultHandler");
87 xgi::bind(
this, &GatewaySupervisor::tooltipRequest,
"TooltipRequest");
90 &GatewaySupervisor::supervisorCookieCheck,
91 "SupervisorCookieCheck",
94 &GatewaySupervisor::supervisorGetActiveUsers,
95 "SupervisorGetActiveUsers",
98 &GatewaySupervisor::supervisorSystemMessage,
99 "SupervisorSystemMessage",
104 &GatewaySupervisor::supervisorSystemLogbookEntry,
105 "SupervisorSystemLogbookEntry",
108 &GatewaySupervisor::supervisorLastConfigGroupRequest,
109 "SupervisorLastConfigGroupRequest",
124 GatewaySupervisor::~GatewaySupervisor(
void)
126 delete CorePropertySupervisorBase::theConfigurationManager_;
127 makeSystemLogbookEntry(
"ots halted.");
133 CorePropertySupervisorBase::indicateOtsAlive(properties);
137 void GatewaySupervisor::init(
void)
139 supervisorGuiHasBeenLoaded_ =
false;
170 bool enableStateChanges =
false;
173 enableStateChanges = CorePropertySupervisorBase::getSupervisorTableNode()
174 .getNode(
"EnableStateChangesOverUDP")
184 auto artdaqStateChangeEnabled =
185 CorePropertySupervisorBase::getSupervisorTableNode()
186 .getNode(
"EnableARTDAQCommanderPlugin")
188 if(artdaqStateChangeEnabled)
190 auto artdaqStateChangePort =
191 CorePropertySupervisorBase::getSupervisorTableNode()
192 .getNode(
"ARTDAQCommanderID")
194 auto artdaqStateChangePluginType =
195 CorePropertySupervisorBase::getSupervisorTableNode()
196 .getNode(
"ARTDAQCommanderType")
197 .getValue<std::string>();
198 theArtdaqCommandable_.init(artdaqStateChangePort,
199 artdaqStateChangePluginType);
207 if(enableStateChanges)
209 __COUT__ <<
"Enabling state changes over UDP..." << __E__;
212 [](GatewaySupervisor* s) { GatewaySupervisor::StateChangerWorkLoop(s); },
217 __COUT__ <<
"State changes over UDP are disabled." << __E__;
224 void GatewaySupervisor::StateChangerWorkLoop(GatewaySupervisor* theSupervisor)
227 theSupervisor->CorePropertySupervisorBase::getSupervisorTableNode();
229 std::string ipAddressForStateChangesOverUDP =
230 configLinkNode.getNode(
"IPAddressForStateChangesOverUDP").getValue<std::string>();
231 int portForStateChangesOverUDP =
232 configLinkNode.getNode(
"PortForStateChangesOverUDP").getValue<
int>();
233 bool acknowledgementEnabled =
234 configLinkNode.getNode(
"EnableAckForStateChangesOverUDP").getValue<
bool>();
243 portForStateChangesOverUDP);
251 __SS__ <<
"FATAL Console error. Could not initialize socket at ip '"
252 << ipAddressForStateChangesOverUDP <<
"' and port "
253 << portForStateChangesOverUDP
254 <<
". Perhaps it is already in use? Exiting State Changer "
255 "SOAPUtilities::receive loop."
257 __COUT__ << ss.str();
262 std::size_t commaPosition;
263 unsigned int commaCounter = 0;
264 std::size_t begin = 0;
266 std::string errorStr;
269 std::vector<std::string> parameters;
279 buffer, 0 , 1 ,
false ) !=
282 __COUT__ <<
"UDP State Changer packet received of size = " << buffer.size()
285 size_t nCommas = std::count(buffer.begin(), buffer.end(),
',');
288 __SS__ <<
"Unrecognized State Machine command :-" << buffer
289 <<
"-. Format is FiniteStateMachineName,Command,Parameter(s). "
290 "Where Parameter(s) is/are optional."
292 __COUT_INFO__ << ss.str();
293 __MOUT_INFO__ << ss.str();
298 while((commaPosition = buffer.find(
',', begin)) != std::string::npos ||
299 commaCounter == nCommas)
301 if(commaCounter == nCommas)
302 commaPosition = buffer.size();
303 if(commaCounter == 0)
304 fsmName = buffer.substr(begin, commaPosition - begin);
305 else if(commaCounter == 1)
306 command = buffer.substr(begin, commaPosition - begin);
308 parameters.push_back(buffer.substr(begin, commaPosition - begin));
309 __COUT__ <<
"Word: " << buffer.substr(begin, commaPosition - begin)
312 begin = commaPosition + 1;
322 if(theSupervisor->VERBOSE_MUTEX)
323 __COUT__ <<
"Waiting for FSM access" << __E__;
324 std::lock_guard<std::mutex> lock(theSupervisor->stateMachineAccessMutex_);
325 if(theSupervisor->VERBOSE_MUTEX)
326 __COUT__ <<
"Have FSM access" << __E__;
328 errorStr = theSupervisor->attemptStateMachineTransition(
333 WebUsers::DEFAULT_STATECHANGER_USERNAME ,
334 WebUsers::DEFAULT_STATECHANGER_USERNAME,
340 __SS__ <<
"UDP State Changer failed to execute command because of the "
343 __COUT_ERR__ << ss.str();
344 __MOUT_ERR__ << ss.str();
345 if(acknowledgementEnabled)
346 sock.acknowledge(errorStr,
true );
350 __SS__ <<
"Successfully executed state change command '" << command
352 __COUT_INFO__ << ss.str();
353 __MOUT_INFO__ << ss.str();
354 if(acknowledgementEnabled)
355 sock.acknowledge(
"Done",
true );
369 void GatewaySupervisor::makeSystemLogbookEntry(std::string entryText)
371 __COUT__ <<
"Making System Logbook Entry: " << entryText << __E__;
373 SupervisorInfoMap logbookInfoMap =
374 allSupervisorInfo_.getAllLogbookTypeSupervisorInfo();
376 if(logbookInfoMap.size() == 0)
378 __COUT__ <<
"No logbooks found! Here is entry: " << entryText << __E__;
379 __MOUT__ <<
"No logbooks found! Here is entry: " << entryText << __E__;
384 __COUT__ <<
"Making logbook entry: " << entryText << __E__;
385 __MOUT__ <<
"Making logbook entry: " << entryText << __E__;
390 std::string replace[] = {
"\"",
"'",
"&",
"<",
">",
"\n",
" "};
391 std::string with[] = {
"%22",
"%27",
"%26",
"%3C",
"%3E",
"%0A%0D",
"%20%20"};
396 for(
int i = 0; i < numOfKeys; ++i)
398 while((f = entryText.find(replace[i])) != std::string::npos)
400 entryText = entryText.substr(0, f) + with[i] +
401 entryText.substr(f + replace[i].length());
412 for(
auto& logbookInfo : logbookInfoMap)
414 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
415 logbookInfo.second.getDescriptor(),
"MakeSystemLogbookEntry", parameters);
420 SOAPUtilities::receive(retMsg, retParameters);
422 __COUT__ <<
"Returned Status: " << retParameters.getValue(
"Status")
428 void GatewaySupervisor::Default(xgi::Input* in, xgi::Output* out)
432 if(!supervisorGuiHasBeenLoaded_ &&
433 (supervisorGuiHasBeenLoaded_ =
435 makeSystemLogbookEntry(
"ots started.");
437 *out <<
"<!DOCTYPE HTML><html lang='en'><head><title>ots</title>" <<
440 "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
441 <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
442 <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
443 <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
444 <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
445 <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
446 <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
447 <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
448 <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
449 <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
450 <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
451 <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
452 <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
453 <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
454 <meta name='msapplication-TileColor' content='#ffffff'>\
455 <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
456 <meta name='theme-color' content='#ffffff'>"
460 <<
"<frameset col='100%' row='100%'>"
461 <<
"<frame src='/WebPath/html/Desktop.html?urn="
462 << this->getApplicationDescriptor()->getLocalId()
463 <<
"&securityType=" << securityType_ <<
"'></frameset></html>";
467 void GatewaySupervisor::stateMachineXgiHandler(xgi::Input* in, xgi::Output* out)
473 __COUT__ <<
"Waiting for FSM access" << __E__;
474 std::lock_guard<std::mutex> lock(stateMachineAccessMutex_);
476 __COUT__ <<
"Have FSM access" << __E__;
478 cgicc::Cgicc cgiIn(in);
480 std::string command = CgiDataUtilities::getData(cgiIn,
"StateMachine");
481 std::string requestType =
482 "StateMachine" + command;
486 CgiDataUtilities::postData(cgiIn,
"CookieCode"));
488 CorePropertySupervisorBase::getRequestUserInfo(userInfo);
490 if(!theWebUsers_.xmlRequestOnGateway(cgiIn, out, &xmlOut, userInfo))
493 std::string fsmName = CgiDataUtilities::getData(cgiIn,
"fsmName");
494 std::string fsmWindowName = CgiDataUtilities::getData(cgiIn,
"fsmWindowName");
495 fsmWindowName = CgiDataUtilities::decodeURIComponent(fsmWindowName);
496 std::string currentState = theStateMachine_.getCurrentStateName();
498 __COUT__ <<
"Check for Handled by theIterator_" << __E__;
501 if((activeStateMachineWindowName_ ==
"" ||
502 activeStateMachineWindowName_ ==
"iterator") &&
503 theIterator_.handleCommandRequest(xmlOut, command, fsmWindowName))
505 __COUT__ <<
"Handled by theIterator_" << __E__;
506 xmlOut.outputXmlDocument((std::ostringstream*)out,
false);
511 if(theStateMachine_.isInTransition())
513 __SS__ <<
"Error - Can not accept request because the State Machine is already "
516 __COUT_ERR__ <<
"\n" << ss.str();
518 xmlOut.addTextElementToData(
"state_tranisition_attempted",
520 xmlOut.addTextElementToData(
521 "state_tranisition_attempted_err",
523 xmlOut.outputXmlDocument((std::ostringstream*)out,
false,
true);
533 if(activeStateMachineName_ !=
"" && activeStateMachineName_ != fsmName)
535 __COUT__ <<
"currentState = " << currentState << __E__;
536 if(currentState !=
"Halted" && currentState !=
"Initial")
540 __SS__ <<
"Error - Can not accept request because the State Machine "
541 <<
"with window name '" << activeStateMachineWindowName_
542 <<
"' (UID: " << activeStateMachineName_
545 <<
"in control of State Machine progress. ";
546 ss <<
"\n\nIn order for this State Machine with window name '"
547 << fsmWindowName <<
"' (UID: " << fsmName
549 "to control progress, please transition to Halted using the active "
550 <<
"State Machine '" << activeStateMachineWindowName_ <<
".'" << __E__;
551 __COUT_ERR__ <<
"\n" << ss.str();
553 xmlOut.addTextElementToData(
"state_tranisition_attempted",
555 xmlOut.addTextElementToData(
556 "state_tranisition_attempted_err",
558 xmlOut.outputXmlDocument((std::ostringstream*)out,
false,
true);
563 activeStateMachineName_ =
"";
564 activeStateMachineWindowName_ =
"";
570 std::vector<std::string> parameters;
571 if(command ==
"Configure")
572 parameters.push_back(CgiDataUtilities::postData(cgiIn,
"ConfigurationAlias"));
573 attemptStateMachineTransition(
574 &xmlOut, out, command, fsmName, fsmWindowName, userInfo.username_, parameters);
578 std::string GatewaySupervisor::attemptStateMachineTransition(
580 std::ostringstream* out,
581 const std::string& command,
582 const std::string& fsmName,
583 const std::string& fsmWindowName,
584 const std::string& username,
585 const std::vector<std::string>& commandParameters)
587 std::string errorStr =
"";
589 std::string currentState = theStateMachine_.getCurrentStateName();
590 __COUT__ <<
"State Machine command = " << command << __E__;
591 __COUT__ <<
"fsmName = " << fsmName << __E__;
592 __COUT__ <<
"fsmWindowName = " << fsmWindowName << __E__;
593 __COUT__ <<
"activeStateMachineName_ = " << activeStateMachineName_ << __E__;
594 __COUT__ <<
"command = " << command << __E__;
595 __COUT__ <<
"commandParameters.size = " << commandParameters.size() << __E__;
598 if(command ==
"Configure")
600 if(currentState !=
"Halted")
602 __SS__ <<
"Error - Can only transition to Configured if the current "
603 <<
"state is Halted. Perhaps your state machine is out of sync."
605 __COUT_ERR__ <<
"\n" << ss.str();
609 xmldoc->addTextElementToData(
610 "state_tranisition_attempted",
613 xmldoc->addTextElementToData(
614 "state_tranisition_attempted_err",
617 xmldoc->outputXmlDocument((std::ostringstream*)out,
626 if(commandParameters.size() == 0)
628 __SS__ <<
"Error - Can only transition to Configured if a Configuration "
629 "Alias parameter is provided."
631 __COUT_ERR__ <<
"\n" << ss.str();
635 xmldoc->addTextElementToData(
636 "state_tranisition_attempted",
639 xmldoc->addTextElementToData(
640 "state_tranisition_attempted_err",
643 xmldoc->outputXmlDocument((std::ostringstream*)out,
650 parameters.addParameter(
"ConfigurationAlias", commandParameters[0]);
652 std::string configurationAlias = parameters.getValue(
"ConfigurationAlias");
653 __COUT__ <<
"Configure --> Name: ConfigurationAlias Value: " << configurationAlias
657 std::string fn = FSM_LAST_GROUP_ALIAS_PATH + FSM_LAST_GROUP_ALIAS_FILE_START +
658 username +
"." + FSM_USERS_PREFERENCES_FILETYPE;
660 __COUT__ <<
"Save FSM preferences: " << fn << __E__;
661 FILE* fp = fopen(fn.c_str(),
"w");
664 __SS__ << (
"Could not open file: " + fn) << __E__;
665 __COUT_ERR__ << ss.str();
668 fprintf(fp,
"FSM_last_configuration_alias %s", configurationAlias.c_str());
671 activeStateMachineName_ = fsmName;
672 activeStateMachineWindowName_ = fsmWindowName;
674 else if(command ==
"Start")
676 if(currentState !=
"Configured")
679 <<
"Error - Can only transition to Configured if the current "
680 <<
"state is Halted. Perhaps your state machine is out of sync. "
681 <<
"(Likely the server was restarted or another user changed the state)"
683 __COUT_ERR__ <<
"\n" << ss.str();
687 xmldoc->addTextElementToData(
688 "state_tranisition_attempted",
691 xmldoc->addTextElementToData(
692 "state_tranisition_attempted_err",
695 xmldoc->outputXmlDocument((std::ostringstream*)out,
701 unsigned int runNumber;
702 if(commandParameters.size() == 0)
704 runNumber = getNextRunNumber();
705 setNextRunNumber(runNumber + 1);
709 runNumber = std::atoi(commandParameters[0].c_str());
711 parameters.addParameter(
"RunNumber", runNumber);
714 xoap::MessageReference message =
715 SOAPUtilities::makeSOAPMessageReference(command, parameters);
717 xoap::MessageReference reply = stateMachineXoapHandler(message);
722 xmldoc->addTextElementToData(
"state_tranisition_attempted",
725 xmldoc->outputXmlDocument((std::ostringstream*)out,
false);
726 __COUT__ <<
"FSM state transition launched!" << __E__;
728 stateMachineLastCommandInput_ = command;
785 xoap::MessageReference GatewaySupervisor::stateMachineXoapHandler(
786 xoap::MessageReference message)
789 __COUT__ <<
"Soap Handler!" << __E__;
790 stateMachineWorkLoopManager_.removeProcessedRequests();
791 stateMachineWorkLoopManager_.processRequest(message);
792 __COUT__ <<
"Done - Soap Handler!" << __E__;
797 xoap::MessageReference GatewaySupervisor::stateMachineResultXoapHandler(
798 xoap::MessageReference message)
801 __COUT__ <<
"Soap Handler!" << __E__;
804 __COUT__ <<
"Done - Soap Handler!" << __E__;
809 bool GatewaySupervisor::stateMachineThread(toolbox::task::WorkLoop* workLoop)
811 stateMachineSemaphore_.take();
812 std::string command =
813 SOAPUtilities::translate(stateMachineWorkLoopManager_.getMessage(workLoop))
816 __COUT__ <<
"Propagating command '" << command <<
"'..." << __E__;
818 std::string reply = send(allSupervisorInfo_.getGatewayDescriptor(),
819 stateMachineWorkLoopManager_.getMessage(workLoop));
820 stateMachineWorkLoopManager_.report(workLoop, reply, 100,
true);
822 __COUT__ <<
"Done with command '" << command <<
".' Reply = " << reply << __E__;
823 stateMachineSemaphore_.give();
827 __SS__ <<
"Failure to send Workloop transition command '" << command
828 <<
"!' An error response '" << reply <<
"' was received." << __E__;
829 __COUT_ERR__ << ss.str();
830 __MOUT_ERR__ << ss.str();
843 void GatewaySupervisor::infoRequestHandler(xgi::Input* in, xgi::Output* out)
846 __COUT__ <<
"Starting to Request!" << __E__;
848 cgicc::Cgicc cgiIn(in);
849 std::string requestType =
850 "infoRequestHandler";
854 CgiDataUtilities::postData(cgiIn,
"CookieCode"));
856 CorePropertySupervisorBase::getRequestUserInfo(userInfo);
858 if(!theWebUsers_.xmlRequestOnGateway(cgiIn, out, &xmlOut, userInfo))
866 HttpXmlDocument tmpDoc = infoRequestWorkLoopManager_.processRequest(cgiIn);
868 xmlOut.copyDataChildren(tmpDoc);
870 xmlOut.outputXmlDocument((std::ostringstream*)out,
false);
874 void GatewaySupervisor::infoRequestResultHandler(xgi::Input* in, xgi::Output* out)
877 __COUT__ <<
"Starting ask!" << __E__;
878 cgicc::Cgicc cgi(in);
880 cgicc::Cgicc cgiIn(in);
881 std::string requestType =
882 "infoRequestResultHandler";
886 CgiDataUtilities::postData(cgiIn,
"CookieCode"));
888 CorePropertySupervisorBase::getRequestUserInfo(userInfo);
890 if(!theWebUsers_.xmlRequestOnGateway(cgiIn, out, &xmlOut, userInfo))
908 infoRequestWorkLoopManager_.getRequestResult(cgiIn, xmlOut);
911 xmlOut.outputXmlDocument((std::ostringstream*)out,
false);
913 __COUT__ <<
"Done asking!" << __E__;
917 bool GatewaySupervisor::infoRequestThread(toolbox::task::WorkLoop* workLoop)
922 infoRequestSemaphore_.take();
926 for(
unsigned long long i = 0; i < 100000000; i++)
929 vectorTest_.push_back(counterTest_);
932 infoRequestWorkLoopManager_.report(
933 workLoop,
"RESULT: This is the best result ever", 50,
false);
934 std::string workLoopName = workLoop->getName();
935 __COUT__ << workLoopName <<
" test: " << counterTest_
936 <<
" vector size: " << vectorTest_.size() << __E__;
937 wait(400,
"InfoRequestThread ----- locked");
938 infoRequestSemaphore_.give();
940 wait(200,
"InfoRequestThread");
942 infoRequestSemaphore_.take();
946 for(
unsigned long long i = 0; i < 100000000; i++)
949 vectorTest_.push_back(counterTest_);
952 wait(400,
"InfoRequestThread ----- locked");
953 __COUT__ << workLoopName <<
" test: " << counterTest_
954 <<
" vector size: " << vectorTest_.size() << __E__;
955 infoRequestSemaphore_.give();
959 infoRequestWorkLoopManager_.report(
960 workLoop, theStateMachine_.getCurrentStateName(), 100,
true);
969 void GatewaySupervisor::stateInitial(toolbox::fsm::FiniteStateMachine& fsm)
972 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
980 void GatewaySupervisor::statePaused(toolbox::fsm::FiniteStateMachine& fsm)
983 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1002 void GatewaySupervisor::stateRunning(toolbox::fsm::FiniteStateMachine& fsm)
1005 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1024 void GatewaySupervisor::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
1027 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1028 __COUT__ <<
"Fsm is in transition? "
1029 << (theStateMachine_.isInTransition() ?
"yes" :
"no") << __E__;
1058 void GatewaySupervisor::stateConfigured(toolbox::fsm::FiniteStateMachine& fsm)
1132 void GatewaySupervisor::inError(toolbox::fsm::FiniteStateMachine& fsm)
1136 <<
"Fsm current state: "
1145 void GatewaySupervisor::enteringError(toolbox::Event::Reference e)
1147 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1150 toolbox::fsm::FailedEvent& failedEvent =
dynamic_cast<toolbox::fsm::FailedEvent&
>(*e);
1155 if(RunControlStateMachine::asyncFailureReceived_)
1157 ss <<
"\nAn asynchronous failure was encountered."
1158 <<
".\n\nException:\n"
1159 << failedEvent.getException().what() << __E__;
1160 RunControlStateMachine::asyncFailureReceived_ =
false;
1164 ss <<
"\nFailure performing transition from " << failedEvent.getFromState() <<
"-"
1165 << theStateMachine_.getStateName(failedEvent.getFromState()) <<
" to "
1166 << failedEvent.getToState() <<
"-"
1167 << theStateMachine_.getStateName(failedEvent.getToState())
1168 <<
".\n\nException:\n"
1169 << failedEvent.getException().what() << __E__;
1172 __COUT_ERR__ <<
"\n" << ss.str();
1173 theStateMachine_.setErrorMessage(ss.str());
1176 broadcastMessage(SOAPUtilities::makeSOAPMessageReference(
"Error"));
1180 void GatewaySupervisor::checkForAsyncError()
1182 if(RunControlStateMachine::asyncFailureReceived_)
1184 __COUTV__(RunControlStateMachine::asyncFailureReceived_);
1186 XCEPT_RAISE(toolbox::fsm::exception::Exception,
1187 RunControlStateMachine::getErrorMessage());
1197 void GatewaySupervisor::transitionConfiguring(toolbox::Event::Reference e)
1199 checkForAsyncError();
1201 RunControlStateMachine::theProgressBar_.step();
1203 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1205 std::string systemAlias =
1206 SOAPUtilities::translate(theStateMachine_.getCurrentMessage())
1208 .getValue(
"ConfigurationAlias");
1210 __COUT__ <<
"Transition parameter: " << systemAlias << __E__;
1212 RunControlStateMachine::theProgressBar_.step();
1216 CorePropertySupervisorBase::theConfigurationManager_
1221 __SS__ <<
"\nTransition to Configuring interrupted! "
1222 <<
"The Configuration Manager could not be initialized." << __E__;
1224 __COUT_ERR__ <<
"\n" << ss.str();
1225 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1229 RunControlStateMachine::theProgressBar_.step();
1234 theConfigurationTableGroup_ =
1235 CorePropertySupervisorBase::theConfigurationManager_->getTableGroupFromAlias(
1240 __COUT_INFO__ <<
"Exception occurred" << __E__;
1243 RunControlStateMachine::theProgressBar_.step();
1245 if(theConfigurationTableGroup_.second.isInvalid())
1247 __SS__ <<
"\nTransition to Configuring interrupted! System Alias " << systemAlias
1248 <<
" could not be translated to a group name and key." << __E__;
1250 __COUT_ERR__ <<
"\n" << ss.str();
1251 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1255 RunControlStateMachine::theProgressBar_.step();
1257 __COUT__ <<
"Configuration table group name: " << theConfigurationTableGroup_.first
1258 <<
" key: " << theConfigurationTableGroup_.second << __E__;
1262 std::stringstream ss;
1263 ss <<
"Configuring '" << systemAlias <<
"' which translates to "
1264 << theConfigurationTableGroup_.first <<
" ("
1265 << theConfigurationTableGroup_.second <<
").";
1266 makeSystemLogbookEntry(ss.str());
1269 RunControlStateMachine::theProgressBar_.step();
1274 CorePropertySupervisorBase::theConfigurationManager_->loadTableGroup(
1275 theConfigurationTableGroup_.first,
1276 theConfigurationTableGroup_.second,
1279 __COUT__ <<
"Done loading Configuration Alias." << __E__;
1283 tmpCfgMgr.activateTableGroup(theConfigurationTableGroup_.first,
1284 theConfigurationTableGroup_.second);
1286 __COUT__ <<
"Done activating Configuration Alias." << __E__;
1290 __SS__ <<
"\nTransition to Configuring interrupted! System Alias " << systemAlias
1291 <<
" was translated to " << theConfigurationTableGroup_.first <<
" ("
1292 << theConfigurationTableGroup_.second
1293 <<
") but could not be loaded and initialized." << __E__;
1294 ss <<
"\n\nTo debug this problem, try activating this group in the Configuration "
1296 <<
" and detailed errors will be shown." << __E__;
1297 __COUT_ERR__ <<
"\n" << ss.str();
1298 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1305 CorePropertySupervisorBase::theConfigurationManager_->getSupervisorTableNode(
1306 supervisorContextUID_, supervisorApplicationUID_);
1307 if(!configLinkNode.isDisconnected())
1311 bool dumpConfiguration =
true;
1312 std::string dumpFilePath, dumpFileRadix, dumpFormat;
1316 configLinkNode.getNode(
"LinkToStateMachineTable")
1317 .getNode(activeStateMachineName_);
1320 .getNode(
"EnableConfigurationDumpOnConfigureTransition")
1323 fsmLinkNode.getNode(
"ConfigurationDumpOnConfigureFilePath")
1324 .getValue<std::string>();
1326 fsmLinkNode.getNode(
"ConfigurationDumpOnConfigureFileRadix")
1327 .getValue<std::string>();
1328 dumpFormat = fsmLinkNode.getNode(
"ConfigurationDumpOnConfigureFormat")
1329 .getValue<std::string>();
1331 catch(std::runtime_error& e)
1333 __COUT_INFO__ <<
"FSM configuration dump Link disconnected." << __E__;
1334 dumpConfiguration =
false;
1337 if(dumpConfiguration)
1340 CorePropertySupervisorBase::theConfigurationManager_
1341 ->dumpActiveConfiguration(dumpFilePath +
"/" + dumpFileRadix +
1342 "_" + std::to_string(time(0)) +
1347 catch(std::runtime_error& e)
1349 __SS__ <<
"\nTransition to Configuring interrupted! There was an error "
1351 <<
"during the configuration dump attempt:\n\n " << e.what()
1353 __COUT_ERR__ <<
"\n" << ss.str();
1354 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1359 __SS__ <<
"\nTransition to Configuring interrupted! There was an error "
1361 <<
"during the configuration dump attempt.\n\n " << __E__;
1362 __COUT_ERR__ <<
"\n" << ss.str();
1363 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1369 RunControlStateMachine::theProgressBar_.step();
1371 parameters.addParameter(
"ConfigurationTableGroupName",
1372 theConfigurationTableGroup_.first);
1373 parameters.addParameter(
"ConfigurationTableGroupKey",
1374 theConfigurationTableGroup_.second.toString());
1378 __COUT__ <<
"Initializing Macro Maker." << __E__;
1379 xoap::MessageReference message =
1380 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1383 parameters.addParameter(
"type",
"initFElist");
1384 parameters.addParameter(
"groupName", theConfigurationTableGroup_.first);
1385 parameters.addParameter(
"groupKey",
1386 theConfigurationTableGroup_.second.toString());
1387 SOAPUtilities::addParameters(message, parameters);
1389 __COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1393 SOAPMessenger::send(CorePropertySupervisorBase::allSupervisorInfo_
1394 .getAllMacroMakerTypeSupervisorInfo()
1396 ->second.getDescriptor(),
1399 __COUT__ <<
"Macro Maker init reply: " << reply << __E__;
1400 if(reply ==
"Error")
1402 __SS__ <<
"\nTransition to Configuring interrupted! There was an error "
1403 "identified initializing Macro Maker.\n\n "
1405 __COUT_ERR__ <<
"\n" << ss.str();
1406 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1414 xoap::MessageReference message = theStateMachine_.getCurrentMessage();
1415 SOAPUtilities::addParameters(message, parameters);
1416 broadcastMessage(message);
1417 RunControlStateMachine::theProgressBar_.step();
1422 saveGroupNameAndKey(theConfigurationTableGroup_,
1423 FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE);
1425 __COUT__ <<
"Done configuring." << __E__;
1426 RunControlStateMachine::theProgressBar_.complete();
1430 void GatewaySupervisor::transitionHalting(toolbox::Event::Reference e)
1432 checkForAsyncError();
1434 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1436 makeSystemLogbookEntry(
"Run halting.");
1438 broadcastMessage(theStateMachine_.getCurrentMessage());
1442 void GatewaySupervisor::transitionShuttingDown(toolbox::Event::Reference e)
1445 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1447 RunControlStateMachine::theProgressBar_.step();
1448 makeSystemLogbookEntry(
"System shutting down.");
1449 RunControlStateMachine::theProgressBar_.step();
1452 GatewaySupervisor::launchStartOTSCommand(
1453 "OTS_APP_SHUTDOWN", CorePropertySupervisorBase::theConfigurationManager_);
1454 RunControlStateMachine::theProgressBar_.step();
1458 for(
int i = 0; i < 5; ++i)
1461 RunControlStateMachine::theProgressBar_.step();
1466 void GatewaySupervisor::transitionStartingUp(toolbox::Event::Reference e)
1469 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1471 RunControlStateMachine::theProgressBar_.step();
1472 makeSystemLogbookEntry(
"System starting up.");
1473 RunControlStateMachine::theProgressBar_.step();
1476 GatewaySupervisor::launchStartOTSCommand(
1477 "OTS_APP_STARTUP", CorePropertySupervisorBase::theConfigurationManager_);
1478 RunControlStateMachine::theProgressBar_.step();
1482 for(
int i = 0; i < 10; ++i)
1485 RunControlStateMachine::theProgressBar_.step();
1490 void GatewaySupervisor::transitionInitializing(toolbox::Event::Reference e)
1493 __COUT__ << theStateMachine_.getCurrentStateName() << __E__;
1495 broadcastMessage(theStateMachine_.getCurrentMessage());
1497 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1498 __COUT__ <<
"Fsm current transition: "
1499 << theStateMachine_.getCurrentTransitionName(e->type()) << __E__;
1500 __COUT__ <<
"Fsm final state: "
1501 << theStateMachine_.getTransitionFinalStateName(e->type()) << __E__;
1505 void GatewaySupervisor::transitionPausing(toolbox::Event::Reference e)
1507 checkForAsyncError();
1509 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1511 makeSystemLogbookEntry(
"Run pausing.");
1514 if(RunControlStateMachine::asyncSoftFailureReceived_)
1516 __COUT_ERR__ <<
"Broadcasting pause for async SOFT error!" << __E__;
1517 broadcastMessage(SOAPUtilities::makeSOAPMessageReference(
"Pause"));
1520 broadcastMessage(theStateMachine_.getCurrentMessage());
1524 void GatewaySupervisor::transitionResuming(toolbox::Event::Reference e)
1526 if(RunControlStateMachine::asyncSoftFailureReceived_)
1529 __COUT_INFO__ <<
"Clearing async SOFT error!" << __E__;
1530 RunControlStateMachine::asyncSoftFailureReceived_ =
false;
1533 checkForAsyncError();
1535 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1537 makeSystemLogbookEntry(
"Run resuming.");
1539 broadcastMessage(theStateMachine_.getCurrentMessage());
1543 void GatewaySupervisor::transitionStarting(toolbox::Event::Reference e)
1545 if(RunControlStateMachine::asyncSoftFailureReceived_)
1548 __COUT_INFO__ <<
"Clearing async SOFT error!" << __E__;
1549 RunControlStateMachine::asyncSoftFailureReceived_ =
false;
1552 checkForAsyncError();
1554 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1557 SOAPUtilities::receive(theStateMachine_.getCurrentMessage(), parameters);
1559 std::string runNumber = parameters.getValue(
"RunNumber");
1560 __COUTV__(runNumber);
1565 CorePropertySupervisorBase::theConfigurationManager_->getSupervisorTableNode(
1566 supervisorContextUID_, supervisorApplicationUID_);
1567 if(!configLinkNode.isDisconnected())
1571 bool dumpConfiguration =
true;
1572 std::string dumpFilePath, dumpFileRadix, dumpFormat;
1576 configLinkNode.getNode(
"LinkToStateMachineTable")
1577 .getNode(activeStateMachineName_);
1579 fsmLinkNode.getNode(
"EnableConfigurationDumpOnRunTransition")
1581 dumpFilePath = fsmLinkNode.getNode(
"ConfigurationDumpOnRunFilePath")
1582 .getValue<std::string>();
1583 dumpFileRadix = fsmLinkNode.getNode(
"ConfigurationDumpOnRunFileRadix")
1584 .getValue<std::string>();
1585 dumpFormat = fsmLinkNode.getNode(
"ConfigurationDumpOnRunFormat")
1586 .getValue<std::string>();
1588 catch(std::runtime_error& e)
1590 __COUT_INFO__ <<
"FSM configuration dump Link disconnected." << __E__;
1591 dumpConfiguration =
false;
1594 if(dumpConfiguration)
1597 CorePropertySupervisorBase::theConfigurationManager_
1598 ->dumpActiveConfiguration(dumpFilePath +
"/" + dumpFileRadix +
1599 "_Run" + runNumber +
"_" +
1600 std::to_string(time(0)) +
".dump",
1604 catch(std::runtime_error& e)
1606 __SS__ <<
"\nTransition to Running interrupted! There was an error "
1608 <<
"during the configuration dump attempt:\n\n " << e.what()
1610 __COUT_ERR__ <<
"\n" << ss.str();
1611 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1616 __SS__ <<
"\nTransition to Running interrupted! There was an error "
1618 <<
"during the configuration dump attempt.\n\n " << __E__;
1619 __COUT_ERR__ <<
"\n" << ss.str();
1620 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1626 makeSystemLogbookEntry(
"Run " + runNumber +
" starting.");
1628 broadcastMessage(theStateMachine_.getCurrentMessage());
1631 saveGroupNameAndKey(theConfigurationTableGroup_, FSM_LAST_STARTED_GROUP_ALIAS_FILE);
1635 void GatewaySupervisor::transitionStopping(toolbox::Event::Reference e)
1637 checkForAsyncError();
1639 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1641 makeSystemLogbookEntry(
"Run stopping.");
1643 broadcastMessage(theStateMachine_.getCurrentMessage());
1656 bool GatewaySupervisor::handleBroadcastMessageTarget(
const SupervisorInfo& appInfo,
1657 xoap::MessageReference message,
1658 const std::string& command,
1659 const unsigned int& iteration,
1661 unsigned int threadIndex)
1663 unsigned int subIteration = 0;
1664 bool subIterationsDone =
false;
1665 bool iterationsDone =
true;
1667 while(!subIterationsDone)
1669 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1670 <<
"Supervisor instance = '" << appInfo.getName()
1671 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1672 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1673 <<
"] Command = " << command << __E__;
1675 subIterationsDone =
true;
1676 RunControlStateMachine::theProgressBar_.step();
1682 parameters.addParameter(
"subIterationIndex", subIteration);
1683 SOAPUtilities::addParameters(message, parameters);
1686 if(iteration || subIteration)
1687 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1688 <<
"Adding iteration parameters " << iteration <<
"." << subIteration
1691 RunControlStateMachine::theProgressBar_.step();
1693 if(iteration == 0 && subIteration == 0)
1695 for(
unsigned int j = 0; j < 4; ++j)
1696 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1697 <<
"Sending message to Supervisor " << appInfo.getName()
1698 <<
" [LID=" << appInfo.getId() <<
"]: " << command << __E__;
1702 if(subIteration == 0)
1704 for(
unsigned int j = 0; j < 4; ++j)
1705 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1706 <<
"Sending message to Supervisor " << appInfo.getName()
1707 <<
" [LID=" << appInfo.getId() <<
"]: " << command
1708 <<
" (iteration: " << iteration <<
")" << __E__;
1712 for(
unsigned int j = 0; j < 4; ++j)
1713 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1714 <<
"Sending message to Supervisor " << appInfo.getName()
1715 <<
" [LID=" << appInfo.getId() <<
"]: " << command
1716 <<
" (iteration: " << iteration
1717 <<
", sub-iteration: " << subIteration <<
")" << __E__;
1725 std::lock_guard<std::mutex> lock(broadcastCommandMessageIndexMutex_);
1726 parameters.addParameter(
"commandId", broadcastCommandMessageIndex_++);
1728 SOAPUtilities::addParameters(message, parameters);
1731 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1732 <<
"Sending... \t" << SOAPUtilities::translate(message) << std::endl;
1736 reply = send(appInfo.getDescriptor(), message);
1738 catch(
const xdaq::exception::Exception& e)
1741 __SS__ <<
"Error! Gateway Supervisor can NOT " << command
1742 <<
" Supervisor instance = '" << appInfo.getName()
1743 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1744 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1746 <<
"Xoap message failure. Did the target Supervisor crash? Try "
1747 "re-initializing or restarting otsdaq."
1749 __COUT_ERR__ << ss.str();
1750 __MOUT_ERR__ << ss.str();
1754 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1755 <<
"Try again.." << __E__;
1760 parameters.addParameter(
"retransmission",
"1");
1761 SOAPUtilities::addParameters(message, parameters);
1768 std::lock_guard<std::mutex> lock(
1769 broadcastCommandMessageIndexMutex_);
1770 parameters.addParameter(
"commandId",
1771 broadcastCommandMessageIndex_++);
1773 SOAPUtilities::addParameters(message, parameters);
1776 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1777 <<
"Re-Sending... " << SOAPUtilities::translate(message)
1780 reply = send(appInfo.getDescriptor(), message);
1782 catch(
const xdaq::exception::Exception& e)
1784 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1785 <<
"Second try failed.." << __E__;
1786 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1788 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1789 <<
"2nd try passed.." << __E__;
1792 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1793 <<
"Reply received = " << reply << __E__;
1795 if((reply != command +
"Done") && (reply != command +
"Response") &&
1796 (reply != command +
"Iterate") && (reply != command +
"SubIterate"))
1798 __SS__ <<
"Error! Gateway Supervisor can NOT " << command
1799 <<
" Supervisor instance = '" << appInfo.getName()
1800 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1801 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1804 __COUT_ERR__ << ss.str() << __E__;
1805 __MOUT_ERR__ << ss.str() << __E__;
1807 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1808 <<
"Getting error message..." << __E__;
1811 xoap::MessageReference errorMessage =
1812 sendWithSOAPReply(appInfo.getDescriptor(),
1813 SOAPUtilities::makeSOAPMessageReference(
1814 "StateMachineErrorMessageRequest"));
1816 parameters.addParameter(
"ErrorMessage");
1817 SOAPUtilities::receive(errorMessage, parameters);
1819 std::string error = parameters.getValue(
"ErrorMessage");
1822 std::stringstream err;
1823 err <<
"Unknown error from Supervisor instance = '"
1824 << appInfo.getName() <<
"' [LID=" << appInfo.getId()
1825 <<
"] in Context '" << appInfo.getContextName()
1826 <<
"' [URL=" << appInfo.getURL()
1827 <<
"]. If the problem persists or is repeatable, please notify "
1832 __SS__ <<
"Received error from Supervisor instance = '"
1833 << appInfo.getName() <<
"' [LID=" << appInfo.getId()
1834 <<
"] in Context '" << appInfo.getContextName()
1835 <<
"' [URL=" << appInfo.getURL()
1836 <<
"].\n\n Error Message = " << error << __E__;
1838 __COUT_ERR__ << ss.str() << __E__;
1839 __MOUT_ERR__ << ss.str() << __E__;
1841 if(command ==
"Error")
1845 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1847 catch(
const xdaq::exception::Exception& e)
1850 __SS__ <<
"Error! Gateway Supervisor failed to read error message from "
1851 "Supervisor instance = '"
1852 << appInfo.getName() <<
"' [LID=" << appInfo.getId()
1853 <<
"] in Context '" << appInfo.getContextName()
1854 <<
"' [URL=" << appInfo.getURL() <<
"].\n\n"
1855 <<
"Xoap message failure. Did the target Supervisor crash? Try "
1856 "re-initializing or restarting otsdaq."
1858 __COUT_ERR__ << ss.str();
1859 __MOUT_ERR__ << ss.str();
1860 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1863 else if(reply == command +
"Iterate")
1870 iterationsDone =
false;
1871 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1872 <<
"Supervisor instance = '" << appInfo.getName()
1873 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1874 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1875 <<
"] flagged for another iteration to " << command
1876 <<
"... (iteration: " << iteration <<
")" << __E__;
1879 else if(reply == command +
"SubIterate")
1886 subIterationsDone =
false;
1887 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1888 <<
"Supervisor instance = '" << appInfo.getName()
1889 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1890 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1891 <<
"] flagged for another sub-iteration to " << command
1892 <<
"... (iteration: " << iteration
1893 <<
", sub-iteration: " << subIteration <<
")" << __E__;
1897 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1898 <<
"Supervisor instance = '" << appInfo.getName()
1899 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1900 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1901 <<
"] was " << command <<
"'d correctly!" << __E__;
1905 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1906 <<
"Completed sub-iteration: " << subIteration << __E__;
1911 return iterationsDone;
1919 void GatewaySupervisor::broadcastMessageThread(
1920 GatewaySupervisor* supervisorPtr,
1921 GatewaySupervisor::BroadcastThreadStruct* threadStruct)
1923 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1924 <<
"starting..." << __E__;
1926 while(!threadStruct->exitThread_)
1932 std::lock_guard<std::mutex> lock(threadStruct->threadMutex);
1933 if(threadStruct->workToDo_)
1935 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1936 <<
"starting work..." << __E__;
1940 if(supervisorPtr->handleBroadcastMessageTarget(
1941 threadStruct->getAppInfo(),
1942 threadStruct->getMessage(),
1943 threadStruct->getCommand(),
1944 threadStruct->getIteration(),
1945 threadStruct->getReply(),
1946 threadStruct->threadIndex_))
1947 threadStruct->getIterationsDone() =
true;
1949 catch(toolbox::fsm::exception::Exception
const& e)
1951 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1952 <<
"going into error: " << e.what() << __E__;
1954 threadStruct->getReply() = e.what();
1955 threadStruct->error_ =
true;
1956 threadStruct->workToDo_ =
false;
1957 threadStruct->working_ =
false;
1961 if(!threadStruct->getIterationsDone())
1963 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1964 <<
"flagged for another iteration." << __E__;
1967 std::lock_guard<std::mutex> lock(
1968 supervisorPtr->broadcastIterationsDoneMutex_);
1969 supervisorPtr->broadcastIterationsDone_ =
false;
1972 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1973 <<
"done with work." << __E__;
1975 threadStruct->workToDo_ =
false;
1980 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1981 <<
"exited." << __E__;
1982 threadStruct->working_ =
false;
1990 void GatewaySupervisor::broadcastMessage(xoap::MessageReference message)
1992 RunControlStateMachine::theProgressBar_.step();
1995 allSupervisorInfo_.setSupervisorStatus(
this, theStateMachine_.getCurrentStateName());
1997 std::string command = SOAPUtilities::translate(message).getCommand();
2000 broadcastIterationsDone_ =
false;
2003 std::vector<std::vector<const SupervisorInfo*>> orderedSupervisors;
2007 orderedSupervisors = allSupervisorInfo_.getOrderedSupervisorDescriptors(command);
2009 catch(
const std::runtime_error& e)
2011 __SS__ <<
"Error getting supervisor priority. Was there a change in the context?"
2012 <<
" Remember, if the context was changed, it is safest to relaunch "
2014 << e.what() << __E__;
2015 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
2018 RunControlStateMachine::theProgressBar_.step();
2022 GatewaySupervisor::BroadcastMessageIterationsDoneStruct supervisorIterationsDone;
2025 for(
const auto& vectorAtPriority : orderedSupervisors)
2026 supervisorIterationsDone.push(
2027 vectorAtPriority.size());
2031 unsigned int iteration = 0;
2032 unsigned int subIteration;
2037 xoap::MessageReference originalMessage =
2038 SOAPUtilities::makeSOAPMessageReference(SOAPUtilities::translate(message));
2040 __COUT__ <<
"=========> Broadcasting state machine command = " << command << __E__;
2042 unsigned int numberOfThreads = 1;
2046 numberOfThreads = CorePropertySupervisorBase::getSupervisorTableNode()
2047 .getNode(
"NumberOfStateMachineBroadcastThreads")
2048 .getValue<
unsigned int>();
2053 __COUT__ <<
"Number of threads not in configuration, so defaulting to "
2054 << numberOfThreads << __E__;
2059 if(numberOfThreads == 1)
2060 numberOfThreads = 0;
2062 __COUTV__(numberOfThreads);
2064 std::vector<GatewaySupervisor::BroadcastThreadStruct> broadcastThreadStructs(
2069 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2071 broadcastThreadStructs[i].threadIndex_ = i;
2074 [](GatewaySupervisor* supervisorPtr,
2075 GatewaySupervisor::BroadcastThreadStruct* threadStruct) {
2076 GatewaySupervisor::broadcastMessageThread(supervisorPtr, threadStruct);
2079 &broadcastThreadStructs[i])
2083 RunControlStateMachine::theProgressBar_.step();
2091 broadcastIterationsDone_ =
true;
2094 __COUT__ <<
"Starting iteration: " << iteration << __E__;
2096 for(
unsigned int i = 0; i < supervisorIterationsDone.size(); ++i)
2098 for(
unsigned int j = 0; j < supervisorIterationsDone.size(i); ++j)
2100 checkForAsyncError();
2102 if(supervisorIterationsDone[i][j])
2108 message = SOAPUtilities::makeSOAPMessageReference(
2109 SOAPUtilities::translate(originalMessage));
2116 parameters.addParameter(
"iterationIndex", iteration);
2117 SOAPUtilities::addParameters(message, parameters);
2123 assignedJob =
false;
2126 for(
unsigned int k = 0; k < numberOfThreads; ++k)
2128 if(!broadcastThreadStructs[k].workToDo_)
2132 __COUT__ <<
"Giving work to thread " << k << __E__;
2134 std::lock_guard<std::mutex> lock(
2135 broadcastThreadStructs[k].threadMutex);
2136 broadcastThreadStructs[k].setMessage(
2141 supervisorIterationsDone[i][j]);
2149 __COUT__ <<
"No free broadcast threads, "
2150 <<
"waiting for an available thread..." << __E__;
2151 usleep(100 * 1000 );
2153 }
while(!assignedJob);
2157 if(handleBroadcastMessageTarget(
2158 appInfo, message, command, iteration, reply))
2159 supervisorIterationsDone[i][j] =
true;
2161 broadcastIterationsDone_ =
false;
2171 <<
"Done with priority level. Waiting for threads to finish..."
2177 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2178 if(broadcastThreadStructs[i].workToDo_)
2181 __COUT__ <<
"Still waiting on thread " << i <<
"..."
2183 usleep(100 * 1000 );
2186 else if(broadcastThreadStructs[i].error_)
2188 __COUT__ <<
"Found thread in error! Throwing state "
2190 << broadcastThreadStructs[i].getReply() << __E__;
2191 XCEPT_RAISE(toolbox::fsm::exception::Exception,
2192 broadcastThreadStructs[i].getReply());
2195 __COUT__ <<
"All threads done with priority level work." << __E__;
2206 if(iteration || !broadcastIterationsDone_)
2207 __COUT__ <<
"Completed iteration: " << iteration << __E__;
2210 }
while(!broadcastIterationsDone_);
2212 RunControlStateMachine::theProgressBar_.step();
2216 __COUT__ <<
"Exception caught, exiting broadcast threads..." << __E__;
2223 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2224 broadcastThreadStructs[i].exitThread_ =
true;
2225 usleep(100 * 1000 );
2232 __COUT__ <<
"All transitions completed. Wrapping up, exiting broadcast threads..."
2241 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2242 broadcastThreadStructs[i].exitThread_ =
true;
2243 usleep(100 * 1000 );
2246 __COUT__ <<
"Broadcast complete." << __E__;
2250 void GatewaySupervisor::wait(
int milliseconds, std::string who)
const
2252 for(
int s = 1; s <= milliseconds; s++)
2257 __COUT__ << s <<
" msecs " << who << __E__;
2266 void GatewaySupervisor::loginRequest(xgi::Input* in, xgi::Output* out)
2268 __COUT__ <<
"Start" << __E__;
2269 cgicc::Cgicc cgi(in);
2270 std::string Command = CgiDataUtilities::getData(cgi,
"RequestType");
2271 __COUT__ <<
"*** Login RequestType = " << Command << __E__;
2280 std::vector<std::string> loggedOutUsernames;
2281 theWebUsers_.cleanupExpiredEntries(&loggedOutUsernames);
2282 for(
unsigned int i = 0; i < loggedOutUsernames.size();
2284 makeSystemLogbookEntry(loggedOutUsernames[i] +
" login timed out.");
2286 if(Command ==
"sessionId")
2295 std::string uuid = CgiDataUtilities::postData(cgi,
"uuid");
2297 std::string sid = theWebUsers_.createNewLoginSession(
2298 uuid, cgi.getEnvironment().getRemoteAddr() );
2304 else if(Command ==
"checkCookie")
2308 std::string jumbledUser;
2309 std::string cookieCode;
2320 uuid = CgiDataUtilities::postData(cgi,
"uuid");
2321 jumbledUser = CgiDataUtilities::postData(cgi,
"ju");
2322 cookieCode = CgiDataUtilities::postData(cgi,
"cc");
2330 uid = theWebUsers_.isCookieCodeActiveForLogin(
2335 if(uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
2337 __COUT__ <<
"cookieCode invalid" << __E__;
2342 __COUT__ <<
"cookieCode is good." << __E__;
2347 theWebUsers_.insertSettingsForUser(uid, &xmldoc);
2349 xmldoc.outputXmlDocument((std::ostringstream*)out);
2351 else if(Command ==
"login")
2362 std::string uuid = CgiDataUtilities::postData(cgi,
"uuid");
2363 std::string newAccountCode = CgiDataUtilities::postData(cgi,
"nac");
2364 std::string jumbledUser = CgiDataUtilities::postData(cgi,
"ju");
2365 std::string jumbledPw = CgiDataUtilities::postData(cgi,
"jp");
2372 uint64_t uid = theWebUsers_.attemptActiveSession(
2377 cgi.getEnvironment()
2380 if(uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
2382 __COUT__ <<
"Login invalid." << __E__;
2384 if(newAccountCode !=
"1")
2385 newAccountCode =
"0";
2388 makeSystemLogbookEntry(theWebUsers_.getUsersUsername(uid) +
" logged in.");
2394 theWebUsers_.insertSettingsForUser(uid, &xmldoc);
2398 if(uid != theWebUsers_.NOT_FOUND_IN_DATABASE)
2400 uint64_t asCnt = theWebUsers_.getActiveSessionCountForUser(uid) -
2403 sprintf(asStr,
"%lu", asCnt);
2404 xmldoc.addTextElementToData(
"user_active_session_count", asStr);
2407 xmldoc.outputXmlDocument((std::ostringstream*)out);
2409 else if(Command ==
"cert")
2420 std::string uuid = CgiDataUtilities::postData(cgi,
"uuid");
2421 std::string jumbledEmail =
2422 cgicc::form_urldecode(CgiDataUtilities::getData(cgi,
"httpsUser"));
2423 std::string username =
"";
2424 std::string cookieCode =
"";
2430 uint64_t uid = theWebUsers_.attemptActiveSessionWithCert(
2435 cgi.getEnvironment()
2438 if(uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
2440 __COUT__ <<
"cookieCode invalid" << __E__;
2442 if(cookieCode !=
"1")
2446 makeSystemLogbookEntry(theWebUsers_.getUsersUsername(uid) +
" logged in.");
2452 theWebUsers_.insertSettingsForUser(uid, &xmldoc);
2456 if(uid != theWebUsers_.NOT_FOUND_IN_DATABASE)
2458 uint64_t asCnt = theWebUsers_.getActiveSessionCountForUser(uid) -
2461 sprintf(asStr,
"%lu", asCnt);
2462 xmldoc.addTextElementToData(
"user_active_session_count", asStr);
2465 xmldoc.outputXmlDocument((std::ostringstream*)out);
2467 else if(Command ==
"logout")
2469 std::string cookieCode = CgiDataUtilities::postData(cgi,
"CookieCode");
2470 std::string logoutOthers = CgiDataUtilities::postData(cgi,
"LogoutOthers");
2476 if(theWebUsers_.cookieCodeLogout(cookieCode,
2477 logoutOthers ==
"1",
2479 cgi.getEnvironment().getRemoteAddr()) !=
2480 theWebUsers_.NOT_FOUND_IN_DATABASE)
2484 if(!theWebUsers_.isUserIdActive(uid))
2485 makeSystemLogbookEntry(theWebUsers_.getUsersUsername(uid) +
2491 __COUT__ <<
"Invalid Command" << __E__;
2495 __COUT__ <<
"Done" << __E__;
2499 void GatewaySupervisor::tooltipRequest(xgi::Input* in, xgi::Output* out)
2501 __COUT__ <<
"Start" << __E__;
2502 cgicc::Cgicc cgi(in);
2504 std::string Command = CgiDataUtilities::getData(cgi,
"RequestType");
2505 __COUT__ <<
"Tooltip RequestType = " << Command << __E__;
2512 std::string cookieCode = CgiDataUtilities::postData(cgi,
"CookieCode");
2515 if(!theWebUsers_.cookieCodeIsActiveForRequest(
2516 cookieCode, 0 , &uid,
"0" ,
false ))
2526 if(Command ==
"check")
2528 WebUsers::tooltipCheckForUsername(theWebUsers_.getUsersUsername(uid),
2530 CgiDataUtilities::getData(cgi,
"srcFile"),
2531 CgiDataUtilities::getData(cgi,
"srcFunc"),
2532 CgiDataUtilities::getData(cgi,
"srcId"));
2534 else if(Command ==
"setNeverShow")
2536 WebUsers::tooltipSetNeverShowForUsername(
2537 theWebUsers_.getUsersUsername(uid),
2539 CgiDataUtilities::getData(cgi,
"srcFile"),
2540 CgiDataUtilities::getData(cgi,
"srcFunc"),
2541 CgiDataUtilities::getData(cgi,
"srcId"),
2542 CgiDataUtilities::getData(cgi,
"doNeverShow") ==
"1" ?
true :
false,
2543 CgiDataUtilities::getData(cgi,
"temporarySilence") ==
"1" ?
true :
false);
2546 __COUT__ <<
"Command Request, " << Command <<
", not recognized." << __E__;
2548 xmldoc.outputXmlDocument((std::ostringstream*)out,
false,
true);
2550 __COUT__ <<
"Done" << __E__;
2557 void GatewaySupervisor::setSupervisorPropertyDefaults()
2559 CorePropertySupervisorBase::setSupervisorProperty(
2560 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
2561 std::string() +
"*=1 | gatewayLaunchOTS=-1 | gatewayLaunchWiz=-1");
2567 void GatewaySupervisor::forceSupervisorPropertyValues()
2573 CorePropertySupervisorBase::setSupervisorProperty(
2574 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
2575 "getSystemMessages | getCurrentState | getIterationPlanStatus");
2576 CorePropertySupervisorBase::setSupervisorProperty(
2577 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.RequireUserLockRequestTypes,
2578 "gatewayLaunchOTS | gatewayLaunchWiz");
2584 void GatewaySupervisor::request(xgi::Input* in, xgi::Output* out)
2592 __COUT__ <<
"Waiting for FSM access" << __E__;
2593 std::lock_guard<std::mutex> lock(stateMachineAccessMutex_);
2595 __COUT__ <<
"Have FSM access" << __E__;
2597 cgicc::Cgicc cgiIn(in);
2599 std::string requestType = CgiDataUtilities::getData(cgiIn,
"RequestType");
2603 CgiDataUtilities::postData(cgiIn,
"CookieCode"));
2605 CorePropertySupervisorBase::getRequestUserInfo(userInfo);
2607 if(!theWebUsers_.xmlRequestOnGateway(cgiIn, out, &xmlOut, userInfo))
2634 if(requestType ==
"getSettings")
2636 std::string accounts = CgiDataUtilities::getData(cgiIn,
"accounts");
2638 __COUT__ <<
"Get Settings Request" << __E__;
2639 __COUT__ <<
"accounts = " << accounts << __E__;
2640 theWebUsers_.insertSettingsForUser(userInfo.uid_, &xmlOut, accounts ==
"1");
2642 else if(requestType ==
"setSettings")
2644 std::string bgcolor = CgiDataUtilities::postData(cgiIn,
"bgcolor");
2645 std::string dbcolor = CgiDataUtilities::postData(cgiIn,
"dbcolor");
2646 std::string wincolor = CgiDataUtilities::postData(cgiIn,
"wincolor");
2647 std::string layout = CgiDataUtilities::postData(cgiIn,
"layout");
2648 std::string syslayout = CgiDataUtilities::postData(cgiIn,
"syslayout");
2650 __COUT__ <<
"Set Settings Request" << __E__;
2651 __COUT__ <<
"bgcolor = " << bgcolor << __E__;
2652 __COUT__ <<
"dbcolor = " << dbcolor << __E__;
2653 __COUT__ <<
"wincolor = " << wincolor << __E__;
2654 __COUT__ <<
"layout = " << layout << __E__;
2655 __COUT__ <<
"syslayout = " << syslayout << __E__;
2657 theWebUsers_.changeSettingsForUser(
2658 userInfo.uid_, bgcolor, dbcolor, wincolor, layout, syslayout);
2659 theWebUsers_.insertSettingsForUser(
2660 userInfo.uid_, &xmlOut,
true);
2662 else if(requestType ==
"accountSettings")
2664 std::string type = CgiDataUtilities::postData(
2668 if(type ==
"updateAccount")
2670 else if(type ==
"createAccount")
2672 else if(type ==
"deleteAccount")
2675 std::string username = CgiDataUtilities::postData(cgiIn,
"username");
2676 std::string displayname = CgiDataUtilities::postData(cgiIn,
"displayname");
2677 std::string email = CgiDataUtilities::postData(cgiIn,
"useremail");
2678 std::string permissions = CgiDataUtilities::postData(cgiIn,
"permissions");
2679 std::string accounts = CgiDataUtilities::getData(cgiIn,
"accounts");
2681 __COUT__ <<
"accountSettings Request" << __E__;
2682 __COUT__ <<
"type = " << type <<
" - " << type_int << __E__;
2683 __COUT__ <<
"username = " << username << __E__;
2684 __COUT__ <<
"useremail = " << email << __E__;
2685 __COUT__ <<
"displayname = " << displayname << __E__;
2686 __COUT__ <<
"permissions = " << permissions << __E__;
2688 theWebUsers_.modifyAccountSettings(
2689 userInfo.uid_, type_int, username, displayname, email, permissions);
2691 __COUT__ <<
"accounts = " << accounts << __E__;
2693 theWebUsers_.insertSettingsForUser(userInfo.uid_, &xmlOut, accounts ==
"1");
2695 else if(requestType ==
"stateMatchinePreferences")
2697 std::string set = CgiDataUtilities::getData(cgiIn,
"set");
2698 const std::string DEFAULT_FSM_VIEW =
"Default_FSM_View";
2700 theWebUsers_.setGenericPreference(
2703 CgiDataUtilities::getData(cgiIn, DEFAULT_FSM_VIEW));
2705 theWebUsers_.getGenericPreference(
2706 userInfo.uid_, DEFAULT_FSM_VIEW, &xmlOut);
2708 else if(requestType ==
"getAliasList")
2710 std::string username = theWebUsers_.getUsersUsername(userInfo.uid_);
2711 std::string fsmName = CgiDataUtilities::getData(cgiIn,
"fsmName");
2712 __COUT__ <<
"fsmName = " << fsmName << __E__;
2714 std::string stateMachineAliasFilter =
"*";
2716 std::map<std::string ,
2718 aliasMap = CorePropertySupervisorBase::theConfigurationManager_
2719 ->getActiveGroupAliases();
2723 CorePropertySupervisorBase::theConfigurationManager_
2724 ->getSupervisorTableNode(supervisorContextUID_,
2725 supervisorApplicationUID_);
2727 if(!configLinkNode.isDisconnected())
2732 configLinkNode.getNode(
"LinkToStateMachineTable");
2733 if(!fsmLinkNode.isDisconnected())
2734 stateMachineAliasFilter =
2735 fsmLinkNode.getNode(fsmName +
"/SystemAliasFilter")
2736 .getValue<std::string>();
2738 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
2740 catch(std::runtime_error& e)
2742 __COUT_INFO__ << e.what() << __E__;
2746 __COUT_ERR__ <<
"Unknown error. Should never happen." << __E__;
2750 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
2752 __COUT__ <<
"stateMachineAliasFilter = " << stateMachineAliasFilter << __E__;
2759 stateMachineAliasFilter.size() && stateMachineAliasFilter[0] ==
'!';
2760 std::vector<std::string> filterArr;
2767 while((f = stateMachineAliasFilter.find(
'*', i)) != std::string::npos)
2769 tmp = stateMachineAliasFilter.substr(i, f - i);
2771 filterArr.push_back(tmp);
2775 if(i <= stateMachineAliasFilter.size())
2777 tmp = stateMachineAliasFilter.substr(i);
2778 filterArr.push_back(tmp);
2784 for(
auto& aliasMapPair : aliasMap)
2790 if(filterArr.size() == 1)
2792 if(filterArr[0] !=
"" && filterArr[0] !=
"*" &&
2793 aliasMapPair.first != filterArr[0])
2794 filterMatch =
false;
2799 for(f = 0; f < filterArr.size(); ++f)
2801 if(!filterArr[f].size())
2806 if((i = aliasMapPair.first.find(filterArr[f])) != 0)
2808 filterMatch =
false;
2813 filterArr.size() - 1)
2815 if(aliasMapPair.first.rfind(filterArr[f]) !=
2816 aliasMapPair.first.size() - filterArr[f].size())
2818 filterMatch =
false;
2822 else if((i = aliasMapPair.first.find(filterArr[f])) ==
2825 filterMatch =
false;
2832 filterMatch = !filterMatch;
2839 xmlOut.addTextElementToData(
"config_alias", aliasMapPair.first);
2840 xmlOut.addTextElementToData(
2842 TableGroupKey::getFullGroupString(aliasMapPair.second.first,
2843 aliasMapPair.second.second)
2846 std::string groupComment, groupAuthor, groupCreationTime;
2849 CorePropertySupervisorBase::theConfigurationManager_
2850 ->loadTableGroup(aliasMapPair.second.first,
2851 aliasMapPair.second.second,
2861 xmlOut.addTextElementToData(
"config_comment", groupComment);
2862 xmlOut.addTextElementToData(
"config_author", groupAuthor);
2863 xmlOut.addTextElementToData(
"config_create_time",
2868 __COUT_WARN__ <<
"Failed to load group metadata." << __E__;
2874 std::string fn = FSM_LAST_GROUP_ALIAS_PATH + FSM_LAST_GROUP_ALIAS_FILE_START +
2875 username +
"." + FSM_USERS_PREFERENCES_FILETYPE;
2876 __COUT__ <<
"Load preferences: " << fn << __E__;
2877 FILE* fp = fopen(fn.c_str(),
"r");
2880 char tmpLastAlias[500];
2881 fscanf(fp,
"%*s %s", tmpLastAlias);
2882 __COUT__ <<
"tmpLastAlias: " << tmpLastAlias << __E__;
2884 xmlOut.addTextElementToData(
"UserLastConfigAlias", tmpLastAlias);
2888 else if(requestType ==
"getFecList")
2890 xmlOut.addTextElementToData(
"fec_list",
"");
2892 for(
auto it : allSupervisorInfo_.getAllFETypeSupervisorInfo())
2894 xmlOut.addTextElementToParent(
"fec_url", it.second.getURL(),
"fec_list");
2895 xmlOut.addTextElementToParent(
2896 "fec_urn", std::to_string(it.second.getId()),
"fec_list");
2899 else if(requestType ==
"getSystemMessages")
2901 xmlOut.addTextElementToData(
2903 theSystemMessenger_.getSystemMessage(
2904 theWebUsers_.getUsersDisplayName(userInfo.uid_)));
2906 xmlOut.addTextElementToData(
2907 "username_with_lock",
2908 theWebUsers_.getUserWithLock());
2912 else if(requestType ==
"setUserWithLock")
2914 std::string username = CgiDataUtilities::postData(cgiIn,
"username");
2915 std::string lock = CgiDataUtilities::postData(cgiIn,
"lock");
2916 std::string accounts = CgiDataUtilities::getData(cgiIn,
"accounts");
2918 __COUT__ << requestType << __E__;
2919 __COUT__ <<
"username " << username << __E__;
2920 __COUT__ <<
"lock " << lock << __E__;
2921 __COUT__ <<
"accounts " << accounts << __E__;
2922 __COUT__ <<
"userInfo.uid_ " << userInfo.uid_ << __E__;
2924 std::string tmpUserWithLock = theWebUsers_.getUserWithLock();
2925 if(!theWebUsers_.setUserWithLock(userInfo.uid_, lock ==
"1", username))
2926 xmlOut.addTextElementToData(
2928 std::string(
"Set user lock action failed. You must have valid "
2929 "permissions and ") +
2930 "locking user must be currently logged in.");
2932 theWebUsers_.insertSettingsForUser(userInfo.uid_, &xmlOut, accounts ==
"1");
2934 if(tmpUserWithLock !=
2937 theSystemMessenger_.addSystemMessage(
2939 theWebUsers_.getUserWithLock() ==
""
2940 ? tmpUserWithLock +
" has unlocked ots."
2941 : theWebUsers_.getUserWithLock() +
" has locked ots.");
2943 else if(requestType ==
"getStateMachine")
2946 std::vector<toolbox::fsm::State> states;
2947 states = theStateMachine_.getStates();
2950 std::string transName;
2951 std::string transParameter;
2954 for(
unsigned int i = 0; i < states.size(); ++i)
2956 stateStr[0] = states[i];
2957 DOMElement* stateParent = xmlOut.addTextElementToData(
"state", stateStr);
2959 xmlOut.addTextElementToParent(
2960 "state_name", theStateMachine_.getStateName(states[i]), stateParent);
2967 std::map<std::string, toolbox::fsm::State, std::less<std::string>> trans =
2968 theStateMachine_.getTransitions(states[i]);
2969 std::set<std::string> actionNames = theStateMachine_.getInputs(states[i]);
2971 std::map<std::string, toolbox::fsm::State, std::less<std::string>>::
2972 iterator it = trans.begin();
2973 std::set<std::string>::iterator ait = actionNames.begin();
2981 for(; it != trans.end() && ait != actionNames.end(); ++it, ++ait)
2983 stateStr[0] = it->second;
2985 if(stateStr[0] ==
'R')
2988 xmlOut.addTextElementToParent(
2989 "state_transition", stateStr, stateParent);
2993 xmlOut.addTextElementToParent(
2994 "state_transition_action", *ait, stateParent);
2996 transName = theStateMachine_.getTransitionName(states[i], *ait);
2999 xmlOut.addTextElementToParent(
3000 "state_transition_name", transName, stateParent);
3002 theStateMachine_.getTransitionParameter(states[i], *ait);
3005 xmlOut.addTextElementToParent(
3006 "state_transition_parameter", transParameter, stateParent);
3009 else if(stateStr[0] ==
'C')
3012 xmlOut.addTextElementToParent(
3013 "state_transition", stateStr, stateParent);
3017 xmlOut.addTextElementToParent(
3018 "state_transition_action", *ait, stateParent);
3020 transName = theStateMachine_.getTransitionName(states[i], *ait);
3023 xmlOut.addTextElementToParent(
3024 "state_transition_name", transName, stateParent);
3026 theStateMachine_.getTransitionParameter(states[i], *ait);
3029 xmlOut.addTextElementToParent(
3030 "state_transition_parameter", transParameter, stateParent);
3037 ait = actionNames.begin();
3040 for(; it != trans.end() && ait != actionNames.end(); ++it, ++ait)
3044 stateStr[0] = it->second;
3046 if(stateStr[0] ==
'R')
3048 else if(stateStr[0] ==
'C')
3051 xmlOut.addTextElementToParent(
3052 "state_transition", stateStr, stateParent);
3056 xmlOut.addTextElementToParent(
3057 "state_transition_action", *ait, stateParent);
3059 transName = theStateMachine_.getTransitionName(states[i], *ait);
3062 xmlOut.addTextElementToParent(
3063 "state_transition_name", transName, stateParent);
3065 theStateMachine_.getTransitionParameter(states[i], *ait);
3068 xmlOut.addTextElementToParent(
3069 "state_transition_parameter", transParameter, stateParent);
3073 else if(requestType ==
"getStateMachineNames")
3077 CorePropertySupervisorBase::theConfigurationManager_
3078 ->getSupervisorTableNode(supervisorContextUID_,
3079 supervisorApplicationUID_);
3084 configLinkNode.getNode(
"LinkToStateMachineTable").getChildren();
3085 for(
const auto& fsmNode : fsmNodes)
3086 xmlOut.addTextElementToData(
"stateMachineName", fsmNode.first);
3090 __COUT__ <<
"Caught exception, assuming no valid FSM names." << __E__;
3091 xmlOut.addTextElementToData(
"stateMachineName",
"");
3094 else if(requestType ==
"getIterationPlanStatus")
3097 theIterator_.handleCommandRequest(xmlOut, requestType,
"");
3099 else if(requestType ==
"getCurrentState")
3101 xmlOut.addTextElementToData(
"current_state",
3102 theStateMachine_.getCurrentStateName());
3103 xmlOut.addTextElementToData(
"in_transition",
3104 theStateMachine_.isInTransition() ?
"1" :
"0");
3105 if(theStateMachine_.isInTransition())
3106 xmlOut.addTextElementToData(
3107 "transition_progress",
3108 RunControlStateMachine::theProgressBar_.readPercentageString());
3110 xmlOut.addTextElementToData(
"transition_progress",
"100");
3113 sprintf(tmp,
"%lu", theStateMachine_.getTimeInState());
3114 xmlOut.addTextElementToData(
"time_in_state", tmp);
3121 std::string fsmName = CgiDataUtilities::getData(cgiIn,
"fsmName");
3130 if(!theStateMachine_.isInTransition())
3132 std::string stateMachineRunAlias =
"Run";
3136 CorePropertySupervisorBase::theConfigurationManager_
3137 ->getSupervisorTableNode(supervisorContextUID_,
3138 supervisorApplicationUID_);
3140 if(!configLinkNode.isDisconnected())
3145 configLinkNode.getNode(
"LinkToStateMachineTable");
3146 if(!fsmLinkNode.isDisconnected())
3147 stateMachineRunAlias =
3148 fsmLinkNode.getNode(fsmName +
"/RunDisplayAlias")
3149 .getValue<std::string>();
3153 catch(std::runtime_error& e)
3162 __COUT_ERR__ <<
"Unknown error. Should never happen." << __E__;
3164 __COUT_INFO__ <<
"No state machine Run alias. Ignoring and "
3165 "assuming alias of '"
3166 << stateMachineRunAlias <<
".'" << __E__;
3175 xmlOut.addTextElementToData(
"stateMachineRunAlias", stateMachineRunAlias);
3179 if(theStateMachine_.getCurrentStateName() ==
"Running" ||
3180 theStateMachine_.getCurrentStateName() ==
"Paused")
3183 "Current %s Number: %u",
3184 stateMachineRunAlias.c_str(),
3185 getNextRunNumber(activeStateMachineName_) - 1);
3187 if(RunControlStateMachine::asyncSoftFailureReceived_)
3191 xmlOut.addTextElementToData(
3192 "soft_error", RunControlStateMachine::getErrorMessage());
3197 "Next %s Number: %u",
3198 stateMachineRunAlias.c_str(),
3199 getNextRunNumber(fsmName));
3200 xmlOut.addTextElementToData(
"run_number", tmp);
3203 else if(requestType ==
"cancelStateMachineTransition")
3205 __SS__ <<
"State transition was cancelled by user!" << __E__;
3206 __MCOUT__(ss.str());
3207 RunControlStateMachine::theStateMachine_.setErrorMessage(ss.str());
3208 RunControlStateMachine::asyncFailureReceived_ =
true;
3210 else if(requestType ==
"getErrorInStateMatchine")
3212 xmlOut.addTextElementToData(
"FSM_Error", theStateMachine_.getErrorMessage());
3214 else if(requestType ==
"getDesktopIcons")
3221 CorePropertySupervisorBase::theConfigurationManager_->__GET_CONFIG__(
3223 std::vector<DesktopIconTable::DesktopIcon> icons =
3224 iconTable->getAllDesktopIcons();
3226 std::string iconString =
"";
3241 std::map<std::string, WebUsers::permissionLevel_t> userPermissionLevelsMap =
3242 theWebUsers_.getPermissionsForUser(userInfo.uid_);
3243 std::map<std::string, WebUsers::permissionLevel_t>
3244 iconPermissionThresholdsMap;
3246 bool firstIcon =
true;
3247 for(
const auto& icon : icons)
3249 __COUTV__(icon.caption_);
3250 __COUTV__(icon.permissionThresholdString_);
3252 CorePropertySupervisorBase::extractPermissionsMapFromString(
3253 icon.permissionThresholdString_, iconPermissionThresholdsMap);
3255 if(!CorePropertySupervisorBase::doPermissionsGrantAccess(
3256 userPermissionLevelsMap, iconPermissionThresholdsMap))
3267 iconString += icon.caption_;
3268 iconString +=
"," + icon.alternateText_;
3270 "," + std::string(icon.enforceOneWindowInstance_ ?
"1" :
"0");
3272 "," + std::string(
"1");
3276 iconString +=
"," + icon.imageURL_;
3277 iconString +=
"," + icon.windowContentURL_;
3278 iconString +=
"," + icon.folderPath_;
3280 __COUTV__(iconString);
3282 xmlOut.addTextElementToData(
"iconList", iconString);
3284 else if(requestType ==
"gatewayLaunchOTS" || requestType ==
"gatewayLaunchWiz")
3288 __COUT_WARN__ << requestType <<
" requestType received! " << __E__;
3289 __MOUT_WARN__ << requestType <<
" requestType received! " << __E__;
3292 theWebUsers_.saveActiveSessions();
3296 if(requestType ==
"gatewayLaunchOTS")
3297 GatewaySupervisor::launchStartOTSCommand(
3298 "LAUNCH_OTS", CorePropertySupervisorBase::theConfigurationManager_);
3299 else if(requestType ==
"gatewayLaunchWiz")
3300 GatewaySupervisor::launchStartOTSCommand(
3301 "LAUNCH_WIZ", CorePropertySupervisorBase::theConfigurationManager_);
3303 else if(requestType ==
"resetUserTooltips")
3305 WebUsers::resetAllUserTooltips(theWebUsers_.getUsersUsername(userInfo.uid_));
3309 __SS__ <<
"requestType Request, " << requestType <<
", not recognized."
3314 catch(
const std::runtime_error& e)
3316 __SS__ <<
"An error was encountered handling requestType '" << requestType
3317 <<
"':" << e.what() << __E__;
3318 __COUT__ <<
"\n" << ss.str();
3319 xmlOut.addTextElementToData(
"Error", ss.str());
3323 __SS__ <<
"An unknown error was encountered handling requestType '" << requestType
3325 <<
"Please check the printouts to debug." << __E__;
3326 __COUT__ <<
"\n" << ss.str();
3327 xmlOut.addTextElementToData(
"Error", ss.str());
3331 xmlOut.outputXmlDocument(
3332 (std::ostringstream*)out,
3343 void GatewaySupervisor::launchStartOTSCommand(
const std::string& command,
3346 __COUT__ <<
"launch StartOTS Command = " << command << __E__;
3347 __COUT__ <<
"Extracting target context hostnames... " << __E__;
3349 std::vector<std::string> hostnames;
3356 auto contexts = contextTable->getContexts();
3358 for(
const auto& context : contexts)
3360 if(!context.status_)
3365 for(i = 0; i < context.address_.size(); ++i)
3366 if(context.address_[i] ==
'/')
3368 hostnames.push_back(context.address_.substr(j));
3369 __COUT__ <<
"StartOTS.sh hostname = " << hostnames.back() << __E__;
3374 __SS__ <<
"\nRelaunch of otsdaq interrupted! "
3375 <<
"The Configuration Manager could not be initialized." << __E__;
3380 for(
const auto& hostname : hostnames)
3382 std::string fn = (std::string(__ENV__(
"SERVICE_DATA_PATH")) +
3383 "/StartOTS_action_" + hostname +
".cmd");
3384 FILE* fp = fopen(fn.c_str(),
"w");
3387 fprintf(fp, command.c_str());
3392 __SS__ <<
"Unable to open command file: " << fn << __E__;
3400 for(
const auto& hostname : hostnames)
3402 std::string fn = (std::string(__ENV__(
"SERVICE_DATA_PATH")) +
3403 "/StartOTS_action_" + hostname +
".cmd");
3404 FILE* fp = fopen(fn.c_str(),
"r");
3408 fgets(line, 100, fp);
3411 if(strcmp(line, command.c_str()) == 0)
3413 __SS__ <<
"The command looks to have been ignored by " << hostname
3414 <<
". Is StartOTS.sh still running on that node?" << __E__;
3421 __SS__ <<
"Unable to open command file for verification: " << fn << __E__;
3430 xoap::MessageReference GatewaySupervisor::supervisorCookieCheck(
3431 xoap::MessageReference message)
3438 parameters.addParameter(
"CookieCode");
3439 parameters.addParameter(
"RefreshOption");
3440 parameters.addParameter(
"IPAddress");
3441 SOAPUtilities::receive(message, parameters);
3442 std::string cookieCode = parameters.getValue(
"CookieCode");
3443 std::string refreshOption =
3444 parameters.getValue(
"RefreshOption");
3446 std::string ipAddress =
3447 parameters.getValue(
"IPAddress");
3453 std::map<std::string , WebUsers::permissionLevel_t>
3454 userGroupPermissionsMap;
3455 std::string userWithLock =
"";
3456 uint64_t activeSessionIndex, uid;
3457 theWebUsers_.cookieCodeIsActiveForRequest(cookieCode,
3458 &userGroupPermissionsMap,
3461 refreshOption ==
"1",
3463 &activeSessionIndex);
3469 retParameters.addParameter(
"CookieCode", cookieCode);
3470 retParameters.addParameter(
3471 "Permissions", StringMacros::mapToString(userGroupPermissionsMap).c_str());
3472 retParameters.addParameter(
"UserWithLock", userWithLock);
3473 retParameters.addParameter(
"Username", theWebUsers_.getUsersUsername(uid));
3474 retParameters.addParameter(
"DisplayName", theWebUsers_.getUsersDisplayName(uid));
3475 sprintf(tmpStringForConversions_,
"%lu", activeSessionIndex);
3476 retParameters.addParameter(
"ActiveSessionIndex", tmpStringForConversions_);
3480 return SOAPUtilities::makeSOAPMessageReference(
"CookieResponse", retParameters);
3486 xoap::MessageReference GatewaySupervisor::supervisorGetActiveUsers(
3487 xoap::MessageReference message)
3492 SOAPParameters parameters(
"UserList", theWebUsers_.getActiveUsersString());
3493 return SOAPUtilities::makeSOAPMessageReference(
"ActiveUserResponse", parameters);
3500 xoap::MessageReference GatewaySupervisor::supervisorSystemMessage(
3501 xoap::MessageReference message)
3505 parameters.addParameter(
"ToUser");
3506 parameters.addParameter(
"Message");
3507 SOAPUtilities::receive(message, parameters);
3509 __COUT__ <<
"toUser: " << parameters.getValue(
"ToUser").substr(0, 10)
3510 <<
", message: " << parameters.getValue(
"Message").substr(0, 10) << __E__;
3512 theSystemMessenger_.addSystemMessage(parameters.getValue(
"ToUser"),
3513 parameters.getValue(
"Message"));
3514 return SOAPUtilities::makeSOAPMessageReference(
"SystemMessageResponse");
3521 xoap::MessageReference GatewaySupervisor::supervisorSystemLogbookEntry(
3522 xoap::MessageReference message)
3526 parameters.addParameter(
"EntryText");
3527 SOAPUtilities::receive(message, parameters);
3529 __COUT__ <<
"EntryText: " << parameters.getValue(
"EntryText").substr(0, 10) << __E__;
3531 makeSystemLogbookEntry(parameters.getValue(
"EntryText"));
3533 return SOAPUtilities::makeSOAPMessageReference(
"SystemLogbookResponse");
3541 xoap::MessageReference GatewaySupervisor::supervisorLastConfigGroupRequest(
3542 xoap::MessageReference message)
3546 parameters.addParameter(
"ActionOfLastGroup");
3547 SOAPUtilities::receive(message, parameters);
3549 return GatewaySupervisor::lastConfigGroupRequestHandler(parameters);
3558 xoap::MessageReference GatewaySupervisor::lastConfigGroupRequestHandler(
3561 std::string action = parameters.getValue(
"ActionOfLastGroup");
3562 __COUT__ <<
"ActionOfLastGroup: " << action.substr(0, 10) << __E__;
3564 std::string fileName =
"";
3565 if(action ==
"Configured")
3566 fileName = FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE;
3567 else if(action ==
"Started")
3568 fileName = FSM_LAST_STARTED_GROUP_ALIAS_FILE;
3571 __COUT_ERR__ <<
"Invalid last group action requested." << __E__;
3572 return SOAPUtilities::makeSOAPMessageReference(
"LastConfigGroupResponseFailure");
3574 std::string timeString;
3576 loadGroupNameAndKey(fileName, timeString);
3580 retParameters.addParameter(
"GroupName", theGroup.first);
3581 retParameters.addParameter(
"GroupKey", theGroup.second.toString());
3582 retParameters.addParameter(
"GroupAction", action);
3583 retParameters.addParameter(
"GroupActionTime", timeString);
3585 return SOAPUtilities::makeSOAPMessageReference(
"LastConfigGroupResponse",
3596 unsigned int GatewaySupervisor::getNextRunNumber(
const std::string& fsmNameIn)
3598 std::string runNumberFileName = RUN_NUMBER_PATH +
"/";
3599 std::string fsmName = fsmNameIn ==
"" ? activeStateMachineName_ : fsmNameIn;
3601 for(
unsigned int i = 0; i < fsmName.size(); ++i)
3602 if((fsmName[i] >=
'a' && fsmName[i] <=
'z') ||
3603 (fsmName[i] >=
'A' && fsmName[i] <=
'Z') ||
3604 (fsmName[i] >=
'0' && fsmName[i] <=
'9'))
3605 runNumberFileName += fsmName[i];
3606 runNumberFileName += RUN_NUMBER_FILE_NAME;
3609 std::ifstream runNumberFile(runNumberFileName.c_str());
3610 if(!runNumberFile.is_open())
3612 __COUT__ <<
"Can't open file: " << runNumberFileName << __E__;
3614 __COUT__ <<
"Creating file and setting Run Number to 1: " << runNumberFileName
3616 FILE* fp = fopen(runNumberFileName.c_str(),
"w");
3620 runNumberFile.open(runNumberFileName.c_str());
3621 if(!runNumberFile.is_open())
3623 __SS__ <<
"Error. Can't create file: " << runNumberFileName << __E__;
3624 __COUT_ERR__ << ss.str();
3628 std::string runNumberString;
3629 runNumberFile >> runNumberString;
3630 runNumberFile.close();
3631 return atoi(runNumberString.c_str());
3635 bool GatewaySupervisor::setNextRunNumber(
unsigned int runNumber,
3636 const std::string& fsmNameIn)
3638 std::string runNumberFileName = RUN_NUMBER_PATH +
"/";
3639 std::string fsmName = fsmNameIn ==
"" ? activeStateMachineName_ : fsmNameIn;
3641 for(
unsigned int i = 0; i < fsmName.size(); ++i)
3642 if((fsmName[i] >=
'a' && fsmName[i] <=
'z') ||
3643 (fsmName[i] >=
'A' && fsmName[i] <=
'Z') ||
3644 (fsmName[i] >=
'0' && fsmName[i] <=
'9'))
3645 runNumberFileName += fsmName[i];
3646 runNumberFileName += RUN_NUMBER_FILE_NAME;
3647 __COUT__ <<
"runNumberFileName: " << runNumberFileName << __E__;
3649 std::ofstream runNumberFile(runNumberFileName.c_str());
3650 if(!runNumberFile.is_open())
3652 __SS__ <<
"Can't open file: " << runNumberFileName << __E__;
3653 __COUT__ << ss.str();
3656 std::stringstream runNumberStream;
3657 runNumberStream << runNumber;
3658 runNumberFile << runNumberStream.str().c_str();
3659 runNumberFile.close();
3670 GatewaySupervisor::loadGroupNameAndKey(
const std::string& fileName,
3671 std::string& returnedTimeString)
3673 std::string fullPath = FSM_LAST_GROUP_ALIAS_PATH +
"/" + fileName;
3675 FILE* groupFile = fopen(fullPath.c_str(),
"r");
3678 __COUT__ <<
"Can't open file: " << fullPath << __E__;
3680 __COUT__ <<
"Returning empty groupName and key -1" << __E__;
3682 return std::pair<std::string ,
TableGroupKey>(
"", TableGroupKey());
3689 fgets(line, 500, groupFile);
3690 theGroup.first = line;
3692 fgets(line, 500, groupFile);
3694 sscanf(line,
"%d", &key);
3695 theGroup.second = key;
3697 fgets(line, 500, groupFile);
3699 sscanf(line,
"%ld", ×tamp);
3703 returnedTimeString = StringMacros::getTimestampString(timestamp);
3706 __COUT__ <<
"theGroup.first= " << theGroup.first
3707 <<
" theGroup.second= " << theGroup.second << __E__;
3713 void GatewaySupervisor::saveGroupNameAndKey(
3714 const std::pair<std::string /*group name*/, TableGroupKey>& theGroup,
3715 const std::string& fileName)
3717 std::string fullPath = FSM_LAST_GROUP_ALIAS_PATH +
"/" + fileName;
3719 std::ofstream groupFile(fullPath.c_str());
3720 if(!groupFile.is_open())
3722 __SS__ <<
"Error. Can't open file: " << fullPath << __E__;
3723 __COUT_ERR__ <<
"\n" << ss.str();
3726 std::stringstream outss;
3727 outss << theGroup.first <<
"\n" << theGroup.second <<
"\n" << time(0);
3728 groupFile << outss.str().c_str();