1 #include "otsdaq/GatewaySupervisor/Iterator.h"
2 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
3 #include "otsdaq/GatewaySupervisor/GatewaySupervisor.h"
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/MessageFacility/MessageFacility.h"
6 #include "otsdaq/WebUsersUtilities/WebUsers.h"
12 #define __MF_SUBJECT__ "Iterator"
16 #define ITERATOR_PLAN_HISTORY_FILENAME \
17 ((getenv("SERVICE_DATA_PATH") == NULL) \
18 ? (std::string(__ENV__("USER_DATA")) + "/ServiceData") \
19 : (std::string(__ENV__("SERVICE_DATA_PATH")))) + \
20 "/IteratorPlanHistory.hist"
22 const std::string Iterator::RESERVED_GEN_PLAN_NAME =
"---GENERATED_PLAN---";
26 : workloopRunning_(false)
27 , activePlanIsRunning_(false)
28 , iteratorBusy_(false)
30 , commandPause_(false)
33 , activeCommandIndex_(-1)
34 , activeCommandStartTime_(0)
35 , theSupervisor_(supervisor)
37 __COUT__ <<
"Iterator constructed." << __E__;
40 __COUT__ <<
"Filename for iterator history: " << ITERATOR_PLAN_HISTORY_FILENAME
42 FILE* fp = fopen((ITERATOR_PLAN_HISTORY_FILENAME).c_str(),
"r");
47 while(fgets(line, 100, fp))
51 line[strlen(line) - 1] =
'\0';
54 lastStartedPlanName_ = line;
57 lastFinishedPlanName_ = line;
63 __COUTV__(lastStartedPlanName_);
64 __COUTV__(lastFinishedPlanName_);
69 Iterator::~Iterator(
void) {}
72 void Iterator::IteratorWorkLoop(
Iterator* iterator)
75 __COUT__ <<
"Iterator work loop starting..." << __E__;
81 if(iterator->theSupervisor_->VERBOSE_MUTEX)
82 __COUT__ <<
"Waiting for iterator access" << __E__;
83 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
84 if(iterator->theSupervisor_->VERBOSE_MUTEX)
85 __COUT__ <<
"Have iterator access" << __E__;
87 iterator->errorMessage_ =
"";
91 WebUsers::DEFAULT_ITERATOR_USERNAME);
93 theConfigurationManager.getAllTableInfo(
true ,
100 __COUT__ <<
"Iterator work loop starting..." << __E__;
101 IteratorWorkLoopStruct theIteratorStruct(iterator, &theConfigurationManager);
102 __COUT__ <<
"Iterator work loop starting..." << __E__;
106 std::vector<IterateTable::Command> commands;
130 if(iterator->theSupervisor_->VERBOSE_MUTEX)
131 __COUT__ <<
"Waiting for iterator access" << __E__;
132 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
133 if(iterator->theSupervisor_->VERBOSE_MUTEX)
134 __COUT__ <<
"Have iterator access" << __E__;
136 if(iterator->commandPlay_)
138 iterator->commandPlay_ =
false;
140 if(!iterator->activePlanIsRunning_)
144 iterator->activePlanIsRunning_ =
true;
145 iterator->iteratorBusy_ =
true;
147 if(theIteratorStruct.activePlan_ != iterator->activePlanName_)
149 __COUT__ <<
"New plan name encountered old="
150 << theIteratorStruct.activePlan_
151 <<
" vs new=" << iterator->activePlanName_ << __E__;
152 theIteratorStruct.commandIndex_ = -1;
155 theIteratorStruct.activePlan_ = iterator->activePlanName_;
156 iterator->lastStartedPlanName_ = iterator->activePlanName_;
157 FILE* fp = fopen((ITERATOR_PLAN_HISTORY_FILENAME).c_str(),
"w");
160 fprintf(fp,
"%s\n", iterator->lastStartedPlanName_.c_str());
161 fprintf(fp,
"%s\n", iterator->lastFinishedPlanName_.c_str());
165 __COUT_WARN__ <<
"Could not open Iterator history file: "
166 << ITERATOR_PLAN_HISTORY_FILENAME << __E__;
168 if(theIteratorStruct.commandIndex_ == (
unsigned int)-1)
170 __COUT__ <<
"Starting plan '" << theIteratorStruct.activePlan_
172 __COUT__ <<
"Starting plan '" << theIteratorStruct.activePlan_
177 theIteratorStruct.doResumeAction_ =
true;
178 __COUT__ <<
"Continuing plan '"
179 << theIteratorStruct.activePlan_
180 <<
"' at command index "
181 << theIteratorStruct.commandIndex_ <<
". " << __E__;
182 __COUT__ <<
"Continuing plan '"
183 << theIteratorStruct.activePlan_
184 <<
"' at command index "
185 << theIteratorStruct.commandIndex_ <<
". " << __E__;
189 else if(iterator->commandPause_ && !theIteratorStruct.doPauseAction_)
191 theIteratorStruct.doPauseAction_ =
true;
192 iterator->commandPause_ =
false;
194 else if(iterator->commandHalt_ && !theIteratorStruct.doHaltAction_)
196 theIteratorStruct.doHaltAction_ =
true;
197 iterator->commandHalt_ =
false;
200 theIteratorStruct.running_ = iterator->activePlanIsRunning_;
203 ->activeCommandIndex_ !=
204 theIteratorStruct.commandIndex_)
206 iterator->activeCommandIndex_ = theIteratorStruct.commandIndex_;
207 if(theIteratorStruct.commandIndex_ <
208 theIteratorStruct.commands_.size())
209 iterator->activeCommandType_ =
210 theIteratorStruct.commands_[theIteratorStruct.commandIndex_]
213 iterator->activeCommandType_ =
"";
214 iterator->activeCommandStartTime_ = time(0);
216 if(theIteratorStruct.commandIndex_ <
217 theIteratorStruct.commandIterations_.size())
218 iterator->activeCommandIteration_ =
220 .commandIterations_[theIteratorStruct.commandIndex_];
222 iterator->activeCommandIteration_ = -1;
224 iterator->depthIterationStack_.clear();
225 for(
const auto& depthIteration : theIteratorStruct.stepIndexStack_)
226 iterator->depthIterationStack_.push_back(depthIteration);
232 iterator->activeNumberOfCommands_ =
233 theIteratorStruct.commands_.size();
242 if(theIteratorStruct.doPauseAction_)
249 __COUT__ <<
"Waiting to pause..." << __E__;
250 while(!iterator->checkCommand(&theIteratorStruct))
251 __COUT__ <<
"Waiting to pause..." << __E__;
253 __COUT__ <<
"Completing pause..." << __E__;
255 theIteratorStruct.doPauseAction_ =
false;
259 if(iterator->theSupervisor_->VERBOSE_MUTEX)
260 __COUT__ <<
"Waiting for iterator access" << __E__;
261 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
262 if(iterator->theSupervisor_->VERBOSE_MUTEX)
263 __COUT__ <<
"Have iterator access" << __E__;
265 iterator->activePlanIsRunning_ =
false;
267 __COUT__ <<
"Paused plan '" << theIteratorStruct.activePlan_
268 <<
"' at command index " << theIteratorStruct.commandIndex_
270 __COUT__ <<
"Paused plan '" << theIteratorStruct.activePlan_
271 <<
"' at command index " << theIteratorStruct.commandIndex_
276 else if(theIteratorStruct.doHaltAction_)
283 __COUT__ <<
"Waiting to halt..." << __E__;
284 while(!iterator->checkCommand(&theIteratorStruct))
285 __COUT__ <<
"Waiting to halt..." << __E__;
287 __COUT__ <<
"Completing halt..." << __E__;
289 theIteratorStruct.doHaltAction_ =
false;
291 iterator->haltIterator(iterator, &theIteratorStruct);
329 if(theIteratorStruct.running_ &&
330 theIteratorStruct.activePlan_ !=
333 if(theIteratorStruct.commandIndex_ == (
unsigned int)-1)
337 __COUT__ <<
"Get commands" << __E__;
339 theIteratorStruct.commandIndex_ = 0;
341 theIteratorStruct.cfgMgr_
344 if(theIteratorStruct.activePlan_ == Iterator::RESERVED_GEN_PLAN_NAME)
346 __COUT__ <<
"Using generated plan..." << __E__;
347 theIteratorStruct.onlyConfigIfNotConfigured_ =
348 iterator->genKeepConfiguration_;
349 theIteratorStruct.commands_ =
350 generateIterationPlan(iterator->genFsmName_,
351 iterator->genConfigAlias_,
352 iterator->genPlanDurationSeconds_,
353 iterator->genPlanNumberOfRuns_);
357 __COUT__ <<
"Getting iterator table..." << __E__;
359 theIteratorStruct.cfgMgr_->__GET_CONFIG__(
IterateTable);
360 theIteratorStruct.onlyConfigIfNotConfigured_ =
false;
361 theIteratorStruct.commands_ = itConfig->getPlanCommands(
362 theIteratorStruct.cfgMgr_, theIteratorStruct.activePlan_);
366 theIteratorStruct.commandIterations_.clear();
367 for(
auto& command : theIteratorStruct.commands_)
369 theIteratorStruct.commandIterations_.push_back(0);
370 __COUT__ <<
"command " << command.type_ << __E__;
372 << IterateTable::commandToTableMap_.at(command.type_)
374 __COUT__ <<
"param count = " << command.params_.size() << __E__;
376 for(
auto& param : command.params_)
378 __COUT__ <<
"\t param " << param.first <<
" : "
379 << param.second << __E__;
383 theIteratorStruct.originalTrackChanges_ =
384 ConfigurationInterface::isVersionTrackingEnabled();
385 theIteratorStruct.originalConfigGroup_ =
386 theIteratorStruct.cfgMgr_->getActiveGroupName();
387 theIteratorStruct.originalConfigKey_ =
388 theIteratorStruct.cfgMgr_->getActiveGroupKey();
390 __COUT__ <<
"originalTrackChanges "
391 << theIteratorStruct.originalTrackChanges_ << __E__;
392 __COUT__ <<
"originalConfigGroup "
393 << theIteratorStruct.originalConfigGroup_ << __E__;
394 __COUT__ <<
"originalConfigKey "
395 << theIteratorStruct.originalConfigKey_ << __E__;
399 if(!theIteratorStruct.commandBusy_)
401 if(theIteratorStruct.commandIndex_ <
402 theIteratorStruct.commands_.size())
405 theIteratorStruct.commandBusy_ =
true;
407 __COUT__ <<
"Iterator starting command "
408 << theIteratorStruct.commandIndex_ + 1 <<
": "
410 .commands_[theIteratorStruct.commandIndex_]
413 __COUT__ <<
"Iterator starting command "
414 << theIteratorStruct.commandIndex_ + 1 <<
": "
416 .commands_[theIteratorStruct.commandIndex_]
420 iterator->startCommand(&theIteratorStruct);
422 else if(theIteratorStruct.commandIndex_ ==
423 theIteratorStruct.commands_.size())
425 __COUT__ <<
"Finished Iteration Plan '"
426 << theIteratorStruct.activePlan_ << __E__;
427 __COUT__ <<
"Finished Iteration Plan '"
428 << theIteratorStruct.activePlan_ << __E__;
430 __COUT__ <<
"Reverting track changes." << __E__;
431 ConfigurationInterface::setVersionTrackingEnabled(
432 theIteratorStruct.originalTrackChanges_);
435 __COUT__ <<
"Activating original group..." << __E__;
438 theIteratorStruct.cfgMgr_->activateTableGroup(
439 theIteratorStruct.originalConfigGroup_,
440 theIteratorStruct.originalConfigKey_);
444 __COUT_WARN__ <<
"Original group could not be activated."
449 __COUT__ <<
"Completing Iteration Plan and cleaning up..."
452 iterator->haltIterator(
453 iterator, &theIteratorStruct,
true );
456 else if(theIteratorStruct.commandBusy_)
459 if(iterator->checkCommand(&theIteratorStruct))
461 theIteratorStruct.commandBusy_ =
false;
463 ++theIteratorStruct.commandIndex_;
465 __COUT__ <<
"Ready for next command. Done with "
466 << theIteratorStruct.commandIndex_ <<
" of "
467 << theIteratorStruct.commands_.size() << __E__;
468 __COUT__ <<
"Iterator ready for next command. Done with "
469 << theIteratorStruct.commandIndex_ <<
" of "
470 << theIteratorStruct.commands_.size() << __E__;
474 if(theIteratorStruct.doResumeAction_)
475 theIteratorStruct.doResumeAction_ =
false;
490 catch(
const std::runtime_error& e)
492 if(theIteratorStruct.activePlan_ !=
"")
494 __SS__ <<
"The active Iterator plan name is '"
495 << theIteratorStruct.activePlan_
496 <<
"'... Here was the error: " << e.what() << __E__;
503 iterator->workloopRunning_ =
false;
505 catch(
const std::runtime_error& e)
507 __SS__ <<
"Encountered error in Iterator thread. Here is the error:\n"
508 << e.what() << __E__;
509 __COUT_ERR__ << ss.str();
513 if(iterator->theSupervisor_->VERBOSE_MUTEX)
514 __COUT__ <<
"Waiting for iterator access" << __E__;
515 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
516 if(iterator->theSupervisor_->VERBOSE_MUTEX)
517 __COUT__ <<
"Have iterator access" << __E__;
519 iterator->workloopRunning_ =
false;
520 iterator->errorMessage_ = ss.str();
524 __SS__ <<
"Encountered unknown error in Iterator thread." << __E__;
529 catch(
const std::exception& e)
531 ss <<
"Exception message: " << e.what();
536 __COUT_ERR__ << ss.str();
540 if(iterator->theSupervisor_->VERBOSE_MUTEX)
541 __COUT__ <<
"Waiting for iterator access" << __E__;
542 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
543 if(iterator->theSupervisor_->VERBOSE_MUTEX)
544 __COUT__ <<
"Have iterator access" << __E__;
546 iterator->workloopRunning_ =
false;
547 iterator->errorMessage_ = ss.str();
551 void Iterator::startCommand(IteratorWorkLoopStruct* iteratorStruct)
556 for(
const auto& depthIteration : iteratorStruct->stepIndexStack_)
558 __COUT__ << i++ <<
":" << depthIteration << __E__;
565 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
566 __COUT__ <<
"Waiting for FSM access" << __E__;
567 std::lock_guard<std::mutex> lock(
568 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
569 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
570 __COUT__ <<
"Have FSM access" << __E__;
573 if(iteratorStruct->commandIndex_ >= iteratorStruct->commands_.size())
575 __SS__ <<
"Out of range commandIndex = " << iteratorStruct->commandIndex_
576 <<
" in size = " << iteratorStruct->commands_.size() << __E__;
581 ++iteratorStruct->commandIterations_[iteratorStruct->commandIndex_];
583 std::string type = iteratorStruct->commands_[iteratorStruct->commandIndex_].type_;
586 return startCommandBeginLabel(iteratorStruct);
588 else if(type == IterateTable::COMMAND_CHOOSE_FSM)
590 return startCommandChooseFSM(
592 iteratorStruct->commands_[iteratorStruct->commandIndex_]
593 .params_[IterateTable::commandChooseFSMParams_.NameOfFSM_]);
595 else if(type == IterateTable::COMMAND_CONFIGURE_ACTIVE_GROUP)
597 return startCommandConfigureActive(iteratorStruct);
599 else if(type == IterateTable::COMMAND_CONFIGURE_ALIAS)
601 return startCommandConfigureAlias(
603 iteratorStruct->commands_[iteratorStruct->commandIndex_]
604 .params_[IterateTable::commandConfigureAliasParams_.SystemAlias_]);
606 else if(type == IterateTable::COMMAND_CONFIGURE_GROUP)
608 return startCommandConfigureGroup(iteratorStruct);
610 else if(type == IterateTable::COMMAND_ACTIVATE_ALIAS)
613 std::pair<std::string, TableGroupKey> newActiveGroup =
615 iteratorStruct->commands_[iteratorStruct->commandIndex_]
616 .params_[IterateTable::commandActivateAliasParams_.SystemAlias_]);
618 newActiveGroup.first, newActiveGroup.second,
true );
620 else if(type == IterateTable::COMMAND_ACTIVATE_GROUP)
624 iteratorStruct->commands_[iteratorStruct->commandIndex_]
625 .params_[IterateTable::commandActivateGroupParams_.GroupName_],
627 iteratorStruct->commands_[iteratorStruct->commandIndex_]
628 .params_[IterateTable::commandActivateGroupParams_.GroupKey_]),
631 else if(type == IterateTable::COMMAND_EXECUTE_FE_MACRO)
633 return startCommandMacro(iteratorStruct,
true );
635 else if(type == IterateTable::COMMAND_EXECUTE_MACRO)
637 return startCommandMacro(iteratorStruct,
false );
639 else if(type == IterateTable::COMMAND_MODIFY_ACTIVE_GROUP)
641 return startCommandModifyActive(iteratorStruct);
643 else if(type == IterateTable::COMMAND_REPEAT_LABEL)
645 return startCommandRepeatLabel(iteratorStruct);
647 else if(type == IterateTable::COMMAND_RUN)
649 return startCommandRun(iteratorStruct);
651 else if(type == IterateTable::COMMAND_START)
653 return startCommandFSMTransition(iteratorStruct,
654 RunControlStateMachine::START_TRANSITION_NAME);
656 else if(type == IterateTable::COMMAND_STOP)
658 return startCommandFSMTransition(iteratorStruct,
659 RunControlStateMachine::STOP_TRANSITION_NAME);
661 else if(type == IterateTable::COMMAND_PAUSE)
663 return startCommandFSMTransition(iteratorStruct,
664 RunControlStateMachine::PAUSE_TRANSITION_NAME);
666 else if(type == IterateTable::COMMAND_RESUME)
668 return startCommandFSMTransition(iteratorStruct,
669 RunControlStateMachine::RESUME_TRANSITION_NAME);
671 else if(type == IterateTable::COMMAND_HALT)
673 return startCommandFSMTransition(iteratorStruct,
674 RunControlStateMachine::HALT_TRANSITION_NAME);
678 __SS__ <<
"Failed attempt to start unrecognized command type = " << type << __E__;
679 __COUT_ERR__ << ss.str();
685 __COUT__ <<
"Error caught. Reverting track changes." << __E__;
686 ConfigurationInterface::setVersionTrackingEnabled(
687 iteratorStruct->originalTrackChanges_);
689 __COUT__ <<
"Activating original group..." << __E__;
692 iteratorStruct->cfgMgr_->activateTableGroup(iteratorStruct->originalConfigGroup_,
693 iteratorStruct->originalConfigKey_);
697 __COUT_WARN__ <<
"Original group could not be activated." << __E__;
706 bool Iterator::checkCommand(IteratorWorkLoopStruct* iteratorStruct)
710 if(iteratorStruct->commandIndex_ >= iteratorStruct->commands_.size())
712 __COUT__ <<
"Out of range commandIndex = " << iteratorStruct->commandIndex_
713 <<
" in size = " << iteratorStruct->commands_.size() << __E__;
717 std::string type = iteratorStruct->commands_[iteratorStruct->commandIndex_].type_;
723 else if(type == IterateTable::COMMAND_CHOOSE_FSM)
728 else if(type == IterateTable::COMMAND_CONFIGURE_ALIAS ||
729 type == IterateTable::COMMAND_CONFIGURE_ACTIVE_GROUP ||
730 type == IterateTable::COMMAND_CONFIGURE_GROUP)
732 return checkCommandConfigure(iteratorStruct);
734 else if(type == IterateTable::COMMAND_ACTIVATE_ALIAS ||
735 type == IterateTable::COMMAND_ACTIVATE_GROUP)
740 else if(type == IterateTable::COMMAND_EXECUTE_FE_MACRO)
742 return checkCommandMacro(iteratorStruct,
true );
744 else if(type == IterateTable::COMMAND_EXECUTE_MACRO)
746 return checkCommandMacro(iteratorStruct,
false );
748 else if(type == IterateTable::COMMAND_MODIFY_ACTIVE_GROUP)
753 else if(type == IterateTable::COMMAND_REPEAT_LABEL)
758 else if(type == IterateTable::COMMAND_RUN)
760 return checkCommandRun(iteratorStruct);
762 else if(type == IterateTable::COMMAND_START)
764 return checkCommandFSMTransition(iteratorStruct,
"Running");
766 else if(type == IterateTable::COMMAND_STOP)
768 return checkCommandFSMTransition(iteratorStruct,
"Configured");
770 else if(type == IterateTable::COMMAND_PAUSE)
772 return checkCommandFSMTransition(iteratorStruct,
"Paused");
774 else if(type == IterateTable::COMMAND_RESUME)
776 return checkCommandFSMTransition(iteratorStruct,
"Running");
778 else if(type == IterateTable::COMMAND_HALT)
780 return checkCommandFSMTransition(iteratorStruct,
781 RunControlStateMachine::HALTED_STATE_NAME);
785 __SS__ <<
"Attempt to check unrecognized command type = " << type << __E__;
786 __COUT_ERR__ << ss.str();
792 __COUT__ <<
"Error caught. Reverting track changes." << __E__;
793 ConfigurationInterface::setVersionTrackingEnabled(
794 iteratorStruct->originalTrackChanges_);
796 __COUT__ <<
"Activating original group..." << __E__;
799 iteratorStruct->cfgMgr_->activateTableGroup(iteratorStruct->originalConfigGroup_,
800 iteratorStruct->originalConfigKey_);
804 __COUT_WARN__ <<
"Original group could not be activated." << __E__;
811 void Iterator::startCommandChooseFSM(IteratorWorkLoopStruct* iteratorStruct,
812 const std::string& fsmName)
814 __COUT__ <<
"fsmName " << fsmName << __E__;
816 iteratorStruct->fsmName_ = fsmName;
817 iteratorStruct->theIterator_->lastFsmName_ = fsmName;
826 iteratorStruct->fsmRunAlias_ =
"Run";
829 ConfigurationTree configLinkNode = iteratorStruct->cfgMgr_->getSupervisorTableNode(
830 iteratorStruct->theIterator_->theSupervisor_->getContextUID(),
831 iteratorStruct->theIterator_->theSupervisor_->getSupervisorUID());
838 configLinkNode.
getNode(
"LinkToStateMachineTable");
840 iteratorStruct->fsmRunAlias_ =
841 fsmLinkNode.
getNode(fsmName +
"/RunDisplayAlias")
844 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
846 catch(std::runtime_error& e)
850 <<
"No state machine Run alias. Ignoring and assuming alias of '"
851 << iteratorStruct->fsmRunAlias_ <<
".'" << __E__;
855 __COUT_ERR__ <<
"Unknown error. Should never happen." << __E__;
858 <<
"No state machine Run alias. Ignoring and assuming alias of '"
859 << iteratorStruct->fsmRunAlias_ <<
".'" << __E__;
863 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
865 __COUT__ <<
"fsmRunAlias_ = " << iteratorStruct->fsmRunAlias_ << __E__;
869 iteratorStruct->fsmNextRunNumber_ =
870 iteratorStruct->theIterator_->theSupervisor_->getNextRunNumber(
871 iteratorStruct->fsmName_);
873 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
874 .getCurrentStateName() ==
"Running" ||
875 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
876 .getCurrentStateName() ==
"Paused")
877 --iteratorStruct->fsmNextRunNumber_;
879 __COUT__ <<
"fsmNextRunNumber_ = " << iteratorStruct->fsmNextRunNumber_ << __E__;
884 bool Iterator::haltIterator(
Iterator* iterator,
885 IteratorWorkLoopStruct* iteratorStruct ,
890 const std::string& fsmName = iterator->lastFsmName_;
892 std::vector<std::string> fsmCommandParameters;
893 std::string errorStr =
"";
894 std::string currentState = theSupervisor->theStateMachine_.getCurrentStateName();
896 __COUTV__(currentState);
898 bool haltAttempted =
true;
901 __COUT_INFO__ <<
"Iterator is leaving FSM in current state: " << currentState
902 <<
". If this is undesireable, add a Halt command, for example, to "
903 "the end of your Iteration plan."
905 haltAttempted =
false;
907 else if(currentState == RunControlStateMachine::INITIAL_STATE_NAME ||
908 currentState == RunControlStateMachine::HALTED_STATE_NAME)
910 __COUT__ <<
"Do nothing. Already halted." << __E__;
911 haltAttempted =
false;
913 else if(currentState ==
"Running")
914 errorStr = theSupervisor->attemptStateMachineTransition(
917 RunControlStateMachine::ABORT_TRANSITION_NAME,
919 WebUsers::DEFAULT_ITERATOR_USERNAME ,
920 WebUsers::DEFAULT_ITERATOR_USERNAME,
921 fsmCommandParameters);
923 errorStr = theSupervisor->attemptStateMachineTransition(
926 RunControlStateMachine::HALT_TRANSITION_NAME,
928 WebUsers::DEFAULT_ITERATOR_USERNAME ,
929 WebUsers::DEFAULT_ITERATOR_USERNAME,
930 fsmCommandParameters);
936 __SS__ <<
"Iterator failed to halt because of the following error: "
942 __COUT__ <<
"FSM in transition = "
943 << theSupervisor->theStateMachine_.isInTransition() << __E__;
944 __COUT__ <<
"halting state machine launched." << __E__;
948 __COUT__ <<
"Conducting Iterator cleanup." << __E__;
952 __COUT__ <<
"Reverting track changes." << __E__;
953 ConfigurationInterface::setVersionTrackingEnabled(
954 iteratorStruct->originalTrackChanges_);
958 __COUT__ <<
"Activating original group..." << __E__;
961 iteratorStruct->cfgMgr_->activateTableGroup(
962 iteratorStruct->originalConfigGroup_,
963 iteratorStruct->originalConfigKey_);
967 __COUT_WARN__ <<
"Original group could not be activated." << __E__;
974 if(iterator->theSupervisor_->VERBOSE_MUTEX)
975 __COUT__ <<
"Waiting for iterator access" << __E__;
976 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
977 if(iterator->theSupervisor_->VERBOSE_MUTEX)
978 __COUT__ <<
"Have iterator access" << __E__;
980 iterator->activePlanIsRunning_ =
false;
981 iterator->iteratorBusy_ =
false;
984 iterator->activePlanName_ =
"";
985 iterator->activeCommandIndex_ = -1;
989 __COUT__ <<
"Iterator cleanup complete of plan '" << iteratorStruct->activePlan_
990 <<
"' at command index " << iteratorStruct->commandIndex_ <<
". "
993 iterator->lastFinishedPlanName_ = iteratorStruct->activePlan_;
994 FILE* fp = fopen((ITERATOR_PLAN_HISTORY_FILENAME).c_str(),
"w");
997 fprintf(fp,
"%s\n", iterator->lastStartedPlanName_.c_str());
998 fprintf(fp,
"%s\n", iterator->lastFinishedPlanName_.c_str());
1002 __COUT_WARN__ <<
"Could not open Iterator history file: "
1003 << ITERATOR_PLAN_HISTORY_FILENAME << __E__;
1005 iteratorStruct->activePlan_ =
"";
1006 iteratorStruct->commandIndex_ = -1;
1009 return haltAttempted;
1013 void Iterator::startCommandBeginLabel(IteratorWorkLoopStruct* iteratorStruct)
1015 __COUT__ <<
"Entering label '"
1016 << iteratorStruct->commands_[iteratorStruct->commandIndex_]
1017 .params_[IterateTable::commandBeginLabelParams_.Label_]
1018 <<
"'..." << std::endl;
1021 iteratorStruct->stepIndexStack_.push_back(0);
1025 void Iterator::startCommandRepeatLabel(IteratorWorkLoopStruct* iteratorStruct)
1029 int numOfRepetitions;
1030 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1031 .params_[IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_]
1035 __COUT__ <<
"numOfRepetitions remaining = " << numOfRepetitions << __E__;
1039 if(numOfRepetitions <= 0)
1042 sprintf(repStr,
"%d", iteratorStruct->stepIndexStack_.back());
1043 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1044 .params_[IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_] =
1048 iteratorStruct->stepIndexStack_.pop_back();
1056 ++(iteratorStruct->stepIndexStack_.back());
1059 for(i = iteratorStruct->commandIndex_; i > 0;
1062 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1063 .params_[IterateTable::commandRepeatLabelParams_.Label_] ==
1064 iteratorStruct->commands_[i]
1065 .params_[IterateTable::commandBeginLabelParams_.Label_])
1068 sprintf(repStr,
"%d", numOfRepetitions);
1069 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1070 .params_[IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_] =
1073 iteratorStruct->commandIndex_ = i;
1074 __COUT__ <<
"Jumping back to commandIndex " << iteratorStruct->commandIndex_ << __E__;
1078 void Iterator::startCommandRun(IteratorWorkLoopStruct* iteratorStruct)
1080 __COUT__ <<
"startCommandRun " << __E__;
1082 iteratorStruct->runIsDone_ =
false;
1083 iteratorStruct->fsmCommandParameters_.clear();
1085 std::string errorStr =
"";
1086 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1087 ->theStateMachine_.getCurrentStateName();
1091 __COUTTV__(iteratorStruct->theIterator_->genLogEntry_);
1093 if(currentState == RunControlStateMachine::CONFIGURED_STATE_NAME)
1095 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1098 RunControlStateMachine::START_TRANSITION_NAME,
1099 iteratorStruct->fsmName_,
1100 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1101 WebUsers::DEFAULT_ITERATOR_USERNAME,
1102 iteratorStruct->fsmCommandParameters_,
1103 iteratorStruct->activePlan_ == Iterator::RESERVED_GEN_PLAN_NAME
1104 ? iteratorStruct->theIterator_->genLogEntry_
1107 errorStr =
"Can only Run from the Configured state. The current state is " +
1112 __SS__ <<
"Iterator failed to run because of the following error: " << errorStr;
1117 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1118 .params_[IterateTable::commandRunParams_.DurationInSeconds_]
1121 &iteratorStruct->originalDurationInSeconds_);
1122 __COUTV__(iteratorStruct->originalDurationInSeconds_);
1126 <<
"FSM in transition = "
1127 << iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition()
1129 __COUT__ <<
"startCommandRun success." << __E__;
1133 void Iterator::startCommandConfigureActive(IteratorWorkLoopStruct* iteratorStruct)
1135 __COUT__ <<
"startCommandConfigureActive " << __E__;
1141 std::string group = iteratorStruct->cfgMgr_->getActiveGroupName();
1142 TableGroupKey key = iteratorStruct->cfgMgr_->getActiveGroupKey();
1144 __COUT__ <<
"group " << group << __E__;
1145 __COUT__ <<
"key " << key << __E__;
1149 std::stringstream systemAlias;
1150 systemAlias <<
"GROUP:" << group <<
":" << key;
1151 startCommandConfigureAlias(iteratorStruct, systemAlias.str());
1155 void Iterator::startCommandConfigureGroup(IteratorWorkLoopStruct* iteratorStruct)
1157 __COUT__ <<
"startCommandConfigureGroup " << __E__;
1163 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1164 .params_[IterateTable::commandConfigureGroupParams_.GroupName_];
1166 TableGroupKey(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1167 .params_[IterateTable::commandConfigureGroupParams_.GroupKey_]);
1169 __COUT__ <<
"group " << group << __E__;
1170 __COUT__ <<
"key " << key << __E__;
1174 std::stringstream systemAlias;
1175 systemAlias <<
"GROUP:" << group <<
":" << key;
1176 startCommandConfigureAlias(iteratorStruct, systemAlias.str());
1180 void Iterator::startCommandConfigureAlias(IteratorWorkLoopStruct* iteratorStruct,
1181 const std::string& systemAlias)
1183 __COUT__ <<
"systemAlias " << systemAlias << __E__;
1185 iteratorStruct->fsmCommandParameters_.clear();
1186 iteratorStruct->fsmCommandParameters_.push_back(systemAlias);
1188 std::string errorStr =
"";
1189 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1190 ->theStateMachine_.getCurrentStateName();
1194 if(currentState == RunControlStateMachine::INITIAL_STATE_NAME)
1196 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1199 RunControlStateMachine::INIT_TRANSITION_NAME,
1200 iteratorStruct->fsmName_,
1201 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1202 WebUsers::DEFAULT_ITERATOR_USERNAME,
1203 iteratorStruct->fsmCommandParameters_);
1204 else if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
1206 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1209 RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
1210 iteratorStruct->fsmName_,
1211 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1212 WebUsers::DEFAULT_ITERATOR_USERNAME,
1213 iteratorStruct->fsmCommandParameters_);
1214 else if(currentState == RunControlStateMachine::CONFIGURED_STATE_NAME ||
1215 currentState == RunControlStateMachine::FAILED_STATE_NAME)
1217 if(iteratorStruct->onlyConfigIfNotConfigured_ &&
1218 currentState != RunControlStateMachine::FAILED_STATE_NAME)
1219 __COUT__ <<
"Already configured, so do nothing!" << __E__;
1221 errorStr = iteratorStruct->theIterator_->theSupervisor_
1222 ->attemptStateMachineTransition(
1225 RunControlStateMachine::HALT_TRANSITION_NAME,
1226 iteratorStruct->fsmName_,
1227 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1228 WebUsers::DEFAULT_ITERATOR_USERNAME,
1229 iteratorStruct->fsmCommandParameters_);
1233 "Can only Configure from the Initial or Halted state. The current state is " +
1238 __SS__ <<
"Iterator failed to configure with system alias '"
1239 << (iteratorStruct->fsmCommandParameters_.size()
1240 ? iteratorStruct->fsmCommandParameters_[0]
1242 <<
"' because of the following error: " << errorStr;
1248 <<
"FSM in transition = "
1249 << iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition()
1251 __COUT__ <<
"startCommandConfigureAlias success." << __E__;
1255 void Iterator::startCommandFSMTransition(IteratorWorkLoopStruct* iteratorStruct,
1256 const std::string& transitionCommand)
1258 __COUTV__(transitionCommand);
1260 iteratorStruct->fsmCommandParameters_.clear();
1262 std::string errorStr =
"";
1263 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1264 ->theStateMachine_.getCurrentStateName();
1268 __COUTV__(currentState);
1271 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1275 iteratorStruct->fsmName_,
1276 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1277 WebUsers::DEFAULT_ITERATOR_USERNAME,
1278 iteratorStruct->fsmCommandParameters_,
1279 (transitionCommand == RunControlStateMachine::START_TRANSITION_NAME &&
1280 iteratorStruct->activePlan_ == Iterator::RESERVED_GEN_PLAN_NAME)
1281 ? iteratorStruct->theIterator_->genLogEntry_
1286 __SS__ <<
"Iterator failed to " << transitionCommand <<
" with ";
1287 if(iteratorStruct->fsmCommandParameters_.size() == 0)
1288 ss <<
"no parameters ";
1290 ss <<
"parameters '"
1293 ss <<
"' because of the following error: " << errorStr;
1299 <<
"FSM in transition = "
1300 << iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition()
1302 __COUT__ <<
"startCommandFSMTransition success." << __E__;
1306 void Iterator::startCommandMacro(IteratorWorkLoopStruct* iteratorStruct,
1307 bool isFrontEndMacro)
1315 const std::string& macroName =
1316 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1317 .params_[IterateTable::commandExecuteMacroParams_.MacroName_];
1318 const std::string& enableSavingOutput =
1319 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1320 .params_[IterateTable::commandExecuteMacroParams_.EnableSavingOutput_];
1321 const std::string& outputFilePath =
1322 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1323 .params_[IterateTable::commandExecuteMacroParams_.OutputFilePath_];
1324 const std::string& outputFileRadix =
1325 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1326 .params_[IterateTable::commandExecuteMacroParams_.OutputFileRadix_];
1327 const std::string& inputArgs =
1328 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1329 .params_[IterateTable::commandExecuteMacroParams_.MacroArgumentString_];
1331 __COUTV__(macroName);
1332 __COUTV__(enableSavingOutput);
1333 __COUTV__(outputFilePath);
1334 __COUTV__(outputFileRadix);
1335 __COUTV__(inputArgs);
1343 iteratorStruct->targetsDone_.clear();
1345 __COUTV__(iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_.size());
1346 for(
const auto& target :
1347 iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_)
1349 __COUT__ <<
"target " << target.table_ <<
":" << target.UID_ << __E__;
1352 iteratorStruct->targetsDone_.push_back(
false);
1354 xoap::MessageReference message =
1355 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1358 std::string type = isFrontEndMacro ?
"feMacroMultiDimensionalStart"
1359 :
"macroMultiDimensionalStart";
1360 parameters.addParameter(
"type", type);
1361 parameters.addParameter(
"requester", WebUsers::DEFAULT_ITERATOR_USERNAME);
1362 parameters.addParameter(
"targetInterfaceID", target.UID_);
1363 parameters.addParameter(isFrontEndMacro ?
"feMacroName" :
"macroName", macroName);
1364 parameters.addParameter(
"enableSavingOutput", enableSavingOutput);
1365 parameters.addParameter(
"outputFilePath", outputFilePath);
1366 parameters.addParameter(
"outputFileRadix", outputFileRadix);
1367 parameters.addParameter(
"inputArgs", inputArgs);
1368 SOAPUtilities::addParameters(message, parameters);
1370 __COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1373 xoap::MessageReference replyMessage =
1374 iteratorStruct->theIterator_->theSupervisor_
1375 ->SOAPMessenger::sendWithSOAPReply(
1376 iteratorStruct->theIterator_->theSupervisor_->allSupervisorInfo_
1377 .getAllMacroMakerTypeSupervisorInfo()
1379 ->second.getDescriptor(),
1382 __COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
1386 rxParameters.addParameter(
"Error");
1387 std::string response = SOAPUtilities::receive(replyMessage, rxParameters);
1389 std::string error = rxParameters.getValue(
"Error");
1391 if(response != type +
"Done" || error !=
"")
1394 __SS__ <<
"Error transmitting request to target interface '" << target.UID_
1395 <<
"' from '" << WebUsers::DEFAULT_ITERATOR_USERNAME <<
".' Response '"
1396 << response <<
"' with error: " << error << __E__;
1404 bool Iterator::checkCommandMacro(IteratorWorkLoopStruct* iteratorStruct,
1405 bool isFrontEndMacro)
1415 const std::string& macroName =
1416 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1417 .params_[IterateTable::commandExecuteMacroParams_.MacroName_];
1419 __COUTV__(macroName);
1424 for(
unsigned int i = 0;
1425 i < iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_.size();
1429 iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_[i];
1431 __COUT__ <<
"target " << target.table_ <<
":" << target.UID_ << __E__;
1433 xoap::MessageReference message =
1434 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1437 std::string type = isFrontEndMacro ?
"feMacroMultiDimensionalCheck"
1438 :
"macroMultiDimensionalCheck";
1439 parameters.addParameter(
"type", type);
1440 parameters.addParameter(
"requester", WebUsers::DEFAULT_ITERATOR_USERNAME);
1441 parameters.addParameter(
"targetInterfaceID", target.UID_);
1442 parameters.addParameter(isFrontEndMacro ?
"feMacroName" :
"macroName", macroName);
1443 SOAPUtilities::addParameters(message, parameters);
1445 __COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1448 xoap::MessageReference replyMessage =
1449 iteratorStruct->theIterator_->theSupervisor_
1450 ->SOAPMessenger::sendWithSOAPReply(
1451 iteratorStruct->theIterator_->theSupervisor_->allSupervisorInfo_
1452 .getAllMacroMakerTypeSupervisorInfo()
1454 ->second.getDescriptor(),
1457 __COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
1461 rxParameters.addParameter(
"Error");
1462 rxParameters.addParameter(
"Done");
1463 std::string response = SOAPUtilities::receive(replyMessage, rxParameters);
1465 std::string error = rxParameters.getValue(
"Error");
1466 bool done = rxParameters.getValue(
"Done") ==
"1";
1468 if(response != type +
"Done" || error !=
"")
1471 __SS__ <<
"Error transmitting request to target interface '" << target.UID_
1472 <<
"' from '" << WebUsers::DEFAULT_ITERATOR_USERNAME <<
".' Response '"
1473 << response <<
"' with error: " << error << __E__;
1481 iteratorStruct->targetsDone_[i] =
true;
1493 void Iterator::startCommandModifyActive(IteratorWorkLoopStruct* iteratorStruct)
1514 bool doTrackGroupChanges =
false;
1516 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1517 .params_[IterateTable::commandModifyActiveParams_.DoTrackGroupChanges_])
1518 doTrackGroupChanges =
true;
1520 const std::string& startValueStr =
1521 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1522 .params_[IterateTable::commandModifyActiveParams_.FieldStartValue_];
1523 const std::string& stepSizeStr =
1524 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1525 .params_[IterateTable::commandModifyActiveParams_.FieldIterationStepSize_];
1527 const unsigned int stepIndex = iteratorStruct->stepIndexStack_.back();
1529 __COUT__ <<
"doTrackGroupChanges " << (doTrackGroupChanges ?
"yes" :
"no")
1531 __COUTV__(startValueStr);
1532 __COUTV__(stepSizeStr);
1533 __COUTV__(stepIndex);
1535 ConfigurationInterface::setVersionTrackingEnabled(doTrackGroupChanges);
1540 if(((stepSizeStr.size() && stepSizeStr[0] ==
'0') || !stepSizeStr.size()) &&
1544 __COUT__ <<
"Treating start value as string: " << startValueStr << __E__;
1545 helpCommandModifyActive(iteratorStruct, startValueStr, doTrackGroupChanges);
1547 else if(startValueStr.size() && (startValueStr[startValueStr.size() - 1] ==
'f' ||
1548 startValueStr.find(
'.') != std::string::npos))
1551 double startValue = strtod(startValueStr.c_str(), 0);
1552 double stepSize = strtod(stepSizeStr.c_str(), 0);
1554 __COUT__ <<
"startValue " << startValue << std::endl;
1555 __COUT__ <<
"stepSize " << stepSize << std::endl;
1556 __COUT__ <<
"currentValue " << startValue + stepSize * stepIndex << std::endl;
1558 helpCommandModifyActive(
1559 iteratorStruct, startValue + stepSize * stepIndex, doTrackGroupChanges);
1563 long int startValue;
1569 __COUT__ <<
"startValue " << startValue << std::endl;
1570 __COUT__ <<
"stepSize " << stepSize << std::endl;
1571 __COUT__ <<
"currentValue " << startValue + stepSize * stepIndex << std::endl;
1573 helpCommandModifyActive(
1574 iteratorStruct, startValue + stepSize * stepIndex, doTrackGroupChanges);
1588 bool Iterator::checkCommandRun(IteratorWorkLoopStruct* iteratorStruct)
1597 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
1598 __COUT__ <<
"Waiting for FSM access" << __E__;
1599 std::lock_guard<std::mutex> lock(
1600 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
1601 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
1602 __COUT__ <<
"Have FSM access" << __E__;
1604 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition())
1607 iteratorStruct->fsmCommandParameters_.clear();
1609 std::string errorStr =
"";
1610 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1611 ->theStateMachine_.getCurrentStateName();
1615 if(iteratorStruct->doPauseAction_)
1618 __COUT__ <<
"Transitioning FSM to Paused..." << __E__;
1620 if(currentState ==
"Paused")
1623 __COUT__ <<
"Transition to Paused complete." << __E__;
1626 else if(currentState ==
"Running")
1627 errorStr = iteratorStruct->theIterator_->theSupervisor_
1628 ->attemptStateMachineTransition(
1632 iteratorStruct->fsmName_,
1633 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1634 WebUsers::DEFAULT_ITERATOR_USERNAME,
1635 iteratorStruct->fsmCommandParameters_);
1636 else if(currentState ==
"Configured")
1639 __COUT__ <<
"In Configured state. No need to transition to Paused." << __E__;
1643 errorStr =
"Expected to be in Paused. Unexpectedly, the current state is " +
1645 ". Last State Machine error message was as follows: " +
1646 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1651 __SS__ <<
"Iterator failed to pause because of the following error: "
1657 else if(iteratorStruct->doHaltAction_)
1660 __COUT__ <<
"Transitioning FSM to Halted..." << __E__;
1662 if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
1665 __COUT__ <<
"Transition to Halted complete." << __E__;
1669 RUNNING_STATE_NAME ||
1670 currentState == RunControlStateMachine::PAUSED_STATE_NAME)
1671 errorStr = iteratorStruct->theIterator_->theSupervisor_
1672 ->attemptStateMachineTransition(
1675 RunControlStateMachine::ABORT_TRANSITION_NAME,
1676 iteratorStruct->fsmName_,
1677 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1678 WebUsers::DEFAULT_ITERATOR_USERNAME,
1679 iteratorStruct->fsmCommandParameters_);
1681 CONFIGURED_STATE_NAME)
1682 errorStr = iteratorStruct->theIterator_->theSupervisor_
1683 ->attemptStateMachineTransition(
1686 RunControlStateMachine::HALT_TRANSITION_NAME,
1687 iteratorStruct->fsmName_,
1688 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1689 WebUsers::DEFAULT_ITERATOR_USERNAME,
1690 iteratorStruct->fsmCommandParameters_);
1692 errorStr =
"Expected to be in Halted. Unexpectedly, the current state is " +
1694 ". Last State Machine error message was as follows: " +
1695 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1700 __SS__ <<
"Iterator failed to halt because of the following error: "
1706 else if(iteratorStruct->doResumeAction_)
1711 __COUT__ <<
"Transitioning FSM to Running..." << __E__;
1713 if(currentState ==
"Paused")
1714 errorStr = iteratorStruct->theIterator_->theSupervisor_
1715 ->attemptStateMachineTransition(
1718 RunControlStateMachine::RESUME_TRANSITION_NAME,
1719 iteratorStruct->fsmName_,
1720 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1721 WebUsers::DEFAULT_ITERATOR_USERNAME,
1722 iteratorStruct->fsmCommandParameters_);
1726 __SS__ <<
"Iterator failed to run because of the following error: "
1736 if(currentState !=
"Running")
1738 if(iteratorStruct->runIsDone_ && currentState ==
"Configured")
1741 __COUT__ <<
"Reached end of run " << iteratorStruct->fsmNextRunNumber_
1746 errorStr =
"Expected to be in Running. Unexpectedly, the current state is " +
1747 currentState +
". Last State Machine error message was as follows: " +
1748 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1753 bool waitOnRunningThreads =
false;
1754 if(
"True" == iteratorStruct->commands_[iteratorStruct->commandIndex_]
1755 .params_[IterateTable::commandRunParams_.WaitOnRunningThreads_])
1756 waitOnRunningThreads =
true;
1758 time_t remainingDurationInSeconds;
1759 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1760 .params_[IterateTable::commandRunParams_.DurationInSeconds_]
1763 &remainingDurationInSeconds);
1765 __COUT__ <<
"waitOnRunningThreads " << waitOnRunningThreads << __E__;
1766 __COUT__ <<
"remainingDurationInSeconds " << remainingDurationInSeconds << __E__;
1770 if(waitOnRunningThreads)
1774 iteratorStruct->theIterator_->theSupervisor_;
1776 bool allFrontEndsAreDone =
true;
1777 for(
auto& it : theSupervisor->allSupervisorInfo_.getAllFETypeSupervisorInfo())
1781 std::string status = theSupervisor->
send(it.second.getDescriptor(),
1782 "WorkLoopStatusRequest");
1784 __COUT__ <<
"FESupervisor instance " << it.first
1785 <<
" has status = " << status << std::endl;
1787 if(status != CoreSupervisorBase::WORK_LOOP_DONE)
1789 allFrontEndsAreDone =
false;
1793 catch(xdaq::exception::Exception& e)
1795 __SS__ <<
"Could not retrieve status from FESupervisor instance "
1796 << it.first <<
"." << std::endl;
1797 __COUT_WARN__ << ss.str();
1798 errorStr = ss.str();
1803 <<
"Iterator failed to run because of the following error: "
1810 if(allFrontEndsAreDone)
1813 __COUT__ <<
"FE workloops all complete! Stopping run..." << __E__;
1815 errorStr = iteratorStruct->theIterator_->theSupervisor_
1816 ->attemptStateMachineTransition(
1820 iteratorStruct->fsmName_,
1821 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1822 WebUsers::DEFAULT_ITERATOR_USERNAME,
1823 iteratorStruct->fsmCommandParameters_);
1828 <<
"Iterator failed to stop run because of the following error: "
1834 iteratorStruct->runIsDone_ =
true;
1842 if(remainingDurationInSeconds > 1)
1845 if(remainingDurationInSeconds == iteratorStruct->originalDurationInSeconds_)
1847 iteratorStruct->theIterator_->activeCommandStartTime_ =
1849 __COUT__ <<
"Starting run duration of " << remainingDurationInSeconds
1850 <<
" [s] at time = "
1851 << iteratorStruct->theIterator_->activeCommandStartTime_ <<
" "
1853 iteratorStruct->theIterator_->activeCommandStartTime_)
1857 --remainingDurationInSeconds;
1861 sprintf(str,
"%ld", remainingDurationInSeconds);
1862 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1863 .params_[IterateTable::commandRunParams_.DurationInSeconds_] =
1866 else if(remainingDurationInSeconds == 1)
1869 __COUT__ <<
"Time duration reached! Stopping run..." << __E__;
1871 errorStr = iteratorStruct->theIterator_->theSupervisor_
1872 ->attemptStateMachineTransition(
1876 iteratorStruct->fsmName_,
1877 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1878 WebUsers::DEFAULT_ITERATOR_USERNAME,
1879 iteratorStruct->fsmCommandParameters_);
1883 __SS__ <<
"Iterator failed to stop run because of the following error: "
1889 iteratorStruct->runIsDone_ =
true;
1893 sprintf(str,
"%ld", iteratorStruct->originalDurationInSeconds_);
1894 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1895 .params_[IterateTable::commandRunParams_.DurationInSeconds_] =
1903 __SS__ <<
"Iterator failed to run because of the following error: " << errorStr;
1911 bool Iterator::checkCommandConfigure(IteratorWorkLoopStruct* iteratorStruct)
1920 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
1921 __COUT__ <<
"Waiting for FSM access" << __E__;
1922 std::lock_guard<std::mutex> lock(
1923 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
1924 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
1925 __COUT__ <<
"Have FSM access" << __E__;
1927 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition())
1930 std::string errorStr =
"";
1931 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1932 ->theStateMachine_.getCurrentStateName();
1934 if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
1936 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1940 iteratorStruct->fsmName_,
1941 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1942 WebUsers::DEFAULT_ITERATOR_USERNAME,
1943 iteratorStruct->fsmCommandParameters_);
1944 else if(currentState != RunControlStateMachine::CONFIGURED_STATE_NAME)
1945 errorStr =
"Expected to be in '" + RunControlStateMachine::CONFIGURED_STATE_NAME +
1946 "' state. Unexpectedly, the current state is " + currentState +
"." +
1947 ". Last State Machine error message was as follows: " +
1948 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1952 __COUT__ <<
"checkCommandConfigureAlias complete." << __E__;
1955 std::pair<std::string, TableGroupKey> newActiveGroup =
1956 iteratorStruct->cfgMgr_->getTableGroupFromAlias(
1957 iteratorStruct->fsmCommandParameters_[0]);
1958 iteratorStruct->cfgMgr_->loadTableGroup(
1959 newActiveGroup.first, newActiveGroup.second,
true );
1961 __COUT__ <<
"originalTrackChanges " << iteratorStruct->originalTrackChanges_
1963 __COUT__ <<
"originalConfigGroup " << iteratorStruct->originalConfigGroup_
1965 __COUT__ <<
"originalConfigKey " << iteratorStruct->originalConfigKey_ << __E__;
1967 __COUT__ <<
"currentTrackChanges "
1968 << ConfigurationInterface::isVersionTrackingEnabled() << __E__;
1969 __COUT__ <<
"originalConfigGroup "
1970 << iteratorStruct->cfgMgr_->getActiveGroupName() << __E__;
1971 __COUT__ <<
"originalConfigKey " << iteratorStruct->cfgMgr_->getActiveGroupKey()
1979 __SS__ <<
"Iterator failed to configure with system alias '"
1980 << (iteratorStruct->fsmCommandParameters_.size()
1981 ? iteratorStruct->fsmCommandParameters_[0]
1983 <<
"' because of the following error: " << errorStr;
1991 bool Iterator::checkCommandFSMTransition(IteratorWorkLoopStruct* iteratorStruct,
1992 const std::string& finalState)
1994 __COUTV__(finalState);
2003 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
2004 __COUT__ <<
"Waiting for FSM access" << __E__;
2005 std::lock_guard<std::mutex> lock(
2006 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
2007 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
2008 __COUT__ <<
"Have FSM access" << __E__;
2010 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition())
2013 std::string errorStr =
"";
2014 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
2015 ->theStateMachine_.getCurrentStateName();
2017 if(currentState != finalState)
2018 errorStr =
"Expected to be in " + finalState +
2019 ". Unexpectedly, the current state is " + currentState +
"." +
2020 ". Last State Machine error message was as follows: " +
2021 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
2025 __COUT__ <<
"checkCommandFSMTransition complete." << __E__;
2032 __SS__ <<
"Iterator failed to reach final state '" << finalState
2033 <<
"' because of the following error: " << errorStr;
2041 std::vector<IterateTable::Command> Iterator::generateIterationPlan(
2042 const std::string& fsmName,
2043 const std::string& configAlias,
2044 uint64_t durationSeconds ,
2045 unsigned int numberOfRuns )
2047 std::vector<IterateTable::Command> commands;
2057 if(durationSeconds == (uint64_t)-1)
2059 __COUTV__(durationSeconds);
2060 __COUTV__(numberOfRuns);
2065 commands.back().type_ = IterateTable::COMMAND_CHOOSE_FSM;
2067 commands.back().params_.emplace(
2068 std::pair<std::string /*param name*/, std::string /*param value*/>(
2069 IterateTable::commandChooseFSMParams_.NameOfFSM_, fsmName));
2075 commands.back().type_ = IterateTable::COMMAND_CONFIGURE_ALIAS;
2077 commands.back().params_.emplace(
2078 std::pair<std::string /*param name*/, std::string /*param value*/>(
2079 IterateTable::commandConfigureAliasParams_.SystemAlias_, configAlias));
2082 if(durationSeconds == (uint64_t)-1)
2084 __COUT__ <<
"Open ended run..." << __E__;
2089 commands.back().type_ = IterateTable::COMMAND_START;
2094 __COUT__ <<
"Finite duration run(s)..." << __E__;
2096 if(numberOfRuns > 1)
2098 __COUT__ <<
"Setting up iterator loop for " << numberOfRuns <<
" runs."
2104 commands.back().params_.emplace(
2105 std::pair<std::string /*param name*/, std::string /*param value*/>(
2106 IterateTable::commandBeginLabelParams_.Label_,
"GENERATED_LABEL"));
2112 commands.back().type_ = IterateTable::COMMAND_RUN;
2114 commands.back().params_.emplace(
2115 std::pair<std::string /*param name*/, std::string /*param value*/>(
2116 IterateTable::commandRunParams_.DurationInSeconds_,
2117 std::to_string(durationSeconds)));
2120 if(numberOfRuns > 1)
2123 commands.back().type_ = IterateTable::COMMAND_REPEAT_LABEL;
2125 commands.back().params_.emplace(
2126 std::pair<std::string /*param name*/, std::string /*param value*/>(
2127 IterateTable::commandRepeatLabelParams_.Label_,
"GENERATED_LABEL"));
2128 commands.back().params_.emplace(
2129 std::pair<std::string /*param name*/, std::string /*param value*/>(
2130 IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_,
2131 std::to_string(numberOfRuns -
2137 __COUTV__(commands.size());
2144 const std::string& command,
2145 const std::string& parameter)
2149 if(command ==
"iteratePlay")
2151 playIterationPlan(xmldoc, parameter);
2154 else if(command ==
"iteratePlayGenerated")
2156 playGeneratedIterationPlan(xmldoc, parameter);
2159 else if(command ==
"iteratePause")
2161 pauseIterationPlan(xmldoc);
2164 else if(command ==
"iterateHalt")
2166 haltIterationPlan(xmldoc);
2169 else if(command ==
"getIterationPlanStatus")
2171 if(activePlanName_ ==
"" &&
2175 activePlanName_ = parameter;
2176 __COUTV__(activePlanName_);
2185 if(theSupervisor_->VERBOSE_MUTEX)
2186 __COUT__ <<
"Waiting for iterator access" << __E__;
2187 std::lock_guard<std::mutex> lock(accessMutex_);
2188 if(theSupervisor_->VERBOSE_MUTEX)
2189 __COUT__ <<
"Have iterator access" << __E__;
2193 __SS__ <<
"Error - Can not accept request because the Iterator "
2195 <<
"in control of State Machine progress. ";
2196 __COUT_ERR__ <<
"\n" << ss.str();
2197 __COUT_ERR__ <<
"\n" << ss.str();
2199 xmldoc.addTextElementToData(
"state_tranisition_attempted",
2201 xmldoc.addTextElementToData(
2202 "state_tranisition_attempted_err",
2204 theSupervisor_->theStateMachine_.setErrorMessage(ss.str());
2212 __SS__ <<
"Error caught by Iterator command handling!" << __E__;
2217 catch(
const std::runtime_error& e)
2219 ss <<
"\nHere is the error: " << e.what() << __E__;
2223 ss <<
"Uknown error caught." << __E__;
2226 __COUT_ERR__ <<
"\n" << ss.str();
2228 xmldoc.addTextElementToData(
"state_tranisition_attempted",
2230 xmldoc.addTextElementToData(
"state_tranisition_attempted_err",
2232 theSupervisor_->theStateMachine_.setErrorMessage(ss.str());
2237 void Iterator::playIterationPlan(
HttpXmlDocument& xmldoc,
const std::string& planName)
2239 __COUT__ <<
"Attempting to play iteration plan '" << planName <<
".'" << __E__;
2241 if(planName == Iterator::RESERVED_GEN_PLAN_NAME)
2243 __SS__ <<
"Illegal use of reserved iteration plan name '"
2244 << Iterator::RESERVED_GEN_PLAN_NAME <<
"!' Please select a different name."
2249 playIterationPlanPrivate(xmldoc, planName);
2255 const std::string& parametersCSV)
2257 __COUTV__(parametersCSV);
2258 std::vector<std::string> parameters =
2261 if(parameters.size() != 6)
2263 __SS__ <<
"Malformed CSV parameters to playGeneratedIterationPlan(), must be 6 "
2264 "arguments and there were "
2265 << parameters.size() <<
": " << parametersCSV << __E__;
2276 uint64_t durationSeconds;
2277 sscanf(parameters[2].c_str(),
"%lu", &durationSeconds);
2278 unsigned int numberOfRuns;
2279 sscanf(parameters[3].c_str(),
"%u", &numberOfRuns);
2280 unsigned int keepConfiguration;
2281 sscanf(parameters[4].c_str(),
"%u", &keepConfiguration);
2282 playGeneratedIterationPlan(xmldoc,
2295 const std::string& fsmName,
2296 const std::string& configAlias,
2297 uint64_t durationSeconds ,
2298 unsigned int numberOfRuns ,
2299 bool keepConfiguration ,
2300 const std::string& logEntry)
2302 std::string planName = Iterator::RESERVED_GEN_PLAN_NAME;
2303 __COUT__ <<
"Attempting to play iteration plan '" << planName <<
".'" << __E__;
2305 genFsmName_ = fsmName;
2306 genConfigAlias_ = configAlias;
2307 genPlanDurationSeconds_ = durationSeconds;
2308 genPlanNumberOfRuns_ = numberOfRuns;
2309 genKeepConfiguration_ = keepConfiguration;
2310 genLogEntry_ = logEntry;
2312 __COUTV__(genFsmName_);
2313 __COUTV__(genConfigAlias_);
2314 __COUTV__(genPlanDurationSeconds_);
2315 __COUTV__(genPlanNumberOfRuns_);
2316 __COUTV__(genKeepConfiguration_);
2317 __COUTV__(genLogEntry_);
2319 playIterationPlanPrivate(xmldoc, planName);
2326 const std::string& planName)
2332 if(theSupervisor_->VERBOSE_MUTEX)
2333 __COUT__ <<
"Waiting for iterator access" << __E__;
2334 std::lock_guard<std::mutex> lock(accessMutex_);
2335 if(theSupervisor_->VERBOSE_MUTEX)
2336 __COUT__ <<
"Have iterator access" << __E__;
2338 if(!activePlanIsRunning_ && !commandPlay_)
2340 if(!workloopRunning_)
2344 workloopRunning_ =
true;
2347 std::thread([](
Iterator* iterator) { Iterator::IteratorWorkLoop(iterator); },
2352 activePlanName_ = planName;
2353 commandPlay_ =
true;
2357 __SS__ <<
"Invalid play command attempted. Can only play when the Iterator is "
2358 "inactive or paused."
2359 <<
" If you would like to restart an iteration plan, first try halting "
2362 __COUT__ << ss.str();
2364 xmldoc.addTextElementToData(
"error_message", ss.str());
2366 __COUT__ <<
"Invalid play command attempted. " << activePlanIsRunning_ <<
" "
2367 << commandPlay_ <<
" " << activePlanName_ << __E__;
2374 __COUT__ <<
"Attempting to pause iteration plan '" << activePlanName_ <<
".'"
2376 __COUT__ <<
"Attempting to pause iteration plan '" << activePlanName_ <<
".'"
2383 if(theSupervisor_->VERBOSE_MUTEX)
2384 __COUT__ <<
"Waiting for iterator access" << __E__;
2385 std::lock_guard<std::mutex> lock(accessMutex_);
2386 if(theSupervisor_->VERBOSE_MUTEX)
2387 __COUT__ <<
"Have iterator access" << __E__;
2389 if(workloopRunning_ && activePlanIsRunning_ && !commandPause_)
2391 commandPause_ =
true;
2395 __SS__ <<
"Invalid pause command attempted. Can only pause when running."
2397 __COUT__ << ss.str();
2399 xmldoc.addTextElementToData(
"error_message", ss.str());
2401 __COUT__ <<
"Invalid pause command attempted. " << workloopRunning_ <<
" "
2402 << activePlanIsRunning_ <<
" " << commandPause_ <<
" " << activePlanName_
2410 __COUT__ <<
"Attempting to halt iteration plan '" << activePlanName_ <<
".'" << __E__;
2411 __COUT__ <<
"Attempting to halt iteration plan '" << activePlanName_ <<
".'" << __E__;
2415 if(workloopRunning_)
2419 if(theSupervisor_->VERBOSE_MUTEX)
2420 __COUT__ <<
"Waiting for iterator access" << __E__;
2421 std::lock_guard<std::mutex> lock(accessMutex_);
2422 if(theSupervisor_->VERBOSE_MUTEX)
2423 __COUT__ <<
"Have iterator access" << __E__;
2425 __COUT__ <<
"activePlanIsRunning_: " << activePlanIsRunning_ << __E__;
2426 __COUT__ <<
"Passing halt command to iterator thread." << __E__;
2427 commandHalt_ =
true;
2430 activePlanName_ =
"";
2431 activeCommandIndex_ = -1;
2435 __COUT__ <<
"No thread, so conducting halt." << __E__;
2436 Iterator::haltIterator(
this);
2444 xmldoc.addTextElementToData(
2446 theSupervisor_->theStateMachine_.isInTransition()
2447 ? theSupervisor_->theStateMachine_.getCurrentTransitionName(
2448 theSupervisor_->stateMachineLastCommandInput_)
2449 : theSupervisor_->theStateMachine_.getCurrentStateName());
2453 if(theSupervisor_->theStateMachine_.isInTransition())
2454 xmldoc.addTextElementToData(
2455 "transition_progress",
2458 xmldoc.addTextElementToData(
"transition_progress",
"100");
2460 xmldoc.addNumberElementToData(
"time_in_state",
2465 if(theSupervisor_->VERBOSE_MUTEX)
2466 __COUT__ <<
"Waiting for iterator access" << __E__;
2467 std::lock_guard<std::mutex> lock(accessMutex_);
2468 if(theSupervisor_->VERBOSE_MUTEX)
2469 __COUT__ <<
"Have iterator access" << __E__;
2471 xmldoc.addTextElementToData(
"active_plan", activePlanName_);
2472 xmldoc.addTextElementToData(
"last_started_plan", lastStartedPlanName_);
2473 xmldoc.addTextElementToData(
"last_finished_plan", lastFinishedPlanName_);
2475 xmldoc.addNumberElementToData(
"current_command_index", activeCommandIndex_);
2476 xmldoc.addNumberElementToData(
"current_number_of_commands", activeNumberOfCommands_);
2477 xmldoc.addTextElementToData(
"current_command_type", activeCommandType_);
2478 xmldoc.addNumberElementToData(
"current_command_duration",
2479 time(0) - activeCommandStartTime_);
2480 xmldoc.addNumberElementToData(
"current_command_iteration", activeCommandIteration_);
2481 for(
const auto& depthIteration : depthIterationStack_)
2482 xmldoc.addNumberElementToData(
"depth_iteration", depthIteration);
2484 if(activePlanName_ == Iterator::RESERVED_GEN_PLAN_NAME)
2486 xmldoc.addNumberElementToData(
"generated_number_of_runs", genPlanNumberOfRuns_);
2487 xmldoc.addNumberElementToData(
"generated_duration_of_runs",
2488 genPlanDurationSeconds_);
2491 if(activePlanIsRunning_ && iteratorBusy_)
2493 if(workloopRunning_)
2494 xmldoc.addTextElementToData(
"active_plan_status",
"Running");
2496 xmldoc.addTextElementToData(
"active_plan_status",
"Error");
2498 else if(!activePlanIsRunning_ && iteratorBusy_)
2499 xmldoc.addTextElementToData(
"active_plan_status",
"Paused");
2501 xmldoc.addTextElementToData(
"active_plan_status",
"Inactive");
2503 xmldoc.addTextElementToData(
"error_message", errorMessage_);
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false)
std::pair< std::string, TableGroupKey > getTableGroupFromAlias(std::string systemAlias, ProgressBar *progressBar=0)
Getters.
bool isDisconnected(void) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
void getValue(T &value) const
time_t getTimeInState(void) const
static const std::string COMMAND_BEGIN_LABEL
void getIterationPlanStatus(HttpXmlDocument &xmldoc)
return state machine and iterator status
std::string readPercentageString()
return percentage complete as std::string
std::string send(XDAQ_CONST_CALL xdaq::ApplicationDescriptor *d, xoap::MessageReference message)
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
vectorToString ~
static bool isNumber(const std::string &stringToCheck)
Note: before call consider use of stringToCheck = StringMacros::convertEnvironmentVariables(stringToC...
static std::string decodeURIComponent(const std::string &data)
static bool getNumber(const std::string &s, T &retValue)