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(getenv("SERVICE_DATA_PATH")) + "/RunNumber/"
37 #define RUN_NUMBER_FILE_NAME "NextRunNumber.txt"
38 #define FSM_LAST_GROUP_ALIAS_PATH \
39 std::string(getenv("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(getenv(
"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, theConfigurationTableGroup_.second,
true);
1279 tmpCfgMgr.activateTableGroup(theConfigurationTableGroup_.first,
1280 theConfigurationTableGroup_.second);
1284 __SS__ <<
"\nTransition to Configuring interrupted! System Alias " << systemAlias
1285 <<
" was translated to " << theConfigurationTableGroup_.first <<
" ("
1286 << theConfigurationTableGroup_.second
1287 <<
") but could not be loaded and initialized." << __E__;
1288 ss <<
"\n\nTo debug this problem, try activating this group in the Configuration "
1290 <<
" and detailed errors will be shown." << __E__;
1291 __COUT_ERR__ <<
"\n" << ss.str();
1292 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1299 CorePropertySupervisorBase::theConfigurationManager_->getSupervisorTableNode(
1300 supervisorContextUID_, supervisorApplicationUID_);
1301 if(!configLinkNode.isDisconnected())
1305 bool dumpConfiguration =
true;
1306 std::string dumpFilePath, dumpFileRadix, dumpFormat;
1310 configLinkNode.getNode(
"LinkToStateMachineTable")
1311 .getNode(activeStateMachineName_);
1314 .getNode(
"EnableConfigurationDumpOnConfigureTransition")
1317 fsmLinkNode.getNode(
"ConfigurationDumpOnConfigureFilePath")
1318 .getValue<std::string>();
1320 fsmLinkNode.getNode(
"ConfigurationDumpOnConfigureFileRadix")
1321 .getValue<std::string>();
1322 dumpFormat = fsmLinkNode.getNode(
"ConfigurationDumpOnConfigureFormat")
1323 .getValue<std::string>();
1325 catch(std::runtime_error& e)
1327 __COUT_INFO__ <<
"FSM configuration dump Link disconnected." << __E__;
1328 dumpConfiguration =
false;
1331 if(dumpConfiguration)
1334 CorePropertySupervisorBase::theConfigurationManager_
1335 ->dumpActiveConfiguration(dumpFilePath +
"/" + dumpFileRadix +
1336 "_" + std::to_string(time(0)) +
1341 catch(std::runtime_error& e)
1343 __SS__ <<
"\nTransition to Configuring interrupted! There was an error "
1345 <<
"during the configuration dump attempt:\n\n " << e.what()
1347 __COUT_ERR__ <<
"\n" << ss.str();
1348 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1353 __SS__ <<
"\nTransition to Configuring interrupted! There was an error "
1355 <<
"during the configuration dump attempt.\n\n " << __E__;
1356 __COUT_ERR__ <<
"\n" << ss.str();
1357 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1363 RunControlStateMachine::theProgressBar_.step();
1365 parameters.addParameter(
"ConfigurationTableGroupName",
1366 theConfigurationTableGroup_.first);
1367 parameters.addParameter(
"ConfigurationTableGroupKey",
1368 theConfigurationTableGroup_.second.toString());
1372 __COUT__ <<
"Initializing Macro Maker." << __E__;
1373 xoap::MessageReference message =
1374 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1377 parameters.addParameter(
"type",
"initFElist");
1378 parameters.addParameter(
"groupName", theConfigurationTableGroup_.first);
1379 parameters.addParameter(
"groupKey",
1380 theConfigurationTableGroup_.second.toString());
1381 SOAPUtilities::addParameters(message, parameters);
1383 __COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1387 SOAPMessenger::send(CorePropertySupervisorBase::allSupervisorInfo_
1388 .getAllMacroMakerTypeSupervisorInfo()
1390 ->second.getDescriptor(),
1393 __COUT__ <<
"Macro Maker init reply: " << reply << __E__;
1394 if(reply ==
"Error")
1396 __SS__ <<
"\nTransition to Configuring interrupted! There was an error "
1397 "identified initializing Macro Maker.\n\n "
1399 __COUT_ERR__ <<
"\n" << ss.str();
1400 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1408 xoap::MessageReference message = theStateMachine_.getCurrentMessage();
1409 SOAPUtilities::addParameters(message, parameters);
1410 broadcastMessage(message);
1411 RunControlStateMachine::theProgressBar_.step();
1416 saveGroupNameAndKey(theConfigurationTableGroup_,
1417 FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE);
1419 __COUT__ <<
"Done configuring." << __E__;
1420 RunControlStateMachine::theProgressBar_.complete();
1424 void GatewaySupervisor::transitionHalting(toolbox::Event::Reference e)
1426 checkForAsyncError();
1428 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1430 makeSystemLogbookEntry(
"Run halting.");
1432 broadcastMessage(theStateMachine_.getCurrentMessage());
1436 void GatewaySupervisor::transitionShuttingDown(toolbox::Event::Reference e)
1439 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1441 RunControlStateMachine::theProgressBar_.step();
1442 makeSystemLogbookEntry(
"System shutting down.");
1443 RunControlStateMachine::theProgressBar_.step();
1446 GatewaySupervisor::launchStartOTSCommand(
1447 "OTS_APP_SHUTDOWN", CorePropertySupervisorBase::theConfigurationManager_);
1448 RunControlStateMachine::theProgressBar_.step();
1452 for(
int i = 0; i < 5; ++i)
1455 RunControlStateMachine::theProgressBar_.step();
1460 void GatewaySupervisor::transitionStartingUp(toolbox::Event::Reference e)
1463 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1465 RunControlStateMachine::theProgressBar_.step();
1466 makeSystemLogbookEntry(
"System starting up.");
1467 RunControlStateMachine::theProgressBar_.step();
1470 GatewaySupervisor::launchStartOTSCommand(
1471 "OTS_APP_STARTUP", CorePropertySupervisorBase::theConfigurationManager_);
1472 RunControlStateMachine::theProgressBar_.step();
1476 for(
int i = 0; i < 10; ++i)
1479 RunControlStateMachine::theProgressBar_.step();
1484 void GatewaySupervisor::transitionInitializing(toolbox::Event::Reference e)
1487 __COUT__ << theStateMachine_.getCurrentStateName() << __E__;
1489 broadcastMessage(theStateMachine_.getCurrentMessage());
1491 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1492 __COUT__ <<
"Fsm current transition: "
1493 << theStateMachine_.getCurrentTransitionName(e->type()) << __E__;
1494 __COUT__ <<
"Fsm final state: "
1495 << theStateMachine_.getTransitionFinalStateName(e->type()) << __E__;
1499 void GatewaySupervisor::transitionPausing(toolbox::Event::Reference e)
1501 checkForAsyncError();
1503 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1505 makeSystemLogbookEntry(
"Run pausing.");
1508 if(RunControlStateMachine::asyncSoftFailureReceived_)
1510 __COUT_ERR__ <<
"Broadcasting pause for async SOFT error!" << __E__;
1511 broadcastMessage(SOAPUtilities::makeSOAPMessageReference(
"Pause"));
1514 broadcastMessage(theStateMachine_.getCurrentMessage());
1518 void GatewaySupervisor::transitionResuming(toolbox::Event::Reference e)
1520 if(RunControlStateMachine::asyncSoftFailureReceived_)
1523 __COUT_INFO__ <<
"Clearing async SOFT error!" << __E__;
1524 RunControlStateMachine::asyncSoftFailureReceived_ =
false;
1527 checkForAsyncError();
1529 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1531 makeSystemLogbookEntry(
"Run resuming.");
1533 broadcastMessage(theStateMachine_.getCurrentMessage());
1537 void GatewaySupervisor::transitionStarting(toolbox::Event::Reference e)
1539 if(RunControlStateMachine::asyncSoftFailureReceived_)
1542 __COUT_INFO__ <<
"Clearing async SOFT error!" << __E__;
1543 RunControlStateMachine::asyncSoftFailureReceived_ =
false;
1546 checkForAsyncError();
1548 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1551 SOAPUtilities::receive(theStateMachine_.getCurrentMessage(), parameters);
1553 std::string runNumber = parameters.getValue(
"RunNumber");
1554 __COUTV__(runNumber);
1559 CorePropertySupervisorBase::theConfigurationManager_->getSupervisorTableNode(
1560 supervisorContextUID_, supervisorApplicationUID_);
1561 if(!configLinkNode.isDisconnected())
1565 bool dumpConfiguration =
true;
1566 std::string dumpFilePath, dumpFileRadix, dumpFormat;
1570 configLinkNode.getNode(
"LinkToStateMachineTable")
1571 .getNode(activeStateMachineName_);
1573 fsmLinkNode.getNode(
"EnableConfigurationDumpOnRunTransition")
1575 dumpFilePath = fsmLinkNode.getNode(
"ConfigurationDumpOnRunFilePath")
1576 .getValue<std::string>();
1577 dumpFileRadix = fsmLinkNode.getNode(
"ConfigurationDumpOnRunFileRadix")
1578 .getValue<std::string>();
1579 dumpFormat = fsmLinkNode.getNode(
"ConfigurationDumpOnRunFormat")
1580 .getValue<std::string>();
1582 catch(std::runtime_error& e)
1584 __COUT_INFO__ <<
"FSM configuration dump Link disconnected." << __E__;
1585 dumpConfiguration =
false;
1588 if(dumpConfiguration)
1591 CorePropertySupervisorBase::theConfigurationManager_
1592 ->dumpActiveConfiguration(dumpFilePath +
"/" + dumpFileRadix +
1593 "_Run" + runNumber +
"_" +
1594 std::to_string(time(0)) +
".dump",
1598 catch(std::runtime_error& e)
1600 __SS__ <<
"\nTransition to Running interrupted! There was an error "
1602 <<
"during the configuration dump attempt:\n\n " << e.what()
1604 __COUT_ERR__ <<
"\n" << ss.str();
1605 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1610 __SS__ <<
"\nTransition to Running interrupted! There was an error "
1612 <<
"during the configuration dump attempt.\n\n " << __E__;
1613 __COUT_ERR__ <<
"\n" << ss.str();
1614 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1620 makeSystemLogbookEntry(
"Run " + runNumber +
" starting.");
1622 broadcastMessage(theStateMachine_.getCurrentMessage());
1625 saveGroupNameAndKey(theConfigurationTableGroup_, FSM_LAST_STARTED_GROUP_ALIAS_FILE);
1629 void GatewaySupervisor::transitionStopping(toolbox::Event::Reference e)
1631 checkForAsyncError();
1633 __COUT__ <<
"Fsm current state: " << theStateMachine_.getCurrentStateName() << __E__;
1635 makeSystemLogbookEntry(
"Run stopping.");
1637 broadcastMessage(theStateMachine_.getCurrentMessage());
1650 bool GatewaySupervisor::handleBroadcastMessageTarget(
const SupervisorInfo& appInfo,
1651 xoap::MessageReference message,
1652 const std::string& command,
1653 const unsigned int& iteration,
1655 unsigned int threadIndex)
1657 unsigned int subIteration = 0;
1658 bool subIterationsDone =
false;
1659 bool iterationsDone =
true;
1661 while(!subIterationsDone)
1663 subIterationsDone =
true;
1664 RunControlStateMachine::theProgressBar_.step();
1670 parameters.addParameter(
"subIterationIndex", subIteration);
1671 SOAPUtilities::addParameters(message, parameters);
1674 if(iteration || subIteration)
1675 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1676 <<
"Adding iteration parameters " << iteration <<
"." << subIteration
1679 RunControlStateMachine::theProgressBar_.step();
1681 if(iteration == 0 && subIteration == 0)
1683 for(
unsigned int j = 0; j < 4; ++j)
1684 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1685 <<
"Sending message to Supervisor " << appInfo.getName()
1686 <<
" [LID=" << appInfo.getId() <<
"]: " << command << __E__;
1690 if(subIteration == 0)
1692 for(
unsigned int j = 0; j < 4; ++j)
1693 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1694 <<
"Sending message to Supervisor " << appInfo.getName()
1695 <<
" [LID=" << appInfo.getId() <<
"]: " << command
1696 <<
" (iteration: " << iteration <<
")" << __E__;
1700 for(
unsigned int j = 0; j < 4; ++j)
1701 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1702 <<
"Sending message to Supervisor " << appInfo.getName()
1703 <<
" [LID=" << appInfo.getId() <<
"]: " << command
1704 <<
" (iteration: " << iteration
1705 <<
", sub-iteration: " << subIteration <<
")" << __E__;
1713 std::lock_guard<std::mutex> lock(broadcastCommandMessageIndexMutex_);
1714 parameters.addParameter(
"commandId", broadcastCommandMessageIndex_++);
1716 SOAPUtilities::addParameters(message, parameters);
1719 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1720 <<
"Sending... \t" << SOAPUtilities::translate(message) << std::endl;
1724 reply = send(appInfo.getDescriptor(), message);
1726 catch(
const xdaq::exception::Exception& e)
1729 __SS__ <<
"Error! Gateway Supervisor can NOT " << command
1730 <<
" Supervisor instance = '" << appInfo.getName()
1731 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1732 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1734 <<
"Xoap message failure. Did the target Supervisor crash? Try "
1735 "re-initializing or restarting otsdaq."
1737 __COUT_ERR__ << ss.str();
1738 __MOUT_ERR__ << ss.str();
1742 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1743 <<
"Try again.." << __E__;
1748 parameters.addParameter(
"retransmission",
"1");
1749 SOAPUtilities::addParameters(message, parameters);
1756 std::lock_guard<std::mutex> lock(
1757 broadcastCommandMessageIndexMutex_);
1758 parameters.addParameter(
"commandId",
1759 broadcastCommandMessageIndex_++);
1761 SOAPUtilities::addParameters(message, parameters);
1764 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1765 <<
"Re-Sending... " << SOAPUtilities::translate(message)
1768 reply = send(appInfo.getDescriptor(), message);
1770 catch(
const xdaq::exception::Exception& e)
1772 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1773 <<
"Second try failed.." << __E__;
1774 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1776 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1777 <<
"2nd try passed.." << __E__;
1780 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1781 <<
"Reply received = " << reply << __E__;
1783 if((reply != command +
"Done") && (reply != command +
"Response") &&
1784 (reply != command +
"Iterate") && (reply != command +
"SubIterate"))
1786 __SS__ <<
"Error! Gateway Supervisor can NOT " << command
1787 <<
" Supervisor instance = '" << appInfo.getName()
1788 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1789 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1792 __COUT_ERR__ << ss.str() << __E__;
1793 __MOUT_ERR__ << ss.str() << __E__;
1795 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1796 <<
"Getting error message..." << __E__;
1799 xoap::MessageReference errorMessage =
1800 sendWithSOAPReply(appInfo.getDescriptor(),
1801 SOAPUtilities::makeSOAPMessageReference(
1802 "StateMachineErrorMessageRequest"));
1804 parameters.addParameter(
"ErrorMessage");
1805 SOAPUtilities::receive(errorMessage, parameters);
1807 std::string error = parameters.getValue(
"ErrorMessage");
1810 std::stringstream err;
1811 err <<
"Unknown error from Supervisor instance = '"
1812 << appInfo.getName() <<
"' [LID=" << appInfo.getId()
1813 <<
"] in Context '" << appInfo.getContextName()
1814 <<
"' [URL=" << appInfo.getURL()
1815 <<
"]. If the problem persists or is repeatable, please notify "
1820 __SS__ <<
"Received error from Supervisor instance = '"
1821 << appInfo.getName() <<
"' [LID=" << appInfo.getId()
1822 <<
"] in Context '" << appInfo.getContextName()
1823 <<
"' [URL=" << appInfo.getURL()
1824 <<
"].\n\n Error Message = " << error << __E__;
1826 __COUT_ERR__ << ss.str() << __E__;
1827 __MOUT_ERR__ << ss.str() << __E__;
1829 if(command ==
"Error")
1833 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1835 catch(
const xdaq::exception::Exception& e)
1838 __SS__ <<
"Error! Gateway Supervisor failed to read error message from "
1839 "Supervisor instance = '"
1840 << appInfo.getName() <<
"' [LID=" << appInfo.getId()
1841 <<
"] in Context '" << appInfo.getContextName()
1842 <<
"' [URL=" << appInfo.getURL() <<
"].\n\n"
1843 <<
"Xoap message failure. Did the target Supervisor crash? Try "
1844 "re-initializing or restarting otsdaq."
1846 __COUT_ERR__ << ss.str();
1847 __MOUT_ERR__ << ss.str();
1848 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1851 else if(reply == command +
"Iterate")
1858 iterationsDone =
false;
1859 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1860 <<
"Supervisor instance = '" << appInfo.getName()
1861 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1862 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1863 <<
"] flagged for another iteration to " << command
1864 <<
"... (iteration: " << iteration <<
")" << __E__;
1867 else if(reply == command +
"SubIterate")
1874 subIterationsDone =
false;
1875 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1876 <<
"Supervisor instance = '" << appInfo.getName()
1877 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1878 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1879 <<
"] flagged for another sub-iteration to " << command
1880 <<
"... (iteration: " << iteration
1881 <<
", sub-iteration: " << subIteration <<
")" << __E__;
1885 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1886 <<
"Supervisor instance = '" << appInfo.getName()
1887 <<
"' [LID=" << appInfo.getId() <<
"] in Context '"
1888 << appInfo.getContextName() <<
"' [URL=" << appInfo.getURL()
1889 <<
"] was " << command <<
"'d correctly!" << __E__;
1893 __COUT__ <<
"Broadcast thread " << threadIndex <<
"\t"
1894 <<
"Completed sub-iteration: " << subIteration << __E__;
1899 return iterationsDone;
1907 void GatewaySupervisor::broadcastMessageThread(
1908 GatewaySupervisor* supervisorPtr,
1909 GatewaySupervisor::BroadcastThreadStruct* threadStruct)
1911 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1912 <<
"starting..." << __E__;
1914 while(!threadStruct->exitThread_)
1920 std::lock_guard<std::mutex> lock(threadStruct->threadMutex);
1921 if(threadStruct->workToDo_)
1923 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1924 <<
"starting work..." << __E__;
1928 if(supervisorPtr->handleBroadcastMessageTarget(
1929 threadStruct->getAppInfo(),
1930 threadStruct->getMessage(),
1931 threadStruct->getCommand(),
1932 threadStruct->getIteration(),
1933 threadStruct->getReply(),
1934 threadStruct->threadIndex_))
1935 threadStruct->getIterationsDone() =
true;
1937 catch(toolbox::fsm::exception::Exception e)
1939 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1940 <<
"going into error: " << e.what() << __E__;
1942 threadStruct->getReply() = e.what();
1943 threadStruct->error_ =
true;
1944 threadStruct->workToDo_ =
false;
1945 threadStruct->working_ =
false;
1949 if(!threadStruct->getIterationsDone())
1951 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1952 <<
"flagged for another iteration." << __E__;
1955 std::lock_guard<std::mutex> lock(
1956 supervisorPtr->broadcastIterationsDoneMutex_);
1957 supervisorPtr->broadcastIterationsDone_ =
false;
1960 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1961 <<
"done with work." << __E__;
1963 threadStruct->workToDo_ =
false;
1968 __COUT__ <<
"Broadcast thread " << threadStruct->threadIndex_ <<
"\t"
1969 <<
"exited." << __E__;
1970 threadStruct->working_ =
false;
1978 void GatewaySupervisor::broadcastMessage(xoap::MessageReference message)
1980 RunControlStateMachine::theProgressBar_.step();
1983 allSupervisorInfo_.setSupervisorStatus(
this, theStateMachine_.getCurrentStateName());
1985 std::string command = SOAPUtilities::translate(message).getCommand();
1988 broadcastIterationsDone_ =
false;
1991 std::vector<std::vector<const SupervisorInfo*>> orderedSupervisors;
1995 orderedSupervisors = allSupervisorInfo_.getOrderedSupervisorDescriptors(command);
1997 catch(
const std::runtime_error& e)
1999 __SS__ <<
"Error getting supervisor priority. Was there a change in the context?"
2000 <<
" Remember, if the context was changed, it is safest to relaunch "
2002 << e.what() << __E__;
2003 XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
2006 RunControlStateMachine::theProgressBar_.step();
2010 GatewaySupervisor::BroadcastMessageIterationsDoneStruct supervisorIterationsDone;
2013 for(
const auto& vectorAtPriority : orderedSupervisors)
2014 supervisorIterationsDone.push(
2015 vectorAtPriority.size());
2019 unsigned int iteration = 0;
2020 unsigned int subIteration;
2025 xoap::MessageReference originalMessage =
2026 SOAPUtilities::makeSOAPMessageReference(SOAPUtilities::translate(message));
2028 __COUT__ <<
"=========> Broadcasting state machine command = " << command << __E__;
2030 unsigned int numberOfThreads = 1;
2034 numberOfThreads = CorePropertySupervisorBase::getSupervisorTableNode()
2035 .getNode(
"NumberOfStateMachineBroadcastThreads")
2036 .getValue<
unsigned int>();
2041 __COUT__ <<
"Number of threads not in configuration, so defaulting to "
2042 << numberOfThreads << __E__;
2047 if(numberOfThreads == 1)
2048 numberOfThreads = 0;
2050 __COUTV__(numberOfThreads);
2052 std::vector<GatewaySupervisor::BroadcastThreadStruct> broadcastThreadStructs(
2057 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2059 broadcastThreadStructs[i].threadIndex_ = i;
2062 [](GatewaySupervisor* supervisorPtr,
2063 GatewaySupervisor::BroadcastThreadStruct* threadStruct) {
2064 GatewaySupervisor::broadcastMessageThread(supervisorPtr, threadStruct);
2067 &broadcastThreadStructs[i])
2071 RunControlStateMachine::theProgressBar_.step();
2079 broadcastIterationsDone_ =
true;
2082 __COUT__ <<
"Starting iteration: " << iteration << __E__;
2084 for(
unsigned int i = 0; i < supervisorIterationsDone.size(); ++i)
2086 for(
unsigned int j = 0; j < supervisorIterationsDone.size(i); ++j)
2088 checkForAsyncError();
2090 if(supervisorIterationsDone[i][j])
2096 message = SOAPUtilities::makeSOAPMessageReference(
2097 SOAPUtilities::translate(originalMessage));
2104 parameters.addParameter(
"iterationIndex", iteration);
2105 SOAPUtilities::addParameters(message, parameters);
2111 assignedJob =
false;
2114 for(
unsigned int k = 0; k < numberOfThreads; ++k)
2116 if(!broadcastThreadStructs[k].workToDo_)
2120 __COUT__ <<
"Giving work to thread " << k << __E__;
2122 std::lock_guard<std::mutex> lock(
2123 broadcastThreadStructs[k].threadMutex);
2124 broadcastThreadStructs[k].setMessage(
2129 supervisorIterationsDone[i][j]);
2137 __COUT__ <<
"No free broadcast threads, "
2138 <<
"waiting for an available thread..." << __E__;
2139 usleep(100 * 1000 );
2141 }
while(!assignedJob);
2145 if(handleBroadcastMessageTarget(
2146 appInfo, message, command, iteration, reply))
2147 supervisorIterationsDone[i][j] =
true;
2149 broadcastIterationsDone_ =
false;
2159 <<
"Done with priority level. Waiting for threads to finish..."
2165 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2166 if(broadcastThreadStructs[i].workToDo_)
2169 __COUT__ <<
"Still waiting on thread " << i <<
"..."
2171 usleep(100 * 1000 );
2174 else if(broadcastThreadStructs[i].error_)
2176 __COUT__ <<
"Found thread in error! Throwing state "
2178 << broadcastThreadStructs[i].getReply() << __E__;
2179 XCEPT_RAISE(toolbox::fsm::exception::Exception,
2180 broadcastThreadStructs[i].getReply());
2183 __COUT__ <<
"All threads done with priority level work." << __E__;
2194 if(iteration || !broadcastIterationsDone_)
2195 __COUT__ <<
"Completed iteration: " << iteration << __E__;
2198 }
while(!broadcastIterationsDone_);
2200 RunControlStateMachine::theProgressBar_.step();
2204 __COUT__ <<
"Exception caught, exiting broadcast threads..." << __E__;
2211 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2212 broadcastThreadStructs[i].exitThread_ =
true;
2213 usleep(100 * 1000 );
2220 __COUT__ <<
"All transitions completed. Wrapping up, exiting broadcast threads..."
2229 for(
unsigned int i = 0; i < numberOfThreads; ++i)
2230 broadcastThreadStructs[i].exitThread_ =
true;
2231 usleep(100 * 1000 );
2234 __COUT__ <<
"Broadcast complete." << __E__;
2238 void GatewaySupervisor::wait(
int milliseconds, std::string who)
const
2240 for(
int s = 1; s <= milliseconds; s++)
2245 __COUT__ << s <<
" msecs " << who << __E__;
2254 void GatewaySupervisor::loginRequest(xgi::Input* in, xgi::Output* out)
2256 __COUT__ <<
"Start" << __E__;
2257 cgicc::Cgicc cgi(in);
2258 std::string Command = CgiDataUtilities::getData(cgi,
"RequestType");
2259 __COUT__ <<
"*** Login RequestType = " << Command << __E__;
2268 std::vector<std::string> loggedOutUsernames;
2269 theWebUsers_.cleanupExpiredEntries(&loggedOutUsernames);
2270 for(
unsigned int i = 0; i < loggedOutUsernames.size();
2272 makeSystemLogbookEntry(loggedOutUsernames[i] +
" login timed out.");
2274 if(Command ==
"sessionId")
2283 std::string uuid = CgiDataUtilities::postData(cgi,
"uuid");
2285 std::string sid = theWebUsers_.createNewLoginSession(
2286 uuid, cgi.getEnvironment().getRemoteAddr() );
2292 else if(Command ==
"checkCookie")
2296 std::string jumbledUser;
2297 std::string cookieCode;
2308 uuid = CgiDataUtilities::postData(cgi,
"uuid");
2309 jumbledUser = CgiDataUtilities::postData(cgi,
"ju");
2310 cookieCode = CgiDataUtilities::postData(cgi,
"cc");
2318 uid = theWebUsers_.isCookieCodeActiveForLogin(
2323 if(uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
2325 __COUT__ <<
"cookieCode invalid" << __E__;
2330 __COUT__ <<
"cookieCode is good." << __E__;
2335 theWebUsers_.insertSettingsForUser(uid, &xmldoc);
2337 xmldoc.outputXmlDocument((std::ostringstream*)out);
2339 else if(Command ==
"login")
2350 std::string uuid = CgiDataUtilities::postData(cgi,
"uuid");
2351 std::string newAccountCode = CgiDataUtilities::postData(cgi,
"nac");
2352 std::string jumbledUser = CgiDataUtilities::postData(cgi,
"ju");
2353 std::string jumbledPw = CgiDataUtilities::postData(cgi,
"jp");
2360 uint64_t uid = theWebUsers_.attemptActiveSession(
2365 cgi.getEnvironment()
2368 if(uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
2370 __COUT__ <<
"Login invalid." << __E__;
2372 if(newAccountCode !=
"1")
2373 newAccountCode =
"0";
2376 makeSystemLogbookEntry(theWebUsers_.getUsersUsername(uid) +
" logged in.");
2382 theWebUsers_.insertSettingsForUser(uid, &xmldoc);
2386 if(uid != theWebUsers_.NOT_FOUND_IN_DATABASE)
2388 uint64_t asCnt = theWebUsers_.getActiveSessionCountForUser(uid) -
2391 sprintf(asStr,
"%lu", asCnt);
2392 xmldoc.addTextElementToData(
"user_active_session_count", asStr);
2395 xmldoc.outputXmlDocument((std::ostringstream*)out);
2397 else if(Command ==
"cert")
2408 std::string uuid = CgiDataUtilities::postData(cgi,
"uuid");
2409 std::string jumbledEmail =
2410 cgicc::form_urldecode(CgiDataUtilities::getData(cgi,
"httpsUser"));
2411 std::string username =
"";
2412 std::string cookieCode =
"";
2418 uint64_t uid = theWebUsers_.attemptActiveSessionWithCert(
2423 cgi.getEnvironment()
2426 if(uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
2428 __COUT__ <<
"cookieCode invalid" << __E__;
2430 if(cookieCode !=
"1")
2434 makeSystemLogbookEntry(theWebUsers_.getUsersUsername(uid) +
" logged in.");
2440 theWebUsers_.insertSettingsForUser(uid, &xmldoc);
2444 if(uid != theWebUsers_.NOT_FOUND_IN_DATABASE)
2446 uint64_t asCnt = theWebUsers_.getActiveSessionCountForUser(uid) -
2449 sprintf(asStr,
"%lu", asCnt);
2450 xmldoc.addTextElementToData(
"user_active_session_count", asStr);
2453 xmldoc.outputXmlDocument((std::ostringstream*)out);
2455 else if(Command ==
"logout")
2457 std::string cookieCode = CgiDataUtilities::postData(cgi,
"CookieCode");
2458 std::string logoutOthers = CgiDataUtilities::postData(cgi,
"LogoutOthers");
2464 if(theWebUsers_.cookieCodeLogout(cookieCode,
2465 logoutOthers ==
"1",
2467 cgi.getEnvironment().getRemoteAddr()) !=
2468 theWebUsers_.NOT_FOUND_IN_DATABASE)
2472 if(!theWebUsers_.isUserIdActive(uid))
2473 makeSystemLogbookEntry(theWebUsers_.getUsersUsername(uid) +
2479 __COUT__ <<
"Invalid Command" << __E__;
2483 __COUT__ <<
"Done" << __E__;
2487 void GatewaySupervisor::tooltipRequest(xgi::Input* in, xgi::Output* out)
2489 __COUT__ <<
"Start" << __E__;
2490 cgicc::Cgicc cgi(in);
2492 std::string Command = CgiDataUtilities::getData(cgi,
"RequestType");
2493 __COUT__ <<
"Tooltip RequestType = " << Command << __E__;
2500 std::string cookieCode = CgiDataUtilities::postData(cgi,
"CookieCode");
2503 if(!theWebUsers_.cookieCodeIsActiveForRequest(
2504 cookieCode, 0 , &uid,
"0" ,
false ))
2514 if(Command ==
"check")
2516 WebUsers::tooltipCheckForUsername(theWebUsers_.getUsersUsername(uid),
2518 CgiDataUtilities::getData(cgi,
"srcFile"),
2519 CgiDataUtilities::getData(cgi,
"srcFunc"),
2520 CgiDataUtilities::getData(cgi,
"srcId"));
2522 else if(Command ==
"setNeverShow")
2524 WebUsers::tooltipSetNeverShowForUsername(
2525 theWebUsers_.getUsersUsername(uid),
2527 CgiDataUtilities::getData(cgi,
"srcFile"),
2528 CgiDataUtilities::getData(cgi,
"srcFunc"),
2529 CgiDataUtilities::getData(cgi,
"srcId"),
2530 CgiDataUtilities::getData(cgi,
"doNeverShow") ==
"1" ?
true :
false,
2531 CgiDataUtilities::getData(cgi,
"temporarySilence") ==
"1" ?
true :
false);
2534 __COUT__ <<
"Command Request, " << Command <<
", not recognized." << __E__;
2536 xmldoc.outputXmlDocument((std::ostringstream*)out,
false,
true);
2538 __COUT__ <<
"Done" << __E__;
2545 void GatewaySupervisor::setSupervisorPropertyDefaults()
2547 CorePropertySupervisorBase::setSupervisorProperty(
2548 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
2549 std::string() +
"*=1 | gatewayLaunchOTS=-1 | gatewayLaunchWiz=-1");
2555 void GatewaySupervisor::forceSupervisorPropertyValues()
2561 CorePropertySupervisorBase::setSupervisorProperty(
2562 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
2563 "getSystemMessages | getCurrentState | getIterationPlanStatus");
2564 CorePropertySupervisorBase::setSupervisorProperty(
2565 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.RequireUserLockRequestTypes,
2566 "gatewayLaunchOTS | gatewayLaunchWiz");
2572 void GatewaySupervisor::request(xgi::Input* in, xgi::Output* out)
2580 __COUT__ <<
"Waiting for FSM access" << __E__;
2581 std::lock_guard<std::mutex> lock(stateMachineAccessMutex_);
2583 __COUT__ <<
"Have FSM access" << __E__;
2585 cgicc::Cgicc cgiIn(in);
2587 std::string requestType = CgiDataUtilities::getData(cgiIn,
"RequestType");
2591 CgiDataUtilities::postData(cgiIn,
"CookieCode"));
2593 CorePropertySupervisorBase::getRequestUserInfo(userInfo);
2595 if(!theWebUsers_.xmlRequestOnGateway(cgiIn, out, &xmlOut, userInfo))
2622 if(requestType ==
"getSettings")
2624 std::string accounts = CgiDataUtilities::getData(cgiIn,
"accounts");
2626 __COUT__ <<
"Get Settings Request" << __E__;
2627 __COUT__ <<
"accounts = " << accounts << __E__;
2628 theWebUsers_.insertSettingsForUser(userInfo.uid_, &xmlOut, accounts ==
"1");
2630 else if(requestType ==
"setSettings")
2632 std::string bgcolor = CgiDataUtilities::postData(cgiIn,
"bgcolor");
2633 std::string dbcolor = CgiDataUtilities::postData(cgiIn,
"dbcolor");
2634 std::string wincolor = CgiDataUtilities::postData(cgiIn,
"wincolor");
2635 std::string layout = CgiDataUtilities::postData(cgiIn,
"layout");
2636 std::string syslayout = CgiDataUtilities::postData(cgiIn,
"syslayout");
2638 __COUT__ <<
"Set Settings Request" << __E__;
2639 __COUT__ <<
"bgcolor = " << bgcolor << __E__;
2640 __COUT__ <<
"dbcolor = " << dbcolor << __E__;
2641 __COUT__ <<
"wincolor = " << wincolor << __E__;
2642 __COUT__ <<
"layout = " << layout << __E__;
2643 __COUT__ <<
"syslayout = " << syslayout << __E__;
2645 theWebUsers_.changeSettingsForUser(
2646 userInfo.uid_, bgcolor, dbcolor, wincolor, layout, syslayout);
2647 theWebUsers_.insertSettingsForUser(
2648 userInfo.uid_, &xmlOut,
true);
2650 else if(requestType ==
"accountSettings")
2652 std::string type = CgiDataUtilities::postData(
2656 if(type ==
"updateAccount")
2658 else if(type ==
"createAccount")
2660 else if(type ==
"deleteAccount")
2663 std::string username = CgiDataUtilities::postData(cgiIn,
"username");
2664 std::string displayname = CgiDataUtilities::postData(cgiIn,
"displayname");
2665 std::string email = CgiDataUtilities::postData(cgiIn,
"useremail");
2666 std::string permissions = CgiDataUtilities::postData(cgiIn,
"permissions");
2667 std::string accounts = CgiDataUtilities::getData(cgiIn,
"accounts");
2669 __COUT__ <<
"accountSettings Request" << __E__;
2670 __COUT__ <<
"type = " << type <<
" - " << type_int << __E__;
2671 __COUT__ <<
"username = " << username << __E__;
2672 __COUT__ <<
"useremail = " << email << __E__;
2673 __COUT__ <<
"displayname = " << displayname << __E__;
2674 __COUT__ <<
"permissions = " << permissions << __E__;
2676 theWebUsers_.modifyAccountSettings(
2677 userInfo.uid_, type_int, username, displayname, email, permissions);
2679 __COUT__ <<
"accounts = " << accounts << __E__;
2681 theWebUsers_.insertSettingsForUser(userInfo.uid_, &xmlOut, accounts ==
"1");
2683 else if(requestType ==
"stateMatchinePreferences")
2685 std::string set = CgiDataUtilities::getData(cgiIn,
"set");
2686 const std::string DEFAULT_FSM_VIEW =
"Default_FSM_View";
2688 theWebUsers_.setGenericPreference(
2691 CgiDataUtilities::getData(cgiIn, DEFAULT_FSM_VIEW));
2693 theWebUsers_.getGenericPreference(
2694 userInfo.uid_, DEFAULT_FSM_VIEW, &xmlOut);
2696 else if(requestType ==
"getAliasList")
2698 std::string username = theWebUsers_.getUsersUsername(userInfo.uid_);
2699 std::string fsmName = CgiDataUtilities::getData(cgiIn,
"fsmName");
2700 __COUT__ <<
"fsmName = " << fsmName << __E__;
2702 std::string stateMachineAliasFilter =
"*";
2704 std::map<std::string ,
2706 aliasMap = CorePropertySupervisorBase::theConfigurationManager_
2707 ->getActiveGroupAliases();
2711 CorePropertySupervisorBase::theConfigurationManager_
2712 ->getSupervisorTableNode(supervisorContextUID_,
2713 supervisorApplicationUID_);
2715 if(!configLinkNode.isDisconnected())
2720 configLinkNode.getNode(
"LinkToStateMachineTable");
2721 if(!fsmLinkNode.isDisconnected())
2722 stateMachineAliasFilter =
2723 fsmLinkNode.getNode(fsmName +
"/SystemAliasFilter")
2724 .getValue<std::string>();
2726 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
2728 catch(std::runtime_error& e)
2730 __COUT_INFO__ << e.what() << __E__;
2734 __COUT_ERR__ <<
"Unknown error. Should never happen." << __E__;
2738 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
2740 __COUT__ <<
"stateMachineAliasFilter = " << stateMachineAliasFilter << __E__;
2747 stateMachineAliasFilter.size() && stateMachineAliasFilter[0] ==
'!';
2748 std::vector<std::string> filterArr;
2755 while((f = stateMachineAliasFilter.find(
'*', i)) != std::string::npos)
2757 tmp = stateMachineAliasFilter.substr(i, f - i);
2759 filterArr.push_back(tmp);
2763 if(i <= stateMachineAliasFilter.size())
2765 tmp = stateMachineAliasFilter.substr(i);
2766 filterArr.push_back(tmp);
2772 for(
auto& aliasMapPair : aliasMap)
2778 if(filterArr.size() == 1)
2780 if(filterArr[0] !=
"" && filterArr[0] !=
"*" &&
2781 aliasMapPair.first != filterArr[0])
2782 filterMatch =
false;
2787 for(f = 0; f < filterArr.size(); ++f)
2789 if(!filterArr[f].size())
2794 if((i = aliasMapPair.first.find(filterArr[f])) != 0)
2796 filterMatch =
false;
2801 filterArr.size() - 1)
2803 if(aliasMapPair.first.rfind(filterArr[f]) !=
2804 aliasMapPair.first.size() - filterArr[f].size())
2806 filterMatch =
false;
2810 else if((i = aliasMapPair.first.find(filterArr[f])) ==
2813 filterMatch =
false;
2820 filterMatch = !filterMatch;
2827 xmlOut.addTextElementToData(
"config_alias", aliasMapPair.first);
2828 xmlOut.addTextElementToData(
2830 TableGroupKey::getFullGroupString(aliasMapPair.second.first,
2831 aliasMapPair.second.second)
2834 std::string groupComment, groupAuthor, groupCreationTime;
2837 CorePropertySupervisorBase::theConfigurationManager_
2838 ->loadTableGroup(aliasMapPair.second.first,
2839 aliasMapPair.second.second,
2849 xmlOut.addTextElementToData(
"config_comment", groupComment);
2850 xmlOut.addTextElementToData(
"config_author", groupAuthor);
2851 xmlOut.addTextElementToData(
"config_create_time",
2856 __COUT_WARN__ <<
"Failed to load group metadata." << __E__;
2862 std::string fn = FSM_LAST_GROUP_ALIAS_PATH + FSM_LAST_GROUP_ALIAS_FILE_START +
2863 username +
"." + FSM_USERS_PREFERENCES_FILETYPE;
2864 __COUT__ <<
"Load preferences: " << fn << __E__;
2865 FILE* fp = fopen(fn.c_str(),
"r");
2868 char tmpLastAlias[500];
2869 fscanf(fp,
"%*s %s", tmpLastAlias);
2870 __COUT__ <<
"tmpLastAlias: " << tmpLastAlias << __E__;
2872 xmlOut.addTextElementToData(
"UserLastConfigAlias", tmpLastAlias);
2876 else if(requestType ==
"getFecList")
2878 xmlOut.addTextElementToData(
"fec_list",
"");
2880 for(
auto it : allSupervisorInfo_.getAllFETypeSupervisorInfo())
2882 xmlOut.addTextElementToParent(
"fec_url", it.second.getURL(),
"fec_list");
2883 xmlOut.addTextElementToParent(
2884 "fec_urn", std::to_string(it.second.getId()),
"fec_list");
2887 else if(requestType ==
"getSystemMessages")
2889 xmlOut.addTextElementToData(
2891 theSystemMessenger_.getSystemMessage(
2892 theWebUsers_.getUsersDisplayName(userInfo.uid_)));
2894 xmlOut.addTextElementToData(
2895 "username_with_lock",
2896 theWebUsers_.getUserWithLock());
2900 else if(requestType ==
"setUserWithLock")
2902 std::string username = CgiDataUtilities::postData(cgiIn,
"username");
2903 std::string lock = CgiDataUtilities::postData(cgiIn,
"lock");
2904 std::string accounts = CgiDataUtilities::getData(cgiIn,
"accounts");
2906 __COUT__ << requestType << __E__;
2907 __COUT__ <<
"username " << username << __E__;
2908 __COUT__ <<
"lock " << lock << __E__;
2909 __COUT__ <<
"accounts " << accounts << __E__;
2910 __COUT__ <<
"userInfo.uid_ " << userInfo.uid_ << __E__;
2912 std::string tmpUserWithLock = theWebUsers_.getUserWithLock();
2913 if(!theWebUsers_.setUserWithLock(userInfo.uid_, lock ==
"1", username))
2914 xmlOut.addTextElementToData(
2916 std::string(
"Set user lock action failed. You must have valid "
2917 "permissions and ") +
2918 "locking user must be currently logged in.");
2920 theWebUsers_.insertSettingsForUser(userInfo.uid_, &xmlOut, accounts ==
"1");
2922 if(tmpUserWithLock !=
2925 theSystemMessenger_.addSystemMessage(
2927 theWebUsers_.getUserWithLock() ==
""
2928 ? tmpUserWithLock +
" has unlocked ots."
2929 : theWebUsers_.getUserWithLock() +
" has locked ots.");
2931 else if(requestType ==
"getStateMachine")
2934 std::vector<toolbox::fsm::State> states;
2935 states = theStateMachine_.getStates();
2938 std::string transName;
2939 std::string transParameter;
2942 for(
unsigned int i = 0; i < states.size(); ++i)
2944 stateStr[0] = states[i];
2945 DOMElement* stateParent = xmlOut.addTextElementToData(
"state", stateStr);
2947 xmlOut.addTextElementToParent(
2948 "state_name", theStateMachine_.getStateName(states[i]), stateParent);
2955 std::map<std::string, toolbox::fsm::State, std::less<std::string>> trans =
2956 theStateMachine_.getTransitions(states[i]);
2957 std::set<std::string> actionNames = theStateMachine_.getInputs(states[i]);
2959 std::map<std::string, toolbox::fsm::State, std::less<std::string>>::
2960 iterator it = trans.begin();
2961 std::set<std::string>::iterator ait = actionNames.begin();
2969 for(; it != trans.end() && ait != actionNames.end(); ++it, ++ait)
2971 stateStr[0] = it->second;
2973 if(stateStr[0] ==
'R')
2976 xmlOut.addTextElementToParent(
2977 "state_transition", stateStr, stateParent);
2981 xmlOut.addTextElementToParent(
2982 "state_transition_action", *ait, stateParent);
2984 transName = theStateMachine_.getTransitionName(states[i], *ait);
2987 xmlOut.addTextElementToParent(
2988 "state_transition_name", transName, stateParent);
2990 theStateMachine_.getTransitionParameter(states[i], *ait);
2993 xmlOut.addTextElementToParent(
2994 "state_transition_parameter", transParameter, stateParent);
2997 else if(stateStr[0] ==
'C')
3000 xmlOut.addTextElementToParent(
3001 "state_transition", stateStr, stateParent);
3005 xmlOut.addTextElementToParent(
3006 "state_transition_action", *ait, stateParent);
3008 transName = theStateMachine_.getTransitionName(states[i], *ait);
3011 xmlOut.addTextElementToParent(
3012 "state_transition_name", transName, stateParent);
3014 theStateMachine_.getTransitionParameter(states[i], *ait);
3017 xmlOut.addTextElementToParent(
3018 "state_transition_parameter", transParameter, stateParent);
3025 ait = actionNames.begin();
3028 for(; it != trans.end() && ait != actionNames.end(); ++it, ++ait)
3032 stateStr[0] = it->second;
3034 if(stateStr[0] ==
'R')
3036 else if(stateStr[0] ==
'C')
3039 xmlOut.addTextElementToParent(
3040 "state_transition", stateStr, stateParent);
3044 xmlOut.addTextElementToParent(
3045 "state_transition_action", *ait, stateParent);
3047 transName = theStateMachine_.getTransitionName(states[i], *ait);
3050 xmlOut.addTextElementToParent(
3051 "state_transition_name", transName, stateParent);
3053 theStateMachine_.getTransitionParameter(states[i], *ait);
3056 xmlOut.addTextElementToParent(
3057 "state_transition_parameter", transParameter, stateParent);
3061 else if(requestType ==
"getStateMachineNames")
3065 CorePropertySupervisorBase::theConfigurationManager_
3066 ->getSupervisorTableNode(supervisorContextUID_,
3067 supervisorApplicationUID_);
3072 configLinkNode.getNode(
"LinkToStateMachineTable").getChildren();
3073 for(
const auto& fsmNode : fsmNodes)
3074 xmlOut.addTextElementToData(
"stateMachineName", fsmNode.first);
3078 __COUT__ <<
"Caught exception, assuming no valid FSM names." << __E__;
3079 xmlOut.addTextElementToData(
"stateMachineName",
"");
3082 else if(requestType ==
"getIterationPlanStatus")
3085 theIterator_.handleCommandRequest(xmlOut, requestType,
"");
3087 else if(requestType ==
"getCurrentState")
3089 xmlOut.addTextElementToData(
"current_state",
3090 theStateMachine_.getCurrentStateName());
3091 xmlOut.addTextElementToData(
"in_transition",
3092 theStateMachine_.isInTransition() ?
"1" :
"0");
3093 if(theStateMachine_.isInTransition())
3094 xmlOut.addTextElementToData(
3095 "transition_progress",
3096 RunControlStateMachine::theProgressBar_.readPercentageString());
3098 xmlOut.addTextElementToData(
"transition_progress",
"100");
3101 sprintf(tmp,
"%lu", theStateMachine_.getTimeInState());
3102 xmlOut.addTextElementToData(
"time_in_state", tmp);
3109 std::string fsmName = CgiDataUtilities::getData(cgiIn,
"fsmName");
3118 if(!theStateMachine_.isInTransition())
3120 std::string stateMachineRunAlias =
"Run";
3124 CorePropertySupervisorBase::theConfigurationManager_
3125 ->getSupervisorTableNode(supervisorContextUID_,
3126 supervisorApplicationUID_);
3128 if(!configLinkNode.isDisconnected())
3133 configLinkNode.getNode(
"LinkToStateMachineTable");
3134 if(!fsmLinkNode.isDisconnected())
3135 stateMachineRunAlias =
3136 fsmLinkNode.getNode(fsmName +
"/RunDisplayAlias")
3137 .getValue<std::string>();
3141 catch(std::runtime_error& e)
3150 __COUT_ERR__ <<
"Unknown error. Should never happen." << __E__;
3152 __COUT_INFO__ <<
"No state machine Run alias. Ignoring and "
3153 "assuming alias of '"
3154 << stateMachineRunAlias <<
".'" << __E__;
3163 xmlOut.addTextElementToData(
"stateMachineRunAlias", stateMachineRunAlias);
3167 if(theStateMachine_.getCurrentStateName() ==
"Running" ||
3168 theStateMachine_.getCurrentStateName() ==
"Paused")
3171 "Current %s Number: %u",
3172 stateMachineRunAlias.c_str(),
3173 getNextRunNumber(activeStateMachineName_) - 1);
3175 if(RunControlStateMachine::asyncSoftFailureReceived_)
3179 xmlOut.addTextElementToData(
3180 "soft_error", RunControlStateMachine::getErrorMessage());
3185 "Next %s Number: %u",
3186 stateMachineRunAlias.c_str(),
3187 getNextRunNumber(fsmName));
3188 xmlOut.addTextElementToData(
"run_number", tmp);
3191 else if(requestType ==
"cancelStateMachineTransition")
3193 __SS__ <<
"State transition was cancelled by user!" << __E__;
3194 __MCOUT__(ss.str());
3195 RunControlStateMachine::theStateMachine_.setErrorMessage(ss.str());
3196 RunControlStateMachine::asyncFailureReceived_ =
true;
3198 else if(requestType ==
"getErrorInStateMatchine")
3200 xmlOut.addTextElementToData(
"FSM_Error", theStateMachine_.getErrorMessage());
3202 else if(requestType ==
"getDesktopIcons")
3209 CorePropertySupervisorBase::theConfigurationManager_->__GET_CONFIG__(
3211 std::vector<DesktopIconTable::DesktopIcon> icons =
3212 iconTable->getAllDesktopIcons();
3214 std::string iconString =
"";
3229 std::map<std::string, WebUsers::permissionLevel_t> userPermissionLevelsMap =
3230 theWebUsers_.getPermissionsForUser(userInfo.uid_);
3231 std::map<std::string, WebUsers::permissionLevel_t>
3232 iconPermissionThresholdsMap;
3234 bool firstIcon =
true;
3235 for(
const auto& icon : icons)
3237 __COUTV__(icon.caption_);
3238 __COUTV__(icon.permissionThresholdString_);
3240 CorePropertySupervisorBase::extractPermissionsMapFromString(
3241 icon.permissionThresholdString_, iconPermissionThresholdsMap);
3243 if(!CorePropertySupervisorBase::doPermissionsGrantAccess(
3244 userPermissionLevelsMap, iconPermissionThresholdsMap))
3255 iconString += icon.caption_;
3256 iconString +=
"," + icon.alternateText_;
3258 "," + std::string(icon.enforceOneWindowInstance_ ?
"1" :
"0");
3260 "," + std::string(
"1");
3264 iconString +=
"," + icon.imageURL_;
3265 iconString +=
"," + icon.windowContentURL_;
3266 iconString +=
"," + icon.folderPath_;
3268 __COUTV__(iconString);
3270 xmlOut.addTextElementToData(
"iconList", iconString);
3272 else if(requestType ==
"gatewayLaunchOTS" || requestType ==
"gatewayLaunchWiz")
3276 __COUT_WARN__ << requestType <<
" requestType received! " << __E__;
3277 __MOUT_WARN__ << requestType <<
" requestType received! " << __E__;
3280 theWebUsers_.saveActiveSessions();
3284 if(requestType ==
"gatewayLaunchOTS")
3285 GatewaySupervisor::launchStartOTSCommand(
3286 "LAUNCH_OTS", CorePropertySupervisorBase::theConfigurationManager_);
3287 else if(requestType ==
"gatewayLaunchWiz")
3288 GatewaySupervisor::launchStartOTSCommand(
3289 "LAUNCH_WIZ", CorePropertySupervisorBase::theConfigurationManager_);
3291 else if(requestType ==
"resetUserTooltips")
3293 WebUsers::resetAllUserTooltips(theWebUsers_.getUsersUsername(userInfo.uid_));
3297 __SS__ <<
"requestType Request, " << requestType <<
", not recognized."
3302 catch(
const std::runtime_error& e)
3304 __SS__ <<
"An error was encountered handling requestType '" << requestType
3305 <<
"':" << e.what() << __E__;
3306 __COUT__ <<
"\n" << ss.str();
3307 xmlOut.addTextElementToData(
"Error", ss.str());
3311 __SS__ <<
"An unknown error was encountered handling requestType '" << requestType
3313 <<
"Please check the printouts to debug." << __E__;
3314 __COUT__ <<
"\n" << ss.str();
3315 xmlOut.addTextElementToData(
"Error", ss.str());
3319 xmlOut.outputXmlDocument(
3320 (std::ostringstream*)out,
3331 void GatewaySupervisor::launchStartOTSCommand(
const std::string& command,
3334 __COUT__ <<
"launch StartOTS Command = " << command << __E__;
3335 __COUT__ <<
"Extracting target context hostnames... " << __E__;
3337 std::vector<std::string> hostnames;
3344 auto contexts = contextTable->getContexts();
3346 for(
const auto& context : contexts)
3348 if(!context.status_)
3353 for(i = 0; i < context.address_.size(); ++i)
3354 if(context.address_[i] ==
'/')
3356 hostnames.push_back(context.address_.substr(j));
3357 __COUT__ <<
"StartOTS.sh hostname = " << hostnames.back() << __E__;
3362 __SS__ <<
"\nRelaunch of otsdaq interrupted! "
3363 <<
"The Configuration Manager could not be initialized." << __E__;
3368 for(
const auto& hostname : hostnames)
3370 std::string fn = (std::string(getenv(
"SERVICE_DATA_PATH")) +
"/StartOTS_action_" +
3372 FILE* fp = fopen(fn.c_str(),
"w");
3375 fprintf(fp, command.c_str());
3380 __SS__ <<
"Unable to open command file: " << fn << __E__;
3388 for(
const auto& hostname : hostnames)
3390 std::string fn = (std::string(getenv(
"SERVICE_DATA_PATH")) +
"/StartOTS_action_" +
3392 FILE* fp = fopen(fn.c_str(),
"r");
3396 fgets(line, 100, fp);
3399 if(strcmp(line, command.c_str()) == 0)
3401 __SS__ <<
"The command looks to have been ignored by " << hostname
3402 <<
". Is StartOTS.sh still running on that node?" << __E__;
3409 __SS__ <<
"Unable to open command file for verification: " << fn << __E__;
3418 xoap::MessageReference GatewaySupervisor::supervisorCookieCheck(
3419 xoap::MessageReference message)
3426 parameters.addParameter(
"CookieCode");
3427 parameters.addParameter(
"RefreshOption");
3428 parameters.addParameter(
"IPAddress");
3429 SOAPUtilities::receive(message, parameters);
3430 std::string cookieCode = parameters.getValue(
"CookieCode");
3431 std::string refreshOption =
3432 parameters.getValue(
"RefreshOption");
3434 std::string ipAddress =
3435 parameters.getValue(
"IPAddress");
3441 std::map<std::string , WebUsers::permissionLevel_t>
3442 userGroupPermissionsMap;
3443 std::string userWithLock =
"";
3444 uint64_t activeSessionIndex, uid;
3445 theWebUsers_.cookieCodeIsActiveForRequest(cookieCode,
3446 &userGroupPermissionsMap,
3449 refreshOption ==
"1",
3451 &activeSessionIndex);
3457 retParameters.addParameter(
"CookieCode", cookieCode);
3458 retParameters.addParameter(
3459 "Permissions", StringMacros::mapToString(userGroupPermissionsMap).c_str());
3460 retParameters.addParameter(
"UserWithLock", userWithLock);
3461 retParameters.addParameter(
"Username", theWebUsers_.getUsersUsername(uid));
3462 retParameters.addParameter(
"DisplayName", theWebUsers_.getUsersDisplayName(uid));
3463 sprintf(tmpStringForConversions_,
"%lu", activeSessionIndex);
3464 retParameters.addParameter(
"ActiveSessionIndex", tmpStringForConversions_);
3468 return SOAPUtilities::makeSOAPMessageReference(
"CookieResponse", retParameters);
3474 xoap::MessageReference GatewaySupervisor::supervisorGetActiveUsers(
3475 xoap::MessageReference message)
3480 SOAPParameters parameters(
"UserList", theWebUsers_.getActiveUsersString());
3481 return SOAPUtilities::makeSOAPMessageReference(
"ActiveUserResponse", parameters);
3488 xoap::MessageReference GatewaySupervisor::supervisorSystemMessage(
3489 xoap::MessageReference message)
3493 parameters.addParameter(
"ToUser");
3494 parameters.addParameter(
"Message");
3495 SOAPUtilities::receive(message, parameters);
3497 __COUT__ <<
"toUser: " << parameters.getValue(
"ToUser").substr(0, 10)
3498 <<
", message: " << parameters.getValue(
"Message").substr(0, 10) << __E__;
3500 theSystemMessenger_.addSystemMessage(parameters.getValue(
"ToUser"),
3501 parameters.getValue(
"Message"));
3502 return SOAPUtilities::makeSOAPMessageReference(
"SystemMessageResponse");
3509 xoap::MessageReference GatewaySupervisor::supervisorSystemLogbookEntry(
3510 xoap::MessageReference message)
3514 parameters.addParameter(
"EntryText");
3515 SOAPUtilities::receive(message, parameters);
3517 __COUT__ <<
"EntryText: " << parameters.getValue(
"EntryText").substr(0, 10) << __E__;
3519 makeSystemLogbookEntry(parameters.getValue(
"EntryText"));
3521 return SOAPUtilities::makeSOAPMessageReference(
"SystemLogbookResponse");
3529 xoap::MessageReference GatewaySupervisor::supervisorLastConfigGroupRequest(
3530 xoap::MessageReference message)
3534 parameters.addParameter(
"ActionOfLastGroup");
3535 SOAPUtilities::receive(message, parameters);
3537 return GatewaySupervisor::lastConfigGroupRequestHandler(parameters);
3546 xoap::MessageReference GatewaySupervisor::lastConfigGroupRequestHandler(
3549 std::string action = parameters.getValue(
"ActionOfLastGroup");
3550 __COUT__ <<
"ActionOfLastGroup: " << action.substr(0, 10) << __E__;
3552 std::string fileName =
"";
3553 if(action ==
"Configured")
3554 fileName = FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE;
3555 else if(action ==
"Started")
3556 fileName = FSM_LAST_STARTED_GROUP_ALIAS_FILE;
3559 __COUT_ERR__ <<
"Invalid last group action requested." << __E__;
3560 return SOAPUtilities::makeSOAPMessageReference(
"LastConfigGroupResponseFailure");
3562 std::string timeString;
3564 loadGroupNameAndKey(fileName, timeString);
3568 retParameters.addParameter(
"GroupName", theGroup.first);
3569 retParameters.addParameter(
"GroupKey", theGroup.second.toString());
3570 retParameters.addParameter(
"GroupAction", action);
3571 retParameters.addParameter(
"GroupActionTime", timeString);
3573 return SOAPUtilities::makeSOAPMessageReference(
"LastConfigGroupResponse",
3584 unsigned int GatewaySupervisor::getNextRunNumber(
const std::string& fsmNameIn)
3586 std::string runNumberFileName = RUN_NUMBER_PATH +
"/";
3587 std::string fsmName = fsmNameIn ==
"" ? activeStateMachineName_ : fsmNameIn;
3589 for(
unsigned int i = 0; i < fsmName.size(); ++i)
3590 if((fsmName[i] >=
'a' && fsmName[i] <=
'z') ||
3591 (fsmName[i] >=
'A' && fsmName[i] <=
'Z') ||
3592 (fsmName[i] >=
'0' && fsmName[i] <=
'9'))
3593 runNumberFileName += fsmName[i];
3594 runNumberFileName += RUN_NUMBER_FILE_NAME;
3597 std::ifstream runNumberFile(runNumberFileName.c_str());
3598 if(!runNumberFile.is_open())
3600 __COUT__ <<
"Can't open file: " << runNumberFileName << __E__;
3602 __COUT__ <<
"Creating file and setting Run Number to 1: " << runNumberFileName
3604 FILE* fp = fopen(runNumberFileName.c_str(),
"w");
3608 runNumberFile.open(runNumberFileName.c_str());
3609 if(!runNumberFile.is_open())
3611 __SS__ <<
"Error. Can't create file: " << runNumberFileName << __E__;
3612 __COUT_ERR__ << ss.str();
3616 std::string runNumberString;
3617 runNumberFile >> runNumberString;
3618 runNumberFile.close();
3619 return atoi(runNumberString.c_str());
3623 bool GatewaySupervisor::setNextRunNumber(
unsigned int runNumber,
3624 const std::string& fsmNameIn)
3626 std::string runNumberFileName = RUN_NUMBER_PATH +
"/";
3627 std::string fsmName = fsmNameIn ==
"" ? activeStateMachineName_ : fsmNameIn;
3629 for(
unsigned int i = 0; i < fsmName.size(); ++i)
3630 if((fsmName[i] >=
'a' && fsmName[i] <=
'z') ||
3631 (fsmName[i] >=
'A' && fsmName[i] <=
'Z') ||
3632 (fsmName[i] >=
'0' && fsmName[i] <=
'9'))
3633 runNumberFileName += fsmName[i];
3634 runNumberFileName += RUN_NUMBER_FILE_NAME;
3635 __COUT__ <<
"runNumberFileName: " << runNumberFileName << __E__;
3637 std::ofstream runNumberFile(runNumberFileName.c_str());
3638 if(!runNumberFile.is_open())
3640 __SS__ <<
"Can't open file: " << runNumberFileName << __E__;
3641 __COUT__ << ss.str();
3644 std::stringstream runNumberStream;
3645 runNumberStream << runNumber;
3646 runNumberFile << runNumberStream.str().c_str();
3647 runNumberFile.close();
3658 GatewaySupervisor::loadGroupNameAndKey(
const std::string& fileName,
3659 std::string& returnedTimeString)
3661 std::string fullPath = FSM_LAST_GROUP_ALIAS_PATH +
"/" + fileName;
3663 FILE* groupFile = fopen(fullPath.c_str(),
"r");
3666 __COUT__ <<
"Can't open file: " << fullPath << __E__;
3668 __COUT__ <<
"Returning empty groupName and key -1" << __E__;
3670 return std::pair<std::string ,
TableGroupKey>(
"", TableGroupKey());
3677 fgets(line, 500, groupFile);
3678 theGroup.first = line;
3680 fgets(line, 500, groupFile);
3682 sscanf(line,
"%d", &key);
3683 theGroup.second = key;
3685 fgets(line, 500, groupFile);
3687 sscanf(line,
"%ld", ×tamp);
3691 returnedTimeString = StringMacros::getTimestampString(timestamp);
3694 __COUT__ <<
"theGroup.first= " << theGroup.first
3695 <<
" theGroup.second= " << theGroup.second << __E__;
3701 void GatewaySupervisor::saveGroupNameAndKey(
3702 const std::pair<std::string /*group name*/, TableGroupKey>& theGroup,
3703 const std::string& fileName)
3705 std::string fullPath = FSM_LAST_GROUP_ALIAS_PATH +
"/" + fileName;
3707 std::ofstream groupFile(fullPath.c_str());
3708 if(!groupFile.is_open())
3710 __SS__ <<
"Error. Can't open file: " << fullPath << __E__;
3711 __COUT_ERR__ <<
"\n" << ss.str();
3714 std::stringstream outss;
3715 outss << theGroup.first <<
"\n" << theGroup.second <<
"\n" << time(0);
3716 groupFile << outss.str().c_str();