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;
146 iterator->errorMessage_ =
"";
148 if(theIteratorStruct.activePlan_ != iterator->activePlanName_)
150 __COUT__ <<
"New plan name encountered old="
151 << theIteratorStruct.activePlan_
152 <<
" vs new=" << iterator->activePlanName_ << __E__;
153 theIteratorStruct.commandIndex_ = -1;
156 theIteratorStruct.activePlan_ = iterator->activePlanName_;
157 iterator->lastStartedPlanName_ = iterator->activePlanName_;
158 FILE* fp = fopen((ITERATOR_PLAN_HISTORY_FILENAME).c_str(),
"w");
161 fprintf(fp,
"%s\n", iterator->lastStartedPlanName_.c_str());
162 fprintf(fp,
"%s\n", iterator->lastFinishedPlanName_.c_str());
166 __COUT_WARN__ <<
"Could not open Iterator history file: "
167 << ITERATOR_PLAN_HISTORY_FILENAME << __E__;
169 if(theIteratorStruct.commandIndex_ == (
unsigned int)-1)
171 __COUT__ <<
"Starting plan '" << theIteratorStruct.activePlan_
173 __COUT__ <<
"Starting plan '" << theIteratorStruct.activePlan_
178 theIteratorStruct.doResumeAction_ =
true;
179 __COUT__ <<
"Continuing plan '"
180 << theIteratorStruct.activePlan_
181 <<
"' at command index "
182 << theIteratorStruct.commandIndex_ <<
". " << __E__;
183 __COUT__ <<
"Continuing plan '"
184 << theIteratorStruct.activePlan_
185 <<
"' at command index "
186 << theIteratorStruct.commandIndex_ <<
". " << __E__;
190 else if(iterator->commandPause_ && !theIteratorStruct.doPauseAction_)
192 theIteratorStruct.doPauseAction_ =
true;
193 iterator->commandPause_ =
false;
195 else if(iterator->commandHalt_ && !theIteratorStruct.doHaltAction_)
197 theIteratorStruct.doHaltAction_ =
true;
198 iterator->commandHalt_ =
false;
201 theIteratorStruct.running_ = iterator->activePlanIsRunning_;
204 ->activeCommandIndex_ !=
205 theIteratorStruct.commandIndex_)
207 iterator->activeCommandIndex_ = theIteratorStruct.commandIndex_;
208 if(theIteratorStruct.commandIndex_ <
209 theIteratorStruct.commands_.size())
210 iterator->activeCommandType_ =
211 theIteratorStruct.commands_[theIteratorStruct.commandIndex_]
214 iterator->activeCommandType_ =
"";
215 iterator->activeCommandStartTime_ = time(0);
217 if(theIteratorStruct.commandIndex_ <
218 theIteratorStruct.commandIterations_.size())
219 iterator->activeCommandIteration_ =
221 .commandIterations_[theIteratorStruct.commandIndex_];
223 iterator->activeCommandIteration_ = -1;
225 iterator->depthIterationStack_.clear();
226 for(
const auto& depthIteration : theIteratorStruct.stepIndexStack_)
227 iterator->depthIterationStack_.push_back(depthIteration);
233 iterator->activeNumberOfCommands_ =
234 theIteratorStruct.commands_.size();
243 if(theIteratorStruct.doPauseAction_)
250 __COUT__ <<
"Waiting to pause..." << __E__;
251 while(!iterator->checkCommand(&theIteratorStruct))
252 __COUT__ <<
"Waiting to pause..." << __E__;
254 __COUT__ <<
"Completing pause..." << __E__;
256 theIteratorStruct.doPauseAction_ =
false;
260 if(iterator->theSupervisor_->VERBOSE_MUTEX)
261 __COUT__ <<
"Waiting for iterator access" << __E__;
262 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
263 if(iterator->theSupervisor_->VERBOSE_MUTEX)
264 __COUT__ <<
"Have iterator access" << __E__;
266 iterator->activePlanIsRunning_ =
false;
268 __COUT__ <<
"Paused plan '" << theIteratorStruct.activePlan_
269 <<
"' at command index " << theIteratorStruct.commandIndex_
271 __COUT__ <<
"Paused plan '" << theIteratorStruct.activePlan_
272 <<
"' at command index " << theIteratorStruct.commandIndex_
277 else if(theIteratorStruct.doHaltAction_)
286 __COUT__ <<
"Waiting to halt..." << __E__;
287 while(!iterator->checkCommand(&theIteratorStruct))
288 __COUT__ <<
"Waiting to halt..." << __E__;
292 __COUT_INFO__ <<
"Current command threw during halt — "
293 <<
"proceeding to halt anyway." << __E__;
296 __COUT__ <<
"Completing halt..." << __E__;
298 theIteratorStruct.doHaltAction_ =
false;
300 iterator->haltIterator(iterator, &theIteratorStruct);
340 if(theIteratorStruct.running_ &&
341 theIteratorStruct.activePlan_ !=
344 if(theIteratorStruct.commandIndex_ == (
unsigned int)-1)
350 __COUT__ <<
"Get commands" << __E__;
352 theIteratorStruct.cfgMgr_
355 if(theIteratorStruct.activePlan_ ==
356 Iterator::RESERVED_GEN_PLAN_NAME)
358 __COUT__ <<
"Using generated plan..." << __E__;
359 theIteratorStruct.onlyConfigIfNotConfigured_ =
360 iterator->genKeepConfiguration_;
361 theIteratorStruct.commands_ =
362 generateIterationPlan(iterator->genFsmName_,
363 iterator->genConfigAlias_,
364 iterator->genPlanDurationSeconds_,
365 iterator->genPlanNumberOfRuns_);
369 __COUT__ <<
"Getting iterator table..." << __E__;
371 theIteratorStruct.cfgMgr_->__GET_CONFIG__(
IterateTable);
372 theIteratorStruct.onlyConfigIfNotConfigured_ =
false;
373 theIteratorStruct.commands_ = itConfig->getPlanCommands(
374 theIteratorStruct.cfgMgr_, theIteratorStruct.activePlan_);
379 theIteratorStruct.commandIterations_.clear();
380 theIteratorStruct.stepIndexStack_.clear();
381 theIteratorStruct.stepLabelStack_.clear();
382 theIteratorStruct.outputFiles_.clear();
383 for(
auto& command : theIteratorStruct.commands_)
385 theIteratorStruct.commandIterations_.push_back(0);
386 __COUT__ <<
"command " << command.type_ << __E__;
388 << IterateTable::commandToTableMap_.at(command.type_)
390 __COUT__ <<
"param count = " << command.params_.size()
393 for(
auto& param : command.params_)
395 __COUT__ <<
"\t param " << param.first <<
" : "
396 << param.second << __E__;
400 theIteratorStruct.originalTrackChanges_ =
401 ConfigurationInterface::isVersionTrackingEnabled();
402 theIteratorStruct.originalConfigGroup_ =
403 theIteratorStruct.cfgMgr_->getActiveGroupName();
404 theIteratorStruct.originalConfigKey_ =
405 theIteratorStruct.cfgMgr_->getActiveGroupKey();
407 __COUT__ <<
"originalTrackChanges "
408 << theIteratorStruct.originalTrackChanges_ << __E__;
409 __COUT__ <<
"originalConfigGroup "
410 << theIteratorStruct.originalConfigGroup_ << __E__;
411 __COUT__ <<
"originalConfigKey "
412 << theIteratorStruct.originalConfigKey_ << __E__;
414 theIteratorStruct.commandIndex_ = 0;
418 if(!theIteratorStruct.commandBusy_)
420 if(theIteratorStruct.commandIndex_ <
421 theIteratorStruct.commands_.size())
424 theIteratorStruct.commandBusy_ =
true;
426 __COUT__ <<
"Iterator starting command "
427 << theIteratorStruct.commandIndex_ + 1 <<
": "
429 .commands_[theIteratorStruct.commandIndex_]
432 __COUT__ <<
"Iterator starting command "
433 << theIteratorStruct.commandIndex_ + 1 <<
": "
435 .commands_[theIteratorStruct.commandIndex_]
439 iterator->startCommand(&theIteratorStruct);
441 else if(theIteratorStruct.commandIndex_ ==
442 theIteratorStruct.commands_.size())
444 __COUT__ <<
"Finished Iteration Plan '"
445 << theIteratorStruct.activePlan_ << __E__;
446 __COUT__ <<
"Finished Iteration Plan '"
447 << theIteratorStruct.activePlan_ << __E__;
449 __COUT__ <<
"Reverting track changes." << __E__;
450 ConfigurationInterface::setVersionTrackingEnabled(
451 theIteratorStruct.originalTrackChanges_);
454 __COUT__ <<
"Activating original group..." << __E__;
457 theIteratorStruct.cfgMgr_->activateTableGroup(
458 theIteratorStruct.originalConfigGroup_,
459 theIteratorStruct.originalConfigKey_);
463 __COUT_WARN__ <<
"Original group could not be activated."
468 __COUT__ <<
"Completing Iteration Plan and cleaning up..."
471 iterator->haltIterator(
472 iterator, &theIteratorStruct,
true );
475 else if(theIteratorStruct.commandBusy_)
478 if(iterator->checkCommand(&theIteratorStruct))
480 theIteratorStruct.commandBusy_ =
false;
482 ++theIteratorStruct.commandIndex_;
484 __COUT__ <<
"Ready for next command. Done with "
485 << theIteratorStruct.commandIndex_ <<
" of "
486 << theIteratorStruct.commands_.size() << __E__;
487 __COUT__ <<
"Iterator ready for next command. Done with "
488 << theIteratorStruct.commandIndex_ <<
" of "
489 << theIteratorStruct.commands_.size() << __E__;
493 if(theIteratorStruct.doResumeAction_)
494 theIteratorStruct.doResumeAction_ =
false;
502 catch(
const std::runtime_error& e)
504 __COUT_ERR__ <<
"Iterator command error (will pause for retry): "
505 << e.what() << __E__;
506 theIteratorStruct.commandBusy_ =
false;
508 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
509 iterator->activePlanIsRunning_ =
false;
510 iterator->errorMessage_ =
511 std::string(
"Error at command ") +
512 std::to_string(theIteratorStruct.commandIndex_) +
" (" +
513 (theIteratorStruct.commandIndex_ < theIteratorStruct.commands_.size()
514 ? theIteratorStruct.commands_[theIteratorStruct.commandIndex_]
521 __COUT_ERR__ <<
"Iterator unknown error (will pause for retry)." << __E__;
522 theIteratorStruct.commandBusy_ =
false;
524 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
525 iterator->activePlanIsRunning_ =
false;
526 iterator->errorMessage_ =
527 std::string(
"Unknown error at command ") +
528 std::to_string(theIteratorStruct.commandIndex_) +
" (" +
529 (theIteratorStruct.commandIndex_ < theIteratorStruct.commands_.size()
530 ? theIteratorStruct.commands_[theIteratorStruct.commandIndex_]
544 catch(
const std::runtime_error& e)
546 if(theIteratorStruct.activePlan_ !=
"")
548 __SS__ <<
"The active Iterator plan name is '"
549 << theIteratorStruct.activePlan_
550 <<
"'... Here was the error: " << e.what() << __E__;
557 iterator->workloopRunning_ =
false;
559 catch(
const std::runtime_error& e)
561 __SS__ <<
"Encountered error in Iterator thread. Here is the error:\n"
562 << e.what() << __E__;
563 __COUT_ERR__ << ss.str();
567 if(iterator->theSupervisor_->VERBOSE_MUTEX)
568 __COUT__ <<
"Waiting for iterator access" << __E__;
569 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
570 if(iterator->theSupervisor_->VERBOSE_MUTEX)
571 __COUT__ <<
"Have iterator access" << __E__;
573 iterator->workloopRunning_ =
false;
574 iterator->errorMessage_ = ss.str();
578 __SS__ <<
"Encountered unknown error in Iterator thread." << __E__;
583 catch(
const std::exception& e)
585 ss <<
"Exception message: " << e.what();
590 __COUT_ERR__ << ss.str();
594 if(iterator->theSupervisor_->VERBOSE_MUTEX)
595 __COUT__ <<
"Waiting for iterator access" << __E__;
596 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
597 if(iterator->theSupervisor_->VERBOSE_MUTEX)
598 __COUT__ <<
"Have iterator access" << __E__;
600 iterator->workloopRunning_ =
false;
601 iterator->errorMessage_ = ss.str();
605 void Iterator::startCommand(IteratorWorkLoopStruct* iteratorStruct)
610 for(
const auto& depthIteration : iteratorStruct->stepIndexStack_)
612 __COUT__ << i++ <<
":" << depthIteration << __E__;
619 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
620 __COUT__ <<
"Waiting for FSM access" << __E__;
621 std::lock_guard<std::mutex> lock(
622 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
623 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
624 __COUT__ <<
"Have FSM access" << __E__;
627 if(iteratorStruct->commandIndex_ >= iteratorStruct->commands_.size())
629 __SS__ <<
"Out of range commandIndex = " << iteratorStruct->commandIndex_
630 <<
" in size = " << iteratorStruct->commands_.size() << __E__;
635 ++iteratorStruct->commandIterations_[iteratorStruct->commandIndex_];
637 std::string type = iteratorStruct->commands_[iteratorStruct->commandIndex_].type_;
638 const std::string& targetSubsystem =
639 iteratorStruct->commands_[iteratorStruct->commandIndex_].targetSubsystem_;
642 if(targetSubsystem.size() &&
643 (type == IterateTable::COMMAND_ACTIVATE_ALIAS ||
644 type == IterateTable::COMMAND_ACTIVATE_GROUP ||
645 type == IterateTable::COMMAND_MODIFY_ACTIVE_GROUP ||
646 type == IterateTable::COMMAND_RUN || type == IterateTable::COMMAND_WAIT ||
648 type == IterateTable::COMMAND_REPEAT_LABEL ||
649 type == IterateTable::COMMAND_CHOOSE_FSM))
651 __SS__ <<
"Command type '" << type <<
"' can not target a remote subsystem ('"
652 << targetSubsystem <<
"'). Clear the TargetSubsystem for this command."
659 return startCommandBeginLabel(iteratorStruct);
661 else if(type == IterateTable::COMMAND_CHOOSE_FSM)
663 return startCommandChooseFSM(
665 iteratorStruct->commands_[iteratorStruct->commandIndex_]
666 .params_[IterateTable::commandChooseFSMParams_.NameOfFSM_]);
668 else if(type == IterateTable::COMMAND_CONFIGURE_ACTIVE_GROUP)
670 if(targetSubsystem.size())
673 std::string groupAlias;
675 std::lock_guard<std::mutex> lock(
676 iteratorStruct->theIterator_->theSupervisor_
677 ->remoteGatewayAppsMutex_);
678 const auto& remoteApp = iteratorStruct->theIterator_->theSupervisor_
679 ->remoteGatewayApps_[findRemoteGatewayApp(
680 iteratorStruct, targetSubsystem)];
681 if(remoteApp.activeConfigGroupName ==
"" ||
682 remoteApp.activeConfigGroupKey.isInvalid())
684 __SS__ <<
"Remote subsystem '" << targetSubsystem
685 <<
"' has not reported an active configuration group yet, "
686 "so CONFIGURE_ACTIVE_GROUP can not be applied to it."
690 groupAlias =
"GROUP:" + remoteApp.activeConfigGroupName +
":" +
691 remoteApp.activeConfigGroupKey.toString();
693 return startRemoteCommandConfigure(
694 iteratorStruct, groupAlias, targetSubsystem);
696 return startCommandConfigureActive(iteratorStruct);
698 else if(type == IterateTable::COMMAND_CONFIGURE_ALIAS)
700 const std::string& systemAlias =
701 iteratorStruct->commands_[iteratorStruct->commandIndex_]
702 .params_[IterateTable::commandConfigureAliasParams_.SystemAlias_];
703 if(targetSubsystem.size())
704 return startRemoteCommandConfigure(
705 iteratorStruct, systemAlias, targetSubsystem);
706 return startCommandConfigureAlias(iteratorStruct, systemAlias);
708 else if(type == IterateTable::COMMAND_CONFIGURE_GROUP)
710 if(targetSubsystem.size())
713 iteratorStruct->commands_[iteratorStruct->commandIndex_].params_;
714 std::string groupAlias =
715 "GROUP:" + params[IterateTable::commandConfigureGroupParams_.GroupName_] +
716 ":" + params[IterateTable::commandConfigureGroupParams_.GroupKey_];
717 return startRemoteCommandConfigure(
718 iteratorStruct, groupAlias, targetSubsystem);
720 return startCommandConfigureGroup(iteratorStruct);
722 else if(type == IterateTable::COMMAND_ACTIVATE_ALIAS)
725 std::pair<std::string, TableGroupKey> newActiveGroup =
727 iteratorStruct->commands_[iteratorStruct->commandIndex_]
728 .params_[IterateTable::commandActivateAliasParams_.SystemAlias_]);
730 newActiveGroup.first, newActiveGroup.second,
true );
732 else if(type == IterateTable::COMMAND_ACTIVATE_GROUP)
736 iteratorStruct->commands_[iteratorStruct->commandIndex_]
737 .params_[IterateTable::commandActivateGroupParams_.GroupName_],
739 iteratorStruct->commands_[iteratorStruct->commandIndex_]
740 .params_[IterateTable::commandActivateGroupParams_.GroupKey_]),
743 else if(type == IterateTable::COMMAND_EXECUTE_FE_MACRO)
745 if(targetSubsystem.size())
746 return startRemoteCommandMacro(iteratorStruct,
true );
747 return startCommandMacro(iteratorStruct,
true );
749 else if(type == IterateTable::COMMAND_EXECUTE_MM_MACRO)
751 if(targetSubsystem.size())
752 return startRemoteCommandMacro(iteratorStruct,
false );
753 return startCommandMacro(iteratorStruct,
false );
755 else if(type == IterateTable::COMMAND_MODIFY_ACTIVE_GROUP)
757 return startCommandModifyActive(iteratorStruct);
759 else if(type == IterateTable::COMMAND_REPEAT_LABEL)
761 return startCommandRepeatLabel(iteratorStruct);
763 else if(type == IterateTable::COMMAND_RUN)
765 return startCommandRun(iteratorStruct);
767 else if(type == IterateTable::COMMAND_WAIT)
769 return startCommandWait(iteratorStruct);
771 else if(type == IterateTable::COMMAND_START)
773 if(targetSubsystem.size())
774 return startRemoteCommandFSMTransition(
776 RunControlStateMachine::START_TRANSITION_NAME,
778 return startCommandFSMTransition(iteratorStruct,
779 RunControlStateMachine::START_TRANSITION_NAME);
781 else if(type == IterateTable::COMMAND_STOP)
783 if(targetSubsystem.size())
784 return startRemoteCommandFSMTransition(
786 RunControlStateMachine::STOP_TRANSITION_NAME,
788 return startCommandFSMTransition(iteratorStruct,
789 RunControlStateMachine::STOP_TRANSITION_NAME);
791 else if(type == IterateTable::COMMAND_PAUSE)
793 if(targetSubsystem.size())
794 return startRemoteCommandFSMTransition(
796 RunControlStateMachine::PAUSE_TRANSITION_NAME,
798 return startCommandFSMTransition(iteratorStruct,
799 RunControlStateMachine::PAUSE_TRANSITION_NAME);
801 else if(type == IterateTable::COMMAND_RESUME)
803 if(targetSubsystem.size())
804 return startRemoteCommandFSMTransition(
806 RunControlStateMachine::RESUME_TRANSITION_NAME,
808 return startCommandFSMTransition(iteratorStruct,
809 RunControlStateMachine::RESUME_TRANSITION_NAME);
811 else if(type == IterateTable::COMMAND_HALT)
813 if(targetSubsystem.size())
814 return startRemoteCommandFSMTransition(
816 RunControlStateMachine::HALT_TRANSITION_NAME,
818 return startCommandFSMTransition(iteratorStruct,
819 RunControlStateMachine::HALT_TRANSITION_NAME);
823 __SS__ <<
"Failed attempt to start unrecognized command type = " << type << __E__;
824 __COUT_ERR__ << ss.str();
830 __COUT__ <<
"Error caught. Reverting track changes." << __E__;
831 ConfigurationInterface::setVersionTrackingEnabled(
832 iteratorStruct->originalTrackChanges_);
834 __COUT__ <<
"Activating original group..." << __E__;
837 iteratorStruct->cfgMgr_->activateTableGroup(iteratorStruct->originalConfigGroup_,
838 iteratorStruct->originalConfigKey_);
842 __COUT_WARN__ <<
"Original group could not be activated." << __E__;
851 bool Iterator::checkCommand(IteratorWorkLoopStruct* iteratorStruct)
855 if(iteratorStruct->commandIndex_ >= iteratorStruct->commands_.size())
857 __COUT__ <<
"Out of range commandIndex = " << iteratorStruct->commandIndex_
858 <<
" in size = " << iteratorStruct->commands_.size() << __E__;
862 std::string type = iteratorStruct->commands_[iteratorStruct->commandIndex_].type_;
863 const std::string& targetSubsystem =
864 iteratorStruct->commands_[iteratorStruct->commandIndex_].targetSubsystem_;
871 else if(type == IterateTable::COMMAND_CHOOSE_FSM)
876 else if(type == IterateTable::COMMAND_CONFIGURE_ALIAS ||
877 type == IterateTable::COMMAND_CONFIGURE_ACTIVE_GROUP ||
878 type == IterateTable::COMMAND_CONFIGURE_GROUP)
880 if(targetSubsystem.size())
881 return checkRemoteCommandConfigure(iteratorStruct, targetSubsystem);
882 return checkCommandConfigure(iteratorStruct);
884 else if(type == IterateTable::COMMAND_ACTIVATE_ALIAS ||
885 type == IterateTable::COMMAND_ACTIVATE_GROUP)
890 else if(type == IterateTable::COMMAND_EXECUTE_FE_MACRO)
892 if(targetSubsystem.size())
893 return checkRemoteCommandMacro(iteratorStruct,
true );
894 return checkCommandMacro(iteratorStruct,
true );
896 else if(type == IterateTable::COMMAND_EXECUTE_MM_MACRO)
898 if(targetSubsystem.size())
899 return checkRemoteCommandMacro(iteratorStruct,
false );
900 return checkCommandMacro(iteratorStruct,
false );
902 else if(type == IterateTable::COMMAND_MODIFY_ACTIVE_GROUP)
907 else if(type == IterateTable::COMMAND_REPEAT_LABEL)
912 else if(type == IterateTable::COMMAND_RUN)
914 return checkCommandRun(iteratorStruct);
916 else if(type == IterateTable::COMMAND_WAIT)
918 return checkCommandWait(iteratorStruct);
920 else if(type == IterateTable::COMMAND_START)
922 if(targetSubsystem.size())
923 return checkRemoteCommandFSMTransition(
924 iteratorStruct,
"Running", targetSubsystem);
925 return checkCommandFSMTransition(iteratorStruct,
"Running");
927 else if(type == IterateTable::COMMAND_STOP)
929 if(targetSubsystem.size())
930 return checkRemoteCommandFSMTransition(
931 iteratorStruct,
"Configured", targetSubsystem);
932 return checkCommandFSMTransition(iteratorStruct,
"Configured");
934 else if(type == IterateTable::COMMAND_PAUSE)
936 if(targetSubsystem.size())
937 return checkRemoteCommandFSMTransition(
938 iteratorStruct,
"Paused", targetSubsystem);
939 return checkCommandFSMTransition(iteratorStruct,
"Paused");
941 else if(type == IterateTable::COMMAND_RESUME)
943 if(targetSubsystem.size())
944 return checkRemoteCommandFSMTransition(
945 iteratorStruct,
"Running", targetSubsystem);
946 return checkCommandFSMTransition(iteratorStruct,
"Running");
948 else if(type == IterateTable::COMMAND_HALT)
950 if(targetSubsystem.size())
951 return checkRemoteCommandFSMTransition(
953 RunControlStateMachine::HALTED_STATE_NAME,
955 return checkCommandFSMTransition(iteratorStruct,
956 RunControlStateMachine::HALTED_STATE_NAME);
960 __SS__ <<
"Attempt to check unrecognized command type = " << type << __E__;
961 __COUT_ERR__ << ss.str();
967 __COUT__ <<
"Error caught. Reverting track changes." << __E__;
968 ConfigurationInterface::setVersionTrackingEnabled(
969 iteratorStruct->originalTrackChanges_);
971 __COUT__ <<
"Activating original group..." << __E__;
974 iteratorStruct->cfgMgr_->activateTableGroup(iteratorStruct->originalConfigGroup_,
975 iteratorStruct->originalConfigKey_);
979 __COUT_WARN__ <<
"Original group could not be activated." << __E__;
986 void Iterator::startCommandChooseFSM(IteratorWorkLoopStruct* iteratorStruct,
987 const std::string& fsmName)
989 __COUT__ <<
"fsmName " << fsmName << __E__;
991 iteratorStruct->fsmName_ = fsmName;
992 iteratorStruct->theIterator_->lastFsmName_ = fsmName;
1001 iteratorStruct->fsmRunAlias_ =
"Run";
1004 ConfigurationTree configLinkNode = iteratorStruct->cfgMgr_->getSupervisorTableNode(
1005 iteratorStruct->theIterator_->theSupervisor_->getContextUID(),
1006 iteratorStruct->theIterator_->theSupervisor_->getSupervisorUID());
1013 configLinkNode.
getNode(
"LinkToStateMachineTable");
1015 iteratorStruct->fsmRunAlias_ =
1016 fsmLinkNode.
getNode(fsmName +
"/RunDisplayAlias")
1019 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
1021 catch(std::runtime_error& e)
1025 <<
"No state machine Run alias. Ignoring and assuming alias of '"
1026 << iteratorStruct->fsmRunAlias_ <<
".'" << __E__;
1030 __COUT_ERR__ <<
"Unknown error. Should never happen." << __E__;
1033 <<
"No state machine Run alias. Ignoring and assuming alias of '"
1034 << iteratorStruct->fsmRunAlias_ <<
".'" << __E__;
1038 __COUT_INFO__ <<
"FSM Link disconnected." << __E__;
1040 __COUT__ <<
"fsmRunAlias_ = " << iteratorStruct->fsmRunAlias_ << __E__;
1044 iteratorStruct->fsmNextRunNumber_ =
1045 iteratorStruct->theIterator_->theSupervisor_->getNextRunNumber(
1046 iteratorStruct->fsmName_);
1048 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1049 .getCurrentStateName() ==
"Running" ||
1050 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1051 .getCurrentStateName() ==
"Paused")
1052 --iteratorStruct->fsmNextRunNumber_;
1054 __COUT__ <<
"fsmNextRunNumber_ = " << iteratorStruct->fsmNextRunNumber_ << __E__;
1059 bool Iterator::haltIterator(
Iterator* iterator,
1060 IteratorWorkLoopStruct* iteratorStruct ,
1065 const std::string& fsmName = iterator->lastFsmName_;
1067 std::vector<std::string> fsmCommandParameters;
1068 std::string errorStr =
"";
1069 std::string currentState = theSupervisor->theStateMachine_.getCurrentStateName();
1071 __COUTV__(currentState);
1073 bool haltAttempted =
true;
1076 __COUT_INFO__ <<
"Iterator is leaving FSM in current state: " << currentState
1077 <<
". If this is undesireable, add a Halt command, for example, to "
1078 "the end of your Iteration plan."
1080 haltAttempted =
false;
1082 else if(currentState == RunControlStateMachine::INITIAL_STATE_NAME ||
1083 currentState == RunControlStateMachine::HALTED_STATE_NAME)
1085 __COUT__ <<
"Do nothing. Already halted." << __E__;
1086 haltAttempted =
false;
1088 else if(currentState ==
"Running")
1089 errorStr = theSupervisor->attemptStateMachineTransition(
1092 RunControlStateMachine::ABORT_TRANSITION_NAME,
1094 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1095 WebUsers::DEFAULT_ITERATOR_USERNAME,
1096 fsmCommandParameters);
1098 errorStr = theSupervisor->attemptStateMachineTransition(
1101 RunControlStateMachine::HALT_TRANSITION_NAME,
1103 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1104 WebUsers::DEFAULT_ITERATOR_USERNAME,
1105 fsmCommandParameters);
1111 __SS__ <<
"Iterator failed to halt because of the following error: "
1117 __COUT__ <<
"FSM in transition = "
1118 << theSupervisor->theStateMachine_.isInTransition() << __E__;
1119 __COUT__ <<
"halting state machine launched." << __E__;
1123 __COUT__ <<
"Conducting Iterator cleanup." << __E__;
1127 __COUT__ <<
"Reverting track changes." << __E__;
1128 ConfigurationInterface::setVersionTrackingEnabled(
1129 iteratorStruct->originalTrackChanges_);
1133 __COUT__ <<
"Activating original group..." << __E__;
1136 iteratorStruct->cfgMgr_->activateTableGroup(
1137 iteratorStruct->originalConfigGroup_,
1138 iteratorStruct->originalConfigKey_);
1142 __COUT_WARN__ <<
"Original group could not be activated." << __E__;
1149 if(iterator->theSupervisor_->VERBOSE_MUTEX)
1150 __COUT__ <<
"Waiting for iterator access" << __E__;
1151 std::lock_guard<std::mutex> lock(iterator->accessMutex_);
1152 if(iterator->theSupervisor_->VERBOSE_MUTEX)
1153 __COUT__ <<
"Have iterator access" << __E__;
1155 iterator->activePlanIsRunning_ =
false;
1156 iterator->iteratorBusy_ =
false;
1159 iterator->activePlanName_ =
"";
1160 iterator->activeCommandIndex_ = -1;
1164 __COUT__ <<
"Iterator cleanup complete of plan '" << iteratorStruct->activePlan_
1165 <<
"' at command index " << iteratorStruct->commandIndex_ <<
". "
1168 iterator->lastFinishedPlanName_ = iteratorStruct->activePlan_;
1170 iterator->lastPlanOutputFiles_ = iteratorStruct->outputFiles_;
1171 for(
const auto& f : iterator->lastPlanOutputFiles_)
1172 __COUT_INFO__ <<
"Plan '" << iteratorStruct->activePlan_ <<
"' output file ("
1173 << (f.subsystem ==
"" ? std::string(
"Self") : f.subsystem)
1174 <<
", " << f.label <<
"): " << f.path << __E__;
1175 FILE* fp = fopen((ITERATOR_PLAN_HISTORY_FILENAME).c_str(),
"w");
1178 fprintf(fp,
"%s\n", iterator->lastStartedPlanName_.c_str());
1179 fprintf(fp,
"%s\n", iterator->lastFinishedPlanName_.c_str());
1183 __COUT_WARN__ <<
"Could not open Iterator history file: "
1184 << ITERATOR_PLAN_HISTORY_FILENAME << __E__;
1186 iteratorStruct->activePlan_ =
"";
1187 iteratorStruct->commandIndex_ = -1;
1190 return haltAttempted;
1194 void Iterator::startCommandBeginLabel(IteratorWorkLoopStruct* iteratorStruct)
1196 __COUT__ <<
"Entering label '"
1197 << iteratorStruct->commands_[iteratorStruct->commandIndex_]
1198 .params_[IterateTable::commandBeginLabelParams_.Label_]
1199 <<
"'..." << std::endl;
1202 iteratorStruct->stepIndexStack_.push_back(0);
1203 iteratorStruct->stepLabelStack_.push_back(
1204 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1205 .params_[IterateTable::commandBeginLabelParams_.Label_]);
1209 void Iterator::startCommandRepeatLabel(IteratorWorkLoopStruct* iteratorStruct)
1213 int numOfRepetitions;
1214 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1215 .params_[IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_]
1219 __COUT__ <<
"numOfRepetitions remaining = " << numOfRepetitions << __E__;
1223 if(numOfRepetitions <= 0)
1226 sprintf(repStr,
"%d", iteratorStruct->stepIndexStack_.back());
1227 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1228 .params_[IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_] =
1232 iteratorStruct->stepIndexStack_.pop_back();
1233 if(iteratorStruct->stepLabelStack_.size())
1234 iteratorStruct->stepLabelStack_.pop_back();
1242 ++(iteratorStruct->stepIndexStack_.back());
1245 for(i = iteratorStruct->commandIndex_; i > 0;
1248 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1249 .params_[IterateTable::commandRepeatLabelParams_.Label_] ==
1250 iteratorStruct->commands_[i]
1251 .params_[IterateTable::commandBeginLabelParams_.Label_])
1254 sprintf(repStr,
"%d", numOfRepetitions);
1255 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1256 .params_[IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_] =
1259 iteratorStruct->commandIndex_ = i;
1260 __COUT__ <<
"Jumping back to commandIndex " << iteratorStruct->commandIndex_ << __E__;
1264 std::string Iterator::buildIteratorLogEntry(IteratorWorkLoopStruct* iteratorStruct)
1266 std::string entry =
"Iterator plan '" + iteratorStruct->activePlan_ +
"'";
1267 if(!iteratorStruct->stepIndexStack_.empty())
1270 for(
size_t i = 0; i < iteratorStruct->stepIndexStack_.size(); ++i)
1274 if(i < iteratorStruct->stepLabelStack_.size() &&
1275 !iteratorStruct->stepLabelStack_[i].empty())
1276 entry += iteratorStruct->stepLabelStack_[i] +
" ";
1277 entry +=
"pass " + std::to_string(iteratorStruct->stepIndexStack_[i]);
1285 void Iterator::startCommandRun(IteratorWorkLoopStruct* iteratorStruct)
1287 __COUT__ <<
"startCommandRun " << __E__;
1289 iteratorStruct->runIsDone_ =
false;
1290 iteratorStruct->fsmCommandParameters_.clear();
1292 bool writeToEcl =
false;
1295 writeToEcl = iteratorStruct->commands_[iteratorStruct->commandIndex_].params_.at(
1296 IterateTable::commandRunParams_.WriteToECL_) ==
"1";
1301 iteratorStruct->theIterator_->theSupervisor_->activeStateMachineWriteToEcl_ =
1304 std::string errorStr =
"";
1305 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1306 ->theStateMachine_.getCurrentStateName();
1310 __COUTTV__(iteratorStruct->theIterator_->genLogEntry_);
1312 if(currentState == RunControlStateMachine::CONFIGURED_STATE_NAME)
1314 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1317 RunControlStateMachine::START_TRANSITION_NAME,
1318 iteratorStruct->fsmName_,
1319 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1320 WebUsers::DEFAULT_ITERATOR_USERNAME,
1321 iteratorStruct->fsmCommandParameters_,
1322 iteratorStruct->activePlan_ == Iterator::RESERVED_GEN_PLAN_NAME
1323 ? iteratorStruct->theIterator_->genLogEntry_
1324 : buildIteratorLogEntry(iteratorStruct));
1326 errorStr =
"Can only Run from the Configured state. The current state is " +
1331 __SS__ <<
"Iterator failed to run because of the following error: " << errorStr;
1336 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1337 .params_[IterateTable::commandRunParams_.DurationInSeconds_]
1340 &iteratorStruct->originalDurationInSeconds_);
1341 __COUTV__(iteratorStruct->originalDurationInSeconds_);
1345 <<
"FSM in transition = "
1346 << iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition()
1348 __COUT__ <<
"startCommandRun success." << __E__;
1352 void Iterator::startCommandWait(IteratorWorkLoopStruct* iteratorStruct)
1354 __COUT__ <<
"startCommandWait " << __E__;
1356 iteratorStruct->waitIsDone_ =
false;
1359 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1360 .params_[IterateTable::commandWaitParams_.DurationInSeconds_]
1363 &iteratorStruct->originalDurationInSeconds_);
1364 __COUTV__(iteratorStruct->originalDurationInSeconds_);
1366 __COUT__ <<
"startCommandWait success." << __E__;
1374 bool Iterator::commandSkipsIfConfigured(IteratorWorkLoopStruct* iteratorStruct)
1376 if(iteratorStruct->onlyConfigIfNotConfigured_)
1378 auto& params = iteratorStruct->commands_[iteratorStruct->commandIndex_].params_;
1380 params.find(IterateTable::commandConfigureAliasParams_.SkipIfAlreadyConfigured_);
1381 return it != params.end() && (it->second ==
"1" || it->second ==
"Yes" ||
1382 it->second ==
"True" || it->second ==
"On");
1386 void Iterator::startCommandConfigureActive(IteratorWorkLoopStruct* iteratorStruct)
1388 __COUT__ <<
"startCommandConfigureActive " << __E__;
1394 std::string group = iteratorStruct->cfgMgr_->getActiveGroupName();
1395 TableGroupKey key = iteratorStruct->cfgMgr_->getActiveGroupKey();
1397 __COUT__ <<
"group " << group << __E__;
1398 __COUT__ <<
"key " << key << __E__;
1402 std::stringstream systemAlias;
1403 systemAlias <<
"GROUP:" << group <<
":" << key;
1404 startCommandConfigureAlias(iteratorStruct, systemAlias.str());
1408 void Iterator::startCommandConfigureGroup(IteratorWorkLoopStruct* iteratorStruct)
1410 __COUT__ <<
"startCommandConfigureGroup " << __E__;
1416 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1417 .params_[IterateTable::commandConfigureGroupParams_.GroupName_];
1419 TableGroupKey(iteratorStruct->commands_[iteratorStruct->commandIndex_]
1420 .params_[IterateTable::commandConfigureGroupParams_.GroupKey_]);
1422 __COUT__ <<
"group " << group << __E__;
1423 __COUT__ <<
"key " << key << __E__;
1427 std::stringstream systemAlias;
1428 systemAlias <<
"GROUP:" << group <<
":" << key;
1429 startCommandConfigureAlias(iteratorStruct, systemAlias.str());
1433 void Iterator::startCommandConfigureAlias(IteratorWorkLoopStruct* iteratorStruct,
1434 const std::string& systemAlias)
1436 __COUT__ <<
"systemAlias " << systemAlias << __E__;
1438 iteratorStruct->fsmCommandParameters_.clear();
1439 iteratorStruct->fsmCommandParameters_.push_back(systemAlias);
1441 std::string errorStr =
"";
1442 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1443 ->theStateMachine_.getCurrentStateName();
1447 if(currentState == RunControlStateMachine::INITIAL_STATE_NAME)
1449 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1452 RunControlStateMachine::INIT_TRANSITION_NAME,
1453 iteratorStruct->fsmName_,
1454 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1455 WebUsers::DEFAULT_ITERATOR_USERNAME,
1456 iteratorStruct->fsmCommandParameters_);
1457 else if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
1459 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1462 RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
1463 iteratorStruct->fsmName_,
1464 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1465 WebUsers::DEFAULT_ITERATOR_USERNAME,
1466 iteratorStruct->fsmCommandParameters_);
1467 else if(currentState == RunControlStateMachine::CONFIGURED_STATE_NAME ||
1468 currentState == RunControlStateMachine::FAILED_STATE_NAME)
1470 if(commandSkipsIfConfigured(iteratorStruct) &&
1471 currentState != RunControlStateMachine::FAILED_STATE_NAME)
1472 __COUT_INFO__ <<
"Already configured and SkipIfAlreadyConfigured is set, so "
1473 "leaving the configuration as-is."
1476 errorStr = iteratorStruct->theIterator_->theSupervisor_
1477 ->attemptStateMachineTransition(
1480 RunControlStateMachine::HALT_TRANSITION_NAME,
1481 iteratorStruct->fsmName_,
1482 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1483 WebUsers::DEFAULT_ITERATOR_USERNAME,
1484 iteratorStruct->fsmCommandParameters_);
1488 "Can only Configure from the Initial or Halted state. The current state is " +
1493 __SS__ <<
"Iterator failed to configure with system alias '"
1494 << (iteratorStruct->fsmCommandParameters_.size()
1495 ? iteratorStruct->fsmCommandParameters_[0]
1497 <<
"' because of the following error: " << errorStr;
1503 <<
"FSM in transition = "
1504 << iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition()
1506 __COUT__ <<
"startCommandConfigureAlias success." << __E__;
1510 void Iterator::startCommandFSMTransition(IteratorWorkLoopStruct* iteratorStruct,
1511 const std::string& transitionCommand)
1513 __COUTV__(transitionCommand);
1515 iteratorStruct->fsmCommandParameters_.clear();
1517 std::string errorStr =
"";
1518 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1519 ->theStateMachine_.getCurrentStateName();
1523 __COUTV__(currentState);
1526 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
1530 iteratorStruct->fsmName_,
1531 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1532 WebUsers::DEFAULT_ITERATOR_USERNAME,
1533 iteratorStruct->fsmCommandParameters_,
1534 (transitionCommand == RunControlStateMachine::START_TRANSITION_NAME)
1535 ? (iteratorStruct->activePlan_ == Iterator::RESERVED_GEN_PLAN_NAME
1536 ? iteratorStruct->theIterator_->genLogEntry_
1537 : buildIteratorLogEntry(iteratorStruct))
1538 : (transitionCommand == RunControlStateMachine::STOP_TRANSITION_NAME)
1539 ?
"Stopped by iterator: " + buildIteratorLogEntry(iteratorStruct)
1544 __SS__ <<
"Iterator failed to " << transitionCommand <<
" with ";
1545 if(iteratorStruct->fsmCommandParameters_.size() == 0)
1546 ss <<
"no parameters ";
1548 ss <<
"parameters '"
1551 ss <<
"' because of the following error: " << errorStr;
1557 <<
"FSM in transition = "
1558 << iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition()
1560 __COUT__ <<
"startCommandFSMTransition success." << __E__;
1564 void Iterator::startCommandMacro(IteratorWorkLoopStruct* iteratorStruct,
1565 bool isFrontEndMacro)
1573 const std::string& macroName =
1574 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1575 .params_[IterateTable::commandExecuteMacroParams_.MacroName_];
1576 const std::string& enableSavingOutput =
1577 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1578 .params_[IterateTable::commandExecuteMacroParams_.EnableSavingOutput_];
1579 const std::string& outputFilePath =
1580 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1581 .params_[IterateTable::commandExecuteMacroParams_.OutputFilePath_];
1582 const std::string& outputFileRadix =
1583 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1584 .params_[IterateTable::commandExecuteMacroParams_.OutputFileRadix_];
1585 const std::string inputArgs = applyStepIndexToMacroArgs(
1587 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1588 .params_[IterateTable::commandExecuteMacroParams_.MacroArgumentString_],
1589 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1590 .params_[IterateTable::commandExecuteMacroParams_.MacroArgumentLabels_]);
1591 iteratorStruct->macroArgsSummary_ =
1592 macroArgsSummary(inputArgs);
1594 __COUTV__(macroName);
1595 __COUTV__(enableSavingOutput);
1596 __COUTV__(outputFilePath);
1597 __COUTV__(outputFileRadix);
1598 __COUTV__(inputArgs);
1606 iteratorStruct->targetsDone_.clear();
1608 __COUTV__(iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_.size());
1609 for(
const auto& target :
1610 iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_)
1612 __COUT__ <<
"target " << target.table_ <<
":" << target.UID_ << __E__;
1615 iteratorStruct->targetsDone_.push_back(
false);
1617 xoap::MessageReference message =
1618 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1621 std::string type = isFrontEndMacro ?
"feMacroMultiDimensionalStart"
1622 :
"macroMultiDimensionalStart";
1623 parameters.addParameter(
"type", type);
1624 parameters.addParameter(
"requester", WebUsers::DEFAULT_ITERATOR_USERNAME);
1625 parameters.addParameter(
"targetInterfaceID", target.UID_);
1626 parameters.addParameter(isFrontEndMacro ?
"feMacroName" :
"macroName", macroName);
1627 parameters.addParameter(
"enableSavingOutput", enableSavingOutput);
1628 parameters.addParameter(
"outputFilePath", outputFilePath);
1629 parameters.addParameter(
"outputFileRadix", outputFileRadix);
1630 parameters.addParameter(
"inputArgs", inputArgs);
1631 SOAPUtilities::addParameters(message, parameters);
1633 __COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1636 xoap::MessageReference replyMessage =
1637 iteratorStruct->theIterator_->theSupervisor_
1638 ->SOAPMessenger::sendWithSOAPReply(
1639 iteratorStruct->theIterator_->theSupervisor_->allSupervisorInfo_
1640 .getAllMacroMakerTypeSupervisorInfo()
1642 ->second.getDescriptor(),
1645 __COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
1649 rxParameters.addParameter(
"Error");
1650 std::string response = SOAPUtilities::receive(replyMessage, rxParameters);
1652 std::string error = rxParameters.getValue(
"Error");
1654 if(response != type +
"Done" || error !=
"")
1657 __SS__ <<
"Error transmitting request to target interface '" << target.UID_
1658 <<
"' from '" << WebUsers::DEFAULT_ITERATOR_USERNAME <<
".' Response '"
1659 << response <<
"' with error: " << error << __E__;
1667 bool Iterator::checkCommandMacro(IteratorWorkLoopStruct* iteratorStruct,
1668 bool isFrontEndMacro)
1678 const std::string& macroName =
1679 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1680 .params_[IterateTable::commandExecuteMacroParams_.MacroName_];
1682 __COUTV__(macroName);
1687 for(
unsigned int i = 0;
1688 i < iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_.size();
1692 iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_[i];
1694 if(i < iteratorStruct->targetsDone_.size() && iteratorStruct->targetsDone_[i])
1697 __COUT__ <<
"target " << target.table_ <<
":" << target.UID_ << __E__;
1699 xoap::MessageReference message =
1700 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1703 std::string type = isFrontEndMacro ?
"feMacroMultiDimensionalCheck"
1704 :
"macroMultiDimensionalCheck";
1705 parameters.addParameter(
"type", type);
1706 parameters.addParameter(
"requester", WebUsers::DEFAULT_ITERATOR_USERNAME);
1707 parameters.addParameter(
"targetInterfaceID", target.UID_);
1708 parameters.addParameter(isFrontEndMacro ?
"feMacroName" :
"macroName", macroName);
1709 SOAPUtilities::addParameters(message, parameters);
1711 __COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
1714 xoap::MessageReference replyMessage =
1715 iteratorStruct->theIterator_->theSupervisor_
1716 ->SOAPMessenger::sendWithSOAPReply(
1717 iteratorStruct->theIterator_->theSupervisor_->allSupervisorInfo_
1718 .getAllMacroMakerTypeSupervisorInfo()
1720 ->second.getDescriptor(),
1723 __COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
1727 rxParameters.addParameter(
"Error");
1728 rxParameters.addParameter(
"Done");
1729 std::string response = SOAPUtilities::receive(replyMessage, rxParameters);
1731 std::string error = rxParameters.getValue(
"Error");
1732 bool done = rxParameters.getValue(
"Done") ==
"1";
1734 if(response != type +
"Done" || error !=
"")
1737 __SS__ <<
"Error transmitting request to target interface '" << target.UID_
1738 <<
"' from '" << WebUsers::DEFAULT_ITERATOR_USERNAME <<
".' Response '"
1739 << response <<
"' with error: " << error << __E__;
1747 iteratorStruct->targetsDone_[i] =
true;
1754 fileParameters.addParameter(
"OutputFile");
1755 SOAPUtilities::receive(replyMessage, fileParameters);
1756 const std::string outputFile = fileParameters.getValue(
"OutputFile");
1757 if(outputFile !=
"")
1759 __COUT_INFO__ <<
"Macro '" << macroName <<
"' on '" << target.UID_
1760 <<
"' saved outputs to: " << outputFile << __E__;
1764 macroName +
" on " + target.UID_ +
" iteration #" +
1767 ->commandIterations_[iteratorStruct->commandIndex_]);
1768 if(iteratorStruct->macroArgsSummary_ !=
"")
1769 label +=
" [" + iteratorStruct->macroArgsSummary_ +
"]";
1770 iteratorStruct->outputFiles_.push_back(
1771 {
"" , outputFile, label,
""});
1776 __COUT__ <<
"Front-end did not report an OutputFile (older build?)" << __E__;
1789 void Iterator::startCommandModifyActive(IteratorWorkLoopStruct* iteratorStruct)
1810 bool doTrackGroupChanges =
false;
1812 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1813 .params_[IterateTable::commandModifyActiveParams_.DoTrackGroupChanges_])
1814 doTrackGroupChanges =
true;
1816 const std::string& startValueStr =
1817 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1818 .params_[IterateTable::commandModifyActiveParams_.FieldStartValue_];
1819 const std::string& stepSizeStr =
1820 iteratorStruct->commands_[iteratorStruct->commandIndex_]
1821 .params_[IterateTable::commandModifyActiveParams_.FieldIterationStepSize_];
1823 const unsigned int stepIndex = getStepIndexForLabel(iteratorStruct,
"" );
1825 __COUT__ <<
"doTrackGroupChanges " << (doTrackGroupChanges ?
"yes" :
"no")
1827 __COUTV__(startValueStr);
1828 __COUTV__(stepSizeStr);
1829 __COUTV__(stepIndex);
1831 ConfigurationInterface::setVersionTrackingEnabled(doTrackGroupChanges);
1836 if(((stepSizeStr.size() && stepSizeStr[0] ==
'0') || !stepSizeStr.size()) &&
1840 __COUT__ <<
"Treating start value as string: " << startValueStr << __E__;
1841 helpCommandModifyActive(iteratorStruct, startValueStr, doTrackGroupChanges);
1843 else if(startValueStr.size() && (startValueStr[startValueStr.size() - 1] ==
'f' ||
1844 startValueStr.find(
'.') != std::string::npos))
1847 double startValue = strtod(startValueStr.c_str(), 0);
1848 double stepSize = strtod(stepSizeStr.c_str(), 0);
1850 __COUT__ <<
"startValue " << startValue << std::endl;
1851 __COUT__ <<
"stepSize " << stepSize << std::endl;
1852 __COUT__ <<
"currentValue " << startValue + stepSize * stepIndex << std::endl;
1854 helpCommandModifyActive(
1855 iteratorStruct, startValue + stepSize * stepIndex, doTrackGroupChanges);
1859 long int startValue;
1865 __COUT__ <<
"startValue " << startValue << std::endl;
1866 __COUT__ <<
"stepSize " << stepSize << std::endl;
1867 __COUT__ <<
"currentValue " << startValue + stepSize * stepIndex << std::endl;
1869 helpCommandModifyActive(
1870 iteratorStruct, startValue + stepSize * stepIndex, doTrackGroupChanges);
1884 bool Iterator::checkCommandRun(IteratorWorkLoopStruct* iteratorStruct)
1893 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
1894 __COUT__ <<
"Waiting for FSM access" << __E__;
1895 std::lock_guard<std::mutex> lock(
1896 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
1897 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
1898 __COUT__ <<
"Have FSM access" << __E__;
1900 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition())
1903 iteratorStruct->fsmCommandParameters_.clear();
1905 std::string errorStr =
"";
1906 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
1907 ->theStateMachine_.getCurrentStateName();
1911 if(iteratorStruct->doPauseAction_)
1914 __COUT__ <<
"Transitioning FSM to Paused..." << __E__;
1916 if(currentState ==
"Paused")
1919 __COUT__ <<
"Transition to Paused complete." << __E__;
1922 else if(currentState ==
"Running")
1923 errorStr = iteratorStruct->theIterator_->theSupervisor_
1924 ->attemptStateMachineTransition(
1928 iteratorStruct->fsmName_,
1929 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1930 WebUsers::DEFAULT_ITERATOR_USERNAME,
1931 iteratorStruct->fsmCommandParameters_);
1932 else if(currentState ==
"Configured")
1935 __COUT__ <<
"In Configured state. No need to transition to Paused." << __E__;
1939 errorStr =
"Expected to be in Paused. Unexpectedly, the current state is " +
1941 ". Last State Machine error message was as follows: " +
1942 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1947 __SS__ <<
"Iterator failed to pause because of the following error: "
1953 else if(iteratorStruct->doHaltAction_)
1956 __COUT__ <<
"Transitioning FSM to Halted..." << __E__;
1958 if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
1961 __COUT__ <<
"Transition to Halted complete." << __E__;
1965 RUNNING_STATE_NAME ||
1966 currentState == RunControlStateMachine::PAUSED_STATE_NAME)
1967 errorStr = iteratorStruct->theIterator_->theSupervisor_
1968 ->attemptStateMachineTransition(
1971 RunControlStateMachine::ABORT_TRANSITION_NAME,
1972 iteratorStruct->fsmName_,
1973 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1974 WebUsers::DEFAULT_ITERATOR_USERNAME,
1975 iteratorStruct->fsmCommandParameters_);
1977 CONFIGURED_STATE_NAME)
1978 errorStr = iteratorStruct->theIterator_->theSupervisor_
1979 ->attemptStateMachineTransition(
1982 RunControlStateMachine::HALT_TRANSITION_NAME,
1983 iteratorStruct->fsmName_,
1984 WebUsers::DEFAULT_ITERATOR_USERNAME ,
1985 WebUsers::DEFAULT_ITERATOR_USERNAME,
1986 iteratorStruct->fsmCommandParameters_);
1988 errorStr =
"Expected to be in Halted. Unexpectedly, the current state is " +
1990 ". Last State Machine error message was as follows: " +
1991 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
1996 __SS__ <<
"Iterator failed to halt because of the following error: "
2002 else if(iteratorStruct->doResumeAction_)
2007 __COUT__ <<
"Transitioning FSM to Running..." << __E__;
2009 if(currentState ==
"Paused")
2010 errorStr = iteratorStruct->theIterator_->theSupervisor_
2011 ->attemptStateMachineTransition(
2014 RunControlStateMachine::RESUME_TRANSITION_NAME,
2015 iteratorStruct->fsmName_,
2016 WebUsers::DEFAULT_ITERATOR_USERNAME ,
2017 WebUsers::DEFAULT_ITERATOR_USERNAME,
2018 iteratorStruct->fsmCommandParameters_);
2022 __SS__ <<
"Iterator failed to run because of the following error: "
2032 if(currentState !=
"Running")
2034 if(iteratorStruct->runIsDone_ && currentState ==
"Configured")
2037 __COUT__ <<
"Reached end of run " << iteratorStruct->fsmNextRunNumber_
2042 errorStr =
"Expected to be in Running. Unexpectedly, the current state is " +
2043 currentState +
". Last State Machine error message was as follows: " +
2044 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
2049 bool waitOnRunningThreads =
false;
2050 if(
"True" == iteratorStruct->commands_[iteratorStruct->commandIndex_]
2051 .params_[IterateTable::commandRunParams_.WaitOnRunningThreads_])
2052 waitOnRunningThreads =
true;
2054 time_t remainingDurationInSeconds;
2055 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
2056 .params_[IterateTable::commandRunParams_.DurationInSeconds_]
2059 &remainingDurationInSeconds);
2061 __COUT__ <<
"waitOnRunningThreads " << waitOnRunningThreads << __E__;
2062 __COUT__ <<
"remainingDurationInSeconds " << remainingDurationInSeconds << __E__;
2066 if(waitOnRunningThreads)
2070 iteratorStruct->theIterator_->theSupervisor_;
2072 bool allFrontEndsAreDone =
true;
2073 for(
auto& it : theSupervisor->allSupervisorInfo_.getAllFETypeSupervisorInfo())
2077 std::string status = theSupervisor->
send(it.second.getDescriptor(),
2078 "WorkLoopStatusRequest");
2080 __COUT__ <<
"FESupervisor instance " << it.first
2081 <<
" has status = " << status << std::endl;
2083 if(status != CoreSupervisorBase::WORK_LOOP_DONE)
2085 allFrontEndsAreDone =
false;
2089 catch(xdaq::exception::Exception& e)
2091 __SS__ <<
"Could not retrieve status from FESupervisor instance "
2092 << it.first <<
"." << std::endl;
2093 __COUT_WARN__ << ss.str();
2094 errorStr = ss.str();
2099 <<
"Iterator failed to run because of the following error: "
2106 if(allFrontEndsAreDone)
2109 __COUT__ <<
"FE workloops all complete! Stopping run..." << __E__;
2111 errorStr = iteratorStruct->theIterator_->theSupervisor_
2112 ->attemptStateMachineTransition(
2116 iteratorStruct->fsmName_,
2117 WebUsers::DEFAULT_ITERATOR_USERNAME ,
2118 WebUsers::DEFAULT_ITERATOR_USERNAME,
2119 iteratorStruct->fsmCommandParameters_,
2120 "Stopped by iterator: " +
2121 buildIteratorLogEntry(iteratorStruct));
2126 <<
"Iterator failed to stop run because of the following error: "
2132 iteratorStruct->runIsDone_ =
true;
2140 if(remainingDurationInSeconds > 1)
2143 if(remainingDurationInSeconds == iteratorStruct->originalDurationInSeconds_)
2145 iteratorStruct->theIterator_->activeCommandStartTime_ =
2147 __COUT__ <<
"Starting run duration of " << remainingDurationInSeconds
2148 <<
" [s] at time = "
2149 << iteratorStruct->theIterator_->activeCommandStartTime_ <<
" "
2151 iteratorStruct->theIterator_->activeCommandStartTime_)
2155 --remainingDurationInSeconds;
2159 sprintf(str,
"%ld", remainingDurationInSeconds);
2160 iteratorStruct->commands_[iteratorStruct->commandIndex_]
2161 .params_[IterateTable::commandRunParams_.DurationInSeconds_] =
2164 else if(remainingDurationInSeconds == 1)
2167 __COUT__ <<
"Time duration reached! Stopping run..." << __E__;
2170 iteratorStruct->theIterator_->theSupervisor_
2171 ->attemptStateMachineTransition(
2175 iteratorStruct->fsmName_,
2176 WebUsers::DEFAULT_ITERATOR_USERNAME ,
2177 WebUsers::DEFAULT_ITERATOR_USERNAME,
2178 iteratorStruct->fsmCommandParameters_,
2179 "Stopped by iterator: " + buildIteratorLogEntry(iteratorStruct));
2183 __SS__ <<
"Iterator failed to stop run because of the following error: "
2189 iteratorStruct->runIsDone_ =
true;
2193 sprintf(str,
"%ld", iteratorStruct->originalDurationInSeconds_);
2194 iteratorStruct->commands_[iteratorStruct->commandIndex_]
2195 .params_[IterateTable::commandRunParams_.DurationInSeconds_] =
2203 __SS__ <<
"Iterator failed to run because of the following error: " << errorStr;
2210 bool Iterator::checkCommandWait(IteratorWorkLoopStruct* iteratorStruct)
2215 long remainingDurationInSeconds;
2216 sscanf(iteratorStruct->commands_[iteratorStruct->commandIndex_]
2217 .params_[IterateTable::commandWaitParams_.DurationInSeconds_]
2220 &remainingDurationInSeconds);
2222 __COUT__ <<
"Wait remaining time: " << remainingDurationInSeconds <<
" seconds."
2226 if(remainingDurationInSeconds == iteratorStruct->originalDurationInSeconds_)
2228 iteratorStruct->theIterator_->activeCommandStartTime_ = time(0);
2229 __COUT__ <<
"Starting wait duration of " << remainingDurationInSeconds
2230 <<
" [s] at time = "
2231 << iteratorStruct->theIterator_->activeCommandStartTime_ <<
" "
2233 iteratorStruct->theIterator_->activeCommandStartTime_)
2238 if(iteratorStruct->doPauseAction_ || iteratorStruct->doHaltAction_)
2242 sprintf(str,
"%ld", iteratorStruct->originalDurationInSeconds_);
2243 iteratorStruct->commands_[iteratorStruct->commandIndex_]
2244 .params_[IterateTable::commandWaitParams_.DurationInSeconds_] = str;
2250 if(remainingDurationInSeconds <= 1)
2252 __COUT__ <<
"Wait duration complete!" << __E__;
2256 sprintf(str,
"%ld", iteratorStruct->originalDurationInSeconds_);
2257 iteratorStruct->commands_[iteratorStruct->commandIndex_]
2258 .params_[IterateTable::commandWaitParams_.DurationInSeconds_] = str;
2260 iteratorStruct->waitIsDone_ =
true;
2266 --remainingDurationInSeconds;
2270 sprintf(str,
"%ld", remainingDurationInSeconds);
2271 iteratorStruct->commands_[iteratorStruct->commandIndex_]
2272 .params_[IterateTable::commandWaitParams_.DurationInSeconds_] = str;
2280 bool Iterator::checkCommandConfigure(IteratorWorkLoopStruct* iteratorStruct)
2289 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
2290 __COUT__ <<
"Waiting for FSM access" << __E__;
2291 std::lock_guard<std::mutex> lock(
2292 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
2293 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
2294 __COUT__ <<
"Have FSM access" << __E__;
2296 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition())
2299 std::string errorStr =
"";
2300 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
2301 ->theStateMachine_.getCurrentStateName();
2303 if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
2305 iteratorStruct->theIterator_->theSupervisor_->attemptStateMachineTransition(
2309 iteratorStruct->fsmName_,
2310 WebUsers::DEFAULT_ITERATOR_USERNAME ,
2311 WebUsers::DEFAULT_ITERATOR_USERNAME,
2312 iteratorStruct->fsmCommandParameters_);
2313 else if(currentState != RunControlStateMachine::CONFIGURED_STATE_NAME)
2314 errorStr =
"Expected to be in '" + RunControlStateMachine::CONFIGURED_STATE_NAME +
2315 "' state. Unexpectedly, the current state is " + currentState +
"." +
2316 ". Last State Machine error message was as follows: " +
2317 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
2321 __COUT__ <<
"checkCommandConfigureAlias complete." << __E__;
2324 std::pair<std::string, TableGroupKey> newActiveGroup =
2325 iteratorStruct->cfgMgr_->getTableGroupFromAlias(
2326 iteratorStruct->fsmCommandParameters_[0]);
2327 iteratorStruct->cfgMgr_->loadTableGroup(
2328 newActiveGroup.first, newActiveGroup.second,
true );
2330 __COUT__ <<
"originalTrackChanges " << iteratorStruct->originalTrackChanges_
2332 __COUT__ <<
"originalConfigGroup " << iteratorStruct->originalConfigGroup_
2334 __COUT__ <<
"originalConfigKey " << iteratorStruct->originalConfigKey_ << __E__;
2336 __COUT__ <<
"currentTrackChanges "
2337 << ConfigurationInterface::isVersionTrackingEnabled() << __E__;
2338 __COUT__ <<
"originalConfigGroup "
2339 << iteratorStruct->cfgMgr_->getActiveGroupName() << __E__;
2340 __COUT__ <<
"originalConfigKey " << iteratorStruct->cfgMgr_->getActiveGroupKey()
2348 __SS__ <<
"Iterator failed to configure with system alias '"
2349 << (iteratorStruct->fsmCommandParameters_.size()
2350 ? iteratorStruct->fsmCommandParameters_[0]
2352 <<
"' because of the following error: " << errorStr;
2360 bool Iterator::checkCommandFSMTransition(IteratorWorkLoopStruct* iteratorStruct,
2361 const std::string& finalState)
2363 __COUTV__(finalState);
2372 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
2373 __COUT__ <<
"Waiting for FSM access" << __E__;
2374 std::lock_guard<std::mutex> lock(
2375 iteratorStruct->theIterator_->theSupervisor_->stateMachineAccessMutex_);
2376 if(iteratorStruct->theIterator_->theSupervisor_->VERBOSE_MUTEX)
2377 __COUT__ <<
"Have FSM access" << __E__;
2379 if(iteratorStruct->theIterator_->theSupervisor_->theStateMachine_.isInTransition())
2382 std::string errorStr =
"";
2383 std::string currentState = iteratorStruct->theIterator_->theSupervisor_
2384 ->theStateMachine_.getCurrentStateName();
2386 if(currentState != finalState)
2387 errorStr =
"Expected to be in " + finalState +
2388 ". Unexpectedly, the current state is " + currentState +
"." +
2389 ". Last State Machine error message was as follows: " +
2390 iteratorStruct->theIterator_->theSupervisor_->theStateMachine_
2394 __COUT__ <<
"checkCommandFSMTransition complete." << __E__;
2401 __SS__ <<
"Iterator failed to reach final state '" << finalState
2402 <<
"' because of the following error: " << errorStr;
2410 std::vector<IterateTable::Command> Iterator::generateIterationPlan(
2411 const std::string& fsmName,
2412 const std::string& configAlias,
2413 uint64_t durationSeconds ,
2414 unsigned int numberOfRuns )
2416 std::vector<IterateTable::Command> commands;
2426 if(durationSeconds == (uint64_t)-1)
2428 __COUTV__(durationSeconds);
2429 __COUTV__(numberOfRuns);
2434 commands.back().type_ = IterateTable::COMMAND_CHOOSE_FSM;
2436 commands.back().params_.emplace(
2437 std::pair<std::string /*param name*/, std::string /*param value*/>(
2438 IterateTable::commandChooseFSMParams_.NameOfFSM_, fsmName));
2444 commands.back().type_ = IterateTable::COMMAND_CONFIGURE_ALIAS;
2446 commands.back().params_.emplace(
2447 std::pair<std::string /*param name*/, std::string /*param value*/>(
2448 IterateTable::commandConfigureAliasParams_.SystemAlias_, configAlias));
2450 commands.back().params_.emplace(
2451 std::pair<std::string /*param name*/, std::string /*param value*/>(
2452 IterateTable::commandConfigureAliasParams_.SkipIfAlreadyConfigured_,
2456 if(durationSeconds == (uint64_t)-1)
2458 __COUT__ <<
"Open ended run..." << __E__;
2463 commands.back().type_ = IterateTable::COMMAND_START;
2468 __COUT__ <<
"Finite duration run(s)..." << __E__;
2470 if(numberOfRuns > 1)
2472 __COUT__ <<
"Setting up iterator loop for " << numberOfRuns <<
" runs."
2478 commands.back().params_.emplace(
2479 std::pair<std::string /*param name*/, std::string /*param value*/>(
2480 IterateTable::commandBeginLabelParams_.Label_,
"GENERATED_LABEL"));
2486 commands.back().type_ = IterateTable::COMMAND_RUN;
2488 commands.back().params_.emplace(
2489 std::pair<std::string /*param name*/, std::string /*param value*/>(
2490 IterateTable::commandRunParams_.DurationInSeconds_,
2491 std::to_string(durationSeconds)));
2494 if(numberOfRuns > 1)
2497 commands.back().type_ = IterateTable::COMMAND_REPEAT_LABEL;
2499 commands.back().params_.emplace(
2500 std::pair<std::string /*param name*/, std::string /*param value*/>(
2501 IterateTable::commandRepeatLabelParams_.Label_,
"GENERATED_LABEL"));
2502 commands.back().params_.emplace(
2503 std::pair<std::string /*param name*/, std::string /*param value*/>(
2504 IterateTable::commandRepeatLabelParams_.NumberOfRepetitions_,
2505 std::to_string(numberOfRuns -
2511 __COUTV__(commands.size());
2518 const std::string& command,
2519 const std::string& parameter)
2522 bool handledCommand =
false;
2523 __COUTTV__(command);
2524 if(command ==
"iteratePlay")
2526 playIterationPlan(xmldoc, parameter);
2527 handledCommand =
true;
2529 else if(command ==
"iteratePlayGenerated")
2531 playGeneratedIterationPlan(xmldoc, parameter);
2532 handledCommand =
true;
2534 else if(command ==
"iteratePause")
2536 pauseIterationPlan(xmldoc);
2537 handledCommand =
true;
2539 else if(command ==
"iterateHalt")
2541 haltIterationPlan(xmldoc);
2542 handledCommand =
true;
2544 else if(command ==
"getIterationPlanStatus")
2546 if(activePlanName_ ==
"" &&
2550 activePlanName_ = parameter;
2551 __COUTV__(activePlanName_);
2554 handledCommand =
true;
2560 if(theSupervisor_->VERBOSE_MUTEX)
2561 __COUT__ <<
"Waiting for iterator access" << __E__;
2562 std::lock_guard<std::mutex> lock(accessMutex_);
2563 if(theSupervisor_->VERBOSE_MUTEX)
2564 __COUT__ <<
"Have iterator access" << __E__;
2568 __SS__ <<
"Error - Can not accept request because the Iterator "
2570 <<
"in control of State Machine progress. ";
2571 __COUT_ERR__ <<
"\n" << ss.str();
2572 __COUT_ERR__ <<
"\n" << ss.str();
2574 xmldoc.addTextElementToData(
"state_transition_attempted",
2576 xmldoc.addTextElementToData(
2577 "state_transition_attempted_err",
2579 theSupervisor_->theStateMachine_.setErrorMessage(ss.str());
2586 xmldoc.addTextElementToData(
"state_transition_attempted",
2596 __SS__ <<
"Error caught by Iterator command handling!" << __E__;
2601 catch(
const std::runtime_error& e)
2603 ss <<
"\nHere is the error: " << e.what() << __E__;
2607 ss <<
"Uknown error caught." << __E__;
2610 __COUT_ERR__ <<
"\n" << ss.str();
2612 xmldoc.addTextElementToData(
"state_transition_attempted",
2614 xmldoc.addTextElementToData(
"state_transition_attempted_err",
2616 theSupervisor_->theStateMachine_.setErrorMessage(ss.str());
2621 void Iterator::playIterationPlan(
HttpXmlDocument& xmldoc,
const std::string& planName)
2623 __COUT__ <<
"Attempting to play iteration plan '" << planName <<
".'" << __E__;
2625 if(planName == Iterator::RESERVED_GEN_PLAN_NAME)
2627 __SS__ <<
"Illegal use of reserved iteration plan name '"
2628 << Iterator::RESERVED_GEN_PLAN_NAME <<
"!' Please select a different name."
2633 playIterationPlanPrivate(xmldoc, planName);
2639 const std::string& parametersCSV)
2641 __COUTV__(parametersCSV);
2642 std::vector<std::string> parameters =
2645 if(parameters.size() != 6)
2647 __SS__ <<
"Malformed CSV parameters to playGeneratedIterationPlan(), must be 6 "
2648 "arguments and there were "
2649 << parameters.size() <<
": " << parametersCSV << __E__;
2660 uint64_t durationSeconds;
2661 sscanf(parameters[2].c_str(),
"%lu", &durationSeconds);
2662 unsigned int numberOfRuns;
2663 sscanf(parameters[3].c_str(),
"%u", &numberOfRuns);
2664 unsigned int keepConfiguration;
2665 sscanf(parameters[4].c_str(),
"%u", &keepConfiguration);
2666 playGeneratedIterationPlan(xmldoc,
2679 const std::string& fsmName,
2680 const std::string& configAlias,
2681 uint64_t durationSeconds ,
2682 unsigned int numberOfRuns ,
2683 bool keepConfiguration ,
2684 const std::string& logEntry)
2686 std::string planName = Iterator::RESERVED_GEN_PLAN_NAME;
2687 __COUT__ <<
"Attempting to play iteration plan '" << planName <<
".'" << __E__;
2689 genFsmName_ = fsmName;
2690 genConfigAlias_ = configAlias;
2691 genPlanDurationSeconds_ = durationSeconds;
2692 genPlanNumberOfRuns_ = numberOfRuns;
2693 genKeepConfiguration_ = keepConfiguration;
2694 genLogEntry_ = logEntry;
2696 __COUTV__(genFsmName_);
2697 __COUTV__(genConfigAlias_);
2698 __COUTV__(genPlanDurationSeconds_);
2699 __COUTV__(genPlanNumberOfRuns_);
2700 __COUTV__(genKeepConfiguration_);
2701 __COUTV__(genLogEntry_);
2703 playIterationPlanPrivate(xmldoc, planName);
2710 const std::string& planName)
2716 if(theSupervisor_->VERBOSE_MUTEX)
2717 __COUT__ <<
"Waiting for iterator access" << __E__;
2718 std::lock_guard<std::mutex> lock(accessMutex_);
2719 if(theSupervisor_->VERBOSE_MUTEX)
2720 __COUT__ <<
"Have iterator access" << __E__;
2722 if(!activePlanIsRunning_ && !commandPlay_)
2724 if(!workloopRunning_)
2728 workloopRunning_ =
true;
2731 std::thread([](
Iterator* iterator) { Iterator::IteratorWorkLoop(iterator); },
2736 activePlanName_ = planName;
2737 commandPlay_ =
true;
2741 __SS__ <<
"Invalid play command attempted. Can only play when the Iterator is "
2742 "inactive or paused."
2743 <<
" If you would like to restart an iteration plan, first try halting "
2746 __COUT__ << ss.str();
2748 xmldoc.addTextElementToData(
"error_message", ss.str());
2750 __COUT__ <<
"Invalid play command attempted. " << activePlanIsRunning_ <<
" "
2751 << commandPlay_ <<
" " << activePlanName_ << __E__;
2758 __COUT__ <<
"Attempting to pause iteration plan '" << activePlanName_ <<
".'"
2760 __COUT__ <<
"Attempting to pause iteration plan '" << activePlanName_ <<
".'"
2767 if(theSupervisor_->VERBOSE_MUTEX)
2768 __COUT__ <<
"Waiting for iterator access" << __E__;
2769 std::lock_guard<std::mutex> lock(accessMutex_);
2770 if(theSupervisor_->VERBOSE_MUTEX)
2771 __COUT__ <<
"Have iterator access" << __E__;
2773 if(workloopRunning_ && activePlanIsRunning_ && !commandPause_)
2775 commandPause_ =
true;
2779 __SS__ <<
"Invalid pause command attempted. Can only pause when running."
2781 __COUT__ << ss.str();
2783 xmldoc.addTextElementToData(
"error_message", ss.str());
2785 __COUT__ <<
"Invalid pause command attempted. " << workloopRunning_ <<
" "
2786 << activePlanIsRunning_ <<
" " << commandPause_ <<
" " << activePlanName_
2794 __COUT__ <<
"Attempting to halt iteration plan '" << activePlanName_ <<
".'" << __E__;
2795 __COUT__ <<
"Attempting to halt iteration plan '" << activePlanName_ <<
".'" << __E__;
2799 if(workloopRunning_)
2803 if(theSupervisor_->VERBOSE_MUTEX)
2804 __COUT__ <<
"Waiting for iterator access" << __E__;
2805 std::lock_guard<std::mutex> lock(accessMutex_);
2806 if(theSupervisor_->VERBOSE_MUTEX)
2807 __COUT__ <<
"Have iterator access" << __E__;
2809 __COUT__ <<
"activePlanIsRunning_: " << activePlanIsRunning_ << __E__;
2810 __COUT__ <<
"Passing halt command to iterator thread." << __E__;
2811 commandHalt_ =
true;
2814 activePlanName_ =
"";
2815 activeCommandIndex_ = -1;
2819 __COUT__ <<
"No thread, so conducting halt. lastFsmName_ = " << lastFsmName_
2823 ->activeStateMachineName_;
2824 __COUTV__(lastFsmName_);
2825 Iterator::haltIterator(
this);
2833 xmldoc.addTextElementToData(
2835 theSupervisor_->theStateMachine_.isInTransition()
2836 ? theSupervisor_->theStateMachine_.getCurrentTransitionName(
2837 theSupervisor_->stateMachineLastCommandInput_)
2838 : theSupervisor_->theStateMachine_.getCurrentStateName());
2842 if(theSupervisor_->theStateMachine_.isInTransition())
2843 xmldoc.addTextElementToData(
2844 "transition_progress",
2847 xmldoc.addTextElementToData(
"transition_progress",
"100");
2849 xmldoc.addNumberElementToData(
"time_in_state",
2854 if(theSupervisor_->VERBOSE_MUTEX)
2855 __COUT__ <<
"Waiting for iterator access" << __E__;
2856 std::lock_guard<std::mutex> lock(accessMutex_);
2857 if(theSupervisor_->VERBOSE_MUTEX)
2858 __COUT__ <<
"Have iterator access" << __E__;
2860 xmldoc.addTextElementToData(
"active_plan", activePlanName_);
2861 xmldoc.addTextElementToData(
"last_started_plan", lastStartedPlanName_);
2862 xmldoc.addTextElementToData(
"last_finished_plan", lastFinishedPlanName_);
2864 for(
const auto& f : lastPlanOutputFiles_)
2866 xmldoc.addTextElementToData(
"output_file_subsystem", f.subsystem);
2867 xmldoc.addTextElementToData(
"output_file_path", f.path);
2868 xmldoc.addTextElementToData(
"output_file_label", f.label);
2869 xmldoc.addTextElementToData(
"output_file_icon", f.iconName);
2872 xmldoc.addNumberElementToData(
"current_command_index", activeCommandIndex_);
2873 xmldoc.addNumberElementToData(
"current_number_of_commands", activeNumberOfCommands_);
2874 xmldoc.addTextElementToData(
"current_command_type", activeCommandType_);
2875 xmldoc.addNumberElementToData(
"current_command_duration",
2876 time(0) - activeCommandStartTime_);
2877 xmldoc.addNumberElementToData(
"current_command_iteration", activeCommandIteration_);
2878 for(
const auto& depthIteration : depthIterationStack_)
2879 xmldoc.addNumberElementToData(
"depth_iteration", depthIteration);
2881 if(activePlanName_ == Iterator::RESERVED_GEN_PLAN_NAME)
2883 xmldoc.addNumberElementToData(
"generated_number_of_runs", genPlanNumberOfRuns_);
2884 xmldoc.addNumberElementToData(
"generated_duration_of_runs",
2885 genPlanDurationSeconds_);
2888 if(activePlanIsRunning_ && iteratorBusy_)
2890 if(workloopRunning_)
2891 xmldoc.addTextElementToData(
"active_plan_status",
"Running");
2893 xmldoc.addTextElementToData(
"active_plan_status",
2896 else if(!activePlanIsRunning_ && iteratorBusy_)
2898 if(errorMessage_.size())
2899 xmldoc.addTextElementToData(
2900 "active_plan_status",
2903 xmldoc.addTextElementToData(
"active_plan_status",
"Paused");
2906 xmldoc.addTextElementToData(
"active_plan_status",
"Inactive");
2908 xmldoc.addTextElementToData(
"error_message", errorMessage_);
2912 size_t Iterator::findRemoteGatewayApp(IteratorWorkLoopStruct* iteratorStruct,
2913 const std::string& targetSubsystem)
2915 auto& remoteApps = iteratorStruct->theIterator_->theSupervisor_->remoteGatewayApps_;
2916 for(
size_t i = 0; i < remoteApps.size(); ++i)
2917 if(remoteApps[i].appInfo.name == targetSubsystem)
2920 __SS__ <<
"Target subsystem '" << targetSubsystem
2921 <<
"' not found in remote gateway apps." << __E__;
2926 void Iterator::queueRemoteGatewayCommand(IteratorWorkLoopStruct* iteratorStruct,
2927 size_t remoteAppIndex,
2928 const std::string& command,
2929 const std::string& statusLabel)
2932 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayApps_[remoteAppIndex];
2934 if(remoteApp.command !=
"")
2936 __SS__ <<
"Remote subsystem '" << remoteApp.appInfo.name
2937 <<
"' already has a pending command: " << remoteApp.command << __E__;
2941 remoteApp.clearError();
2942 remoteApp.command = command;
2943 remoteApp.fsmName = iteratorStruct->fsmName_;
2944 remoteApp.appInfo.status =
"Launching " + statusLabel;
2945 remoteApp.appInfo.progress = 0;
2946 remoteApp.commandSentTime = time(0);
2948 __COUT__ <<
"Remote command '" << command <<
"' queued for subsystem '"
2949 << remoteApp.appInfo.name <<
"'" << __E__;
2955 std::string Iterator::buildRemoteConfigureCommand(IteratorWorkLoopStruct* iteratorStruct,
2956 const std::string& systemAlias)
2960 std::string command =
2961 RunControlStateMachine::CONFIGURE_TRANSITION_NAME +
"," + systemAlias;
2963 std::string subsystemCommonList =
2965 ConfigurationManager::SUBSYSTEM_COMMON_VERSION_ALIAS));
2966 if(subsystemCommonList.size())
2967 command +=
"," + GatewaySupervisor::COMMAND_PARAM_SUBSYSTEM_COMMON_PREAMBLE +
2968 StringMacros::encodeURIComponent(subsystemCommonList);
2970 std::string subsystemCommonOverrideList =
2972 ConfigurationManager::SUBSYSTEM_COMMON_OVERRIDE_VERSION_ALIAS));
2973 if(subsystemCommonOverrideList.size())
2975 GatewaySupervisor::COMMAND_PARAM_SUBSYSTEM_COMMON_OVERRIDE_PREAMBLE +
2976 StringMacros::encodeURIComponent(subsystemCommonOverrideList);
2978 std::string logEntry = gw->getLastLogEntry(
2979 RunControlStateMachine::CONFIGURE_TRANSITION_NAME, iteratorStruct->fsmName_);
2981 command +=
"," + GatewaySupervisor::COMMAND_PARAM_LOG_ENTRY_PREAMBLE +
2982 StringMacros::encodeURIComponent(logEntry);
2988 void Iterator::startRemoteCommandFSMTransition(IteratorWorkLoopStruct* iteratorStruct,
2989 const std::string& transitionCommand,
2990 const std::string& targetSubsystem)
2992 __COUT__ <<
"startRemoteCommandFSMTransition: " << transitionCommand <<
" targeting '"
2993 << targetSubsystem <<
"'" << __E__;
2995 std::lock_guard<std::mutex> lock(
2996 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayAppsMutex_);
2998 queueRemoteGatewayCommand(iteratorStruct,
2999 findRemoteGatewayApp(iteratorStruct, targetSubsystem),
3005 bool Iterator::checkRemoteCommandFSMTransition(IteratorWorkLoopStruct* iteratorStruct,
3006 const std::string& finalState,
3007 const std::string& targetSubsystem)
3011 std::lock_guard<std::mutex> lock(
3012 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayAppsMutex_);
3014 const auto& remoteApp =
3015 iteratorStruct->theIterator_->theSupervisor_
3016 ->remoteGatewayApps_[findRemoteGatewayApp(iteratorStruct, targetSubsystem)];
3018 if(remoteApp.getError() !=
"")
3020 __SS__ <<
"Remote subsystem '" << targetSubsystem
3021 <<
"' reported error: " << remoteApp.getError() << __E__;
3025 if(remoteApp.command !=
"")
3027 __COUT__ <<
"Waiting for command to be sent to '" << targetSubsystem <<
"'..."
3032 const std::string& remoteStatus = remoteApp.appInfo.status;
3033 __COUT__ <<
"Remote subsystem '" << targetSubsystem <<
"' status: " << remoteStatus
3034 <<
" (waiting for '" << finalState <<
"')" << __E__;
3038 if(finalState != RunControlStateMachine::HALTED_STATE_NAME &&
3039 remoteStatus.find(RunControlStateMachine::FAILED_STATE_NAME) == 0)
3041 __SS__ <<
"Remote subsystem '" << targetSubsystem <<
"' entered '" << remoteStatus
3042 <<
"' while waiting for '" << finalState <<
"'" << __E__;
3046 if(remoteStatus == finalState)
3048 __COUT__ <<
"checkRemoteCommandFSMTransition complete for '" << targetSubsystem
3058 void Iterator::startRemoteCommandConfigure(IteratorWorkLoopStruct* iteratorStruct,
3059 const std::string& systemAlias,
3060 const std::string& targetSubsystem)
3062 __COUT__ <<
"startRemoteCommandConfigure: alias '" << systemAlias <<
"' targeting '"
3063 << targetSubsystem <<
"'" << __E__;
3065 iteratorStruct->fsmCommandParameters_.clear();
3066 iteratorStruct->fsmCommandParameters_.push_back(systemAlias);
3067 iteratorStruct->remoteConfigureQueued_ =
false;
3069 std::lock_guard<std::mutex> lock(
3070 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayAppsMutex_);
3072 size_t remoteAppIndex = findRemoteGatewayApp(iteratorStruct, targetSubsystem);
3073 std::string currentState =
3074 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayApps_[remoteAppIndex]
3076 __COUTV__(currentState);
3078 if(currentState == RunControlStateMachine::INITIAL_STATE_NAME ||
3079 currentState == RunControlStateMachine::HALTED_STATE_NAME)
3081 queueRemoteGatewayCommand(
3084 buildRemoteConfigureCommand(iteratorStruct, systemAlias),
3085 RunControlStateMachine::CONFIGURE_TRANSITION_NAME);
3087 else if(currentState == RunControlStateMachine::CONFIGURED_STATE_NAME ||
3088 currentState.find(RunControlStateMachine::FAILED_STATE_NAME) == 0)
3090 if(commandSkipsIfConfigured(iteratorStruct) &&
3091 currentState == RunControlStateMachine::CONFIGURED_STATE_NAME)
3094 <<
"Remote subsystem '" << targetSubsystem
3095 <<
"' already configured and SkipIfAlreadyConfigured is set, so "
3096 "leaving its configuration as-is."
3101 queueRemoteGatewayCommand(iteratorStruct,
3103 RunControlStateMachine::HALT_TRANSITION_NAME,
3104 RunControlStateMachine::HALT_TRANSITION_NAME);
3105 iteratorStruct->remoteConfigureQueued_ =
true;
3109 __SS__ <<
"Iterator failed to configure remote subsystem '" << targetSubsystem
3110 <<
"' with system alias '" << systemAlias
3111 <<
"': Can only Configure from the Initial or Halted state. The current "
3113 << currentState << __E__;
3117 __COUT__ <<
"startRemoteCommandConfigure success." << __E__;
3121 bool Iterator::checkRemoteCommandConfigure(IteratorWorkLoopStruct* iteratorStruct,
3122 const std::string& targetSubsystem)
3126 std::lock_guard<std::mutex> lock(
3127 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayAppsMutex_);
3129 size_t remoteAppIndex = findRemoteGatewayApp(iteratorStruct, targetSubsystem);
3131 iteratorStruct->theIterator_->theSupervisor_->remoteGatewayApps_[remoteAppIndex];
3133 if(remoteApp.getError() !=
"")
3135 __SS__ <<
"Iterator failed to configure remote subsystem '" << targetSubsystem
3136 <<
"' with system alias '"
3137 << (iteratorStruct->fsmCommandParameters_.size()
3138 ? iteratorStruct->fsmCommandParameters_[0]
3140 <<
"' because of the following error: " << remoteApp.getError() << __E__;
3144 if(remoteApp.command !=
"")
3146 __COUT__ <<
"Waiting for command to be sent to '" << targetSubsystem <<
"'..."
3151 const std::string& currentState = remoteApp.appInfo.status;
3152 __COUT__ <<
"Remote subsystem '" << targetSubsystem <<
"' status: " << currentState
3155 if(iteratorStruct->remoteConfigureQueued_)
3160 if(currentState == RunControlStateMachine::HALTED_STATE_NAME)
3162 queueRemoteGatewayCommand(
3165 buildRemoteConfigureCommand(iteratorStruct,
3166 iteratorStruct->fsmCommandParameters_[0]),
3167 RunControlStateMachine::CONFIGURE_TRANSITION_NAME);
3168 iteratorStruct->remoteConfigureQueued_ =
false;
3173 if(currentState.find(RunControlStateMachine::FAILED_STATE_NAME) == 0)
3175 __SS__ <<
"Remote subsystem '" << targetSubsystem <<
"' entered '" << currentState
3176 <<
"' while configuring." << __E__;
3180 if(currentState == RunControlStateMachine::CONFIGURED_STATE_NAME)
3182 __COUT__ <<
"checkRemoteCommandConfigure complete for '" << targetSubsystem <<
"'"
3197 Iterator::MacroLoopSpec Iterator::parseMacroLoopSpec(
const std::string& inputArgs)
3201 std::vector<std::string> dimensions;
3204 if(dimensions.size() == 0 || (dimensions.size() == 1 && dimensions[0] ==
""))
3206 spec.dimIterations.push_back(1);
3207 spec.dimArgs.push_back({});
3210 for(
unsigned int d = 0; d < dimensions.size(); ++d)
3212 std::vector<std::string> args;
3214 if(args.size() == 0 || args[0] ==
"")
3216 __SS__ <<
"Invalid dimensional arguments! Need number of iterations at "
3221 unsigned long numOfIterations;
3223 if(numOfIterations == 0)
3225 __SS__ <<
"Illegal number of iterations '" << args[0] <<
"' at dimension "
3226 << d <<
". Must be a positive integer!" << __E__;
3229 spec.dimIterations.push_back(numOfIterations);
3230 spec.dimArgs.push_back({});
3232 for(
unsigned int a = 1; a < args.size(); ++a)
3235 std::string name, init, step;
3238 __SS__ <<
"Invalid argument '" << args[a]
3239 <<
"'! Expected name:initialValue:stepSize." << __E__;
3245 MacroLoopSpec::Arg arg;
3247 if(isConstantMacroStep(step))
3250 arg.type = MacroLoopSpec::Arg::STRING;
3253 else if((init.size() &&
3254 (init.back() ==
'f' || init.find(
'.') != std::string::npos)) ||
3256 (step.back() ==
'f' || step.find(
'.') != std::string::npos)))
3258 arg.type = MacroLoopSpec::Arg::DOUBLE;
3259 arg.dInit = strtod(init.c_str(), 0);
3260 arg.dStep = strtod(step.c_str(), 0);
3264 arg.type = MacroLoopSpec::Arg::LONG;
3268 spec.dimArgs.back().push_back(arg);
3273 spec.totalIterations = 1;
3274 for(
unsigned long n : spec.dimIterations)
3275 if(__builtin_mul_overflow(
3276 spec.totalIterations, (uint64_t)n, &spec.totalIterations))
3278 __SS__ <<
"Dimensional loop '" << inputArgs
3279 <<
"' has more iterations than can be counted (product overflows)."
3285 for(
const auto& dim : spec.dimArgs)
3286 for(
const auto& arg : dim)
3289 for(
const auto& existing : spec.argNames)
3290 if(existing == arg.name)
3296 spec.argNames.push_back(arg.name);
3306 std::string Iterator::macroArgValueForLabel(
const std::string& value)
3310 char* end =
nullptr;
3311 long long v = strtoll(value.c_str(), &end, 0 );
3312 if(end == value.c_str() || *end !=
'\0')
3314 std::stringstream ss;
3315 ss << v <<
" (0x" << std::hex << std::uppercase << v <<
")";
3324 std::string Iterator::macroArgsSummary(
const std::string& inputArgs)
3328 const MacroLoopSpec spec = parseMacroLoopSpec(inputArgs);
3329 const auto values = macroLoopIteration(spec, 0);
3331 for(
size_t a = 0; a < values.size(); ++a)
3332 str += (a ?
", " :
"") + feMacroArgBaseName(values[a].first) +
" = " +
3333 macroArgValueForLabel(values[a].second);
3334 if(spec.totalIterations > 1)
3335 str +=
" (x" + std::to_string(spec.totalIterations) +
")";
3348 std::vector<std::pair<std::string, std::string>> Iterator::macroLoopIteration(
3349 const MacroLoopSpec& spec, uint64_t index)
3352 std::vector<uint64_t> counters(spec.dimIterations.size(), 0);
3353 for(
size_t d = spec.dimIterations.size(); d-- > 0;)
3355 counters[d] = index % spec.dimIterations[d];
3356 index /= spec.dimIterations[d];
3359 std::vector<std::pair<std::string, std::string>> argsIn;
3360 for(
size_t d = 0; d < spec.dimArgs.size(); ++d)
3361 for(
const auto& arg : spec.dimArgs[d])
3364 for(
const auto& existing : argsIn)
3365 if(existing.first == arg.name)
3373 arg.type == MacroLoopSpec::Arg::LONG
3374 ? std::to_string(arg.lInit + arg.lStep * (
long)counters[d])
3375 : arg.type == MacroLoopSpec::Arg::DOUBLE
3376 ? std::to_string(arg.dInit + arg.dStep * (double)counters[d])
3378 argsIn.emplace_back(arg.name, value);
3384 unsigned int Iterator::getStepIndexForLabel(IteratorWorkLoopStruct* iteratorStruct,
3385 const std::string& label)
3387 if(iteratorStruct->stepIndexStack_.empty())
3391 if(label ==
"" || label == TableViewColumnInfo::DATATYPE_STRING_DEFAULT ||
3392 label == TableViewColumnInfo::DATATYPE_STRING_ALT_DEFAULT)
3393 return iteratorStruct->stepIndexStack_.back();
3396 for(
size_t i = iteratorStruct->stepLabelStack_.size(); i-- > 0;)
3397 if(iteratorStruct->stepLabelStack_[i] == label &&
3398 i < iteratorStruct->stepIndexStack_.size())
3399 return iteratorStruct->stepIndexStack_[i];
3401 __COUT_WARN__ <<
"Step label '" << label
3402 <<
"' is not an open BEGIN_LABEL at this command (open labels: "
3404 <<
"). Using pass index 0." << __E__;
3412 bool Iterator::isConstantMacroStep(
const std::string& step)
3414 if(step == TableViewColumnInfo::DATATYPE_STRING_DEFAULT ||
3415 step == TableViewColumnInfo::DATATYPE_STRING_ALT_DEFAULT)
3417 double stepValue = 1;
3426 std::string Iterator::applyStepIndexToMacroArgs(IteratorWorkLoopStruct* iteratorStruct,
3427 const std::string& inputArgs,
3428 const std::string& labelsStr)
3433 std::vector<std::string> dimensions, labels;
3438 for(
size_t d = 0; d < dimensions.size(); ++d)
3440 std::string label = d < labels.size() ? labels[d] :
"";
3441 unsigned int stepIndex = getStepIndexForLabel(iteratorStruct, label);
3443 std::vector<std::string> args;
3448 for(
size_t a = 0; a < args.size(); ++a)
3458 std::vector<std::string> pieces(3);
3460 args[a], pieces[0], pieces[1], pieces[2]))
3472 if(isConstantMacroStep(step))
3479 std::string newInit;
3481 (init.back() ==
'f' || init.find(
'.') != std::string::npos)) ||
3483 (step.back() ==
'f' || step.find(
'.') != std::string::npos)))
3484 newInit = std::to_string(strtod(init.c_str(), 0) +
3485 strtod(step.c_str(), 0) * stepIndex);
3488 long initValue = 0, stepValue = 0;
3491 newInit = std::to_string(initValue + stepValue * (
long)stepIndex);
3494 __COUT_INFO__ <<
"Macro arg '" << name <<
"' pass " << stepIndex
3495 << (label.size() ? (
" of label '" + label +
"'") :
"") <<
": "
3496 << init <<
" + " << step <<
"*" << stepIndex <<
" = " << newInit
3500 out += StringMacros::encodeURIComponent(name) +
":" +
3501 StringMacros::encodeURIComponent(newInit) +
":" +
3502 StringMacros::encodeURIComponent(step);
3513 std::string Iterator::feMacroArgBaseName(
const std::string& argName)
3515 std::string base = argName.substr(0, argName.find(
'('));
3516 size_t end = base.find_last_not_of(
" \t");
3517 return end == std::string::npos ? std::string() : base.substr(0, end + 1);
3526 void Iterator::startRemoteCommandMacro(IteratorWorkLoopStruct* iteratorStruct,
3529 auto& command = iteratorStruct->commands_[iteratorStruct->commandIndex_];
3530 const std::string targetSubsystem = command.targetSubsystem_;
3531 const std::string macroName =
3532 command.params_[IterateTable::commandExecuteMacroParams_.MacroName_];
3533 const bool saveOutputs =
3534 command.params_[IterateTable::commandExecuteMacroParams_.EnableSavingOutput_] ==
3536 const std::string inputArgs = applyStepIndexToMacroArgs(
3538 command.params_[IterateTable::commandExecuteMacroParams_.MacroArgumentString_],
3539 command.params_[IterateTable::commandExecuteMacroParams_.MacroArgumentLabels_]);
3541 __COUT__ <<
"startRemoteCommandMacro: '" << macroName <<
"' targeting '"
3542 << targetSubsystem <<
"' isFEMacro=" << isFEMacro << __E__;
3543 __COUTV__(inputArgs);
3545 if(command.targets_.size() == 0)
3547 __SS__ <<
"No target front-ends defined for remote macro '" << macroName
3548 <<
"' on subsystem '" << targetSubsystem <<
"'" << __E__;
3555 std::string ipPort = gw->getRemoteMacroMakerUDPAddress(targetSubsystem);
3562 GatewaySupervisor::RemoteFEMacroInfo info =
3563 GatewaySupervisor::parseFEMacroInfo(GatewaySupervisor::queryRemoteMacroMaker(
3564 ipPort,
"GetFrontendMacroInfo", 10 , localIpAddress));
3565 __COUT__ <<
"Remote subsystem '" << targetSubsystem <<
"' has " << info.fes.size()
3566 <<
" live front-end(s) and " << info.publicMacros.size()
3567 <<
" public MacroMaker macro(s)." << __E__;
3570 std::vector<std::string> inputNames, outputNames;
3572 for(
size_t t = 0; t < command.targets_.size(); ++t)
3574 const std::string& uid = command.targets_[t].UID_;
3575 auto feIt = info.fes.find(uid);
3576 if(feIt == info.fes.end())
3578 __SS__ <<
"Front-end '" << uid <<
"' is not live on remote subsystem '"
3580 <<
"'. Is it enabled and is the subsystem Configured? "
3581 <<
"Live front-ends: ";
3582 for(
const auto& fe : info.fes)
3583 ss << fe.first <<
" ";
3589 auto macroIt = feIt->second.macros.find(macroName);
3590 if(macroIt == feIt->second.macros.end())
3592 __SS__ <<
"FE Macro '" << macroName <<
"' not found on front-end '" << uid
3593 <<
"' of remote subsystem '" << targetSubsystem
3594 <<
"'. Available: ";
3595 for(
const auto& m : feIt->second.macros)
3596 ss << m.first <<
" ";
3602 inputNames = macroIt->second.inputs;
3603 outputNames = macroIt->second.outputs;
3612 const auto& otherInputs = macroIt->second.inputs;
3613 bool same = otherInputs.size() == inputNames.size();
3614 for(
size_t k = 0; same && k < inputNames.size(); ++k)
3615 same = feMacroArgBaseName(otherInputs[k]) ==
3616 feMacroArgBaseName(inputNames[k]);
3619 __SS__ <<
"FE Macro '" << macroName <<
"' on front-end '" << uid
3620 <<
"' of remote subsystem '" << targetSubsystem
3621 <<
"' declares inputs ["
3623 <<
"] which differ from front-end '"
3624 << command.targets_[0].UID_ <<
"' inputs ["
3626 <<
"]. All targets of one remote macro command must share "
3627 "the same input signature."
3631 const auto& otherOutputs = macroIt->second.outputs;
3632 if(otherOutputs != outputNames)
3634 __SS__ <<
"FE Macro '" << macroName <<
"' on front-end '" << uid
3635 <<
"' of remote subsystem '" << targetSubsystem
3636 <<
"' declares outputs ["
3638 <<
"] which differ from front-end '"
3639 << command.targets_[0].UID_ <<
"' outputs ["
3641 <<
"]. All targets of one remote macro command must share "
3642 "the same output signature; use separate commands for "
3643 "front-ends with different signatures."
3655 auto macroIt = info.publicMacros.find(macroName);
3656 if(macroIt == info.publicMacros.end())
3658 __SS__ <<
"MacroMaker macro '" << macroName
3659 <<
"' not found among the PUBLIC macros of remote subsystem '"
3661 <<
"' (only public macros can be run remotely; make a private macro "
3662 "public in MacroMaker first). Available: ";
3663 for(
const auto& m : info.publicMacros)
3664 ss << m.first <<
" ";
3668 inputNames = macroIt->second.inputs;
3669 outputNames = macroIt->second.outputs;
3678 const MacroLoopSpec spec = parseMacroLoopSpec(inputArgs);
3682 std::vector<bool> used(spec.argNames.size(),
false);
3683 for(
const auto& inputName : inputNames)
3685 const std::string inputBase = feMacroArgBaseName(inputName);
3687 for(
size_t a = 0; a < spec.argNames.size(); ++a)
3688 if(!used[a] && feMacroArgBaseName(spec.argNames[a]) == inputBase)
3690 inputToArgIndex.push_back(a);
3703 <<
"ArgIn '" << inputName
3704 <<
"' was not assigned a value by any dimensional loop parameter "
3705 "sets. This is illegal. Macro '"
3706 << macroName <<
"' requires '" << inputName
3707 <<
"' as an input argument. Either remove the input argument "
3709 "the macro, or define a value as a dimensional loop parameter."
3713 inputToArgIndex.push_back(SIZE_MAX);
3715 <<
"ArgIn '" << inputName
3716 <<
"' was not specified by the Iterator command for FE macro '"
3717 << macroName <<
"'; using 'Default' for this argument." << __E__;
3720 for(
size_t a = 0; a < spec.argNames.size(); ++a)
3722 __COUT_WARN__ <<
"Dimensional loop parameter '" << spec.argNames[a]
3723 <<
"' is not an input of macro '" << macroName
3724 <<
"' on remote subsystem '" << targetSubsystem
3725 <<
"'; it will not be sent." << __E__;
3729 std::stringstream hdr;
3730 hdr <<
"Remote macro '" << macroName <<
"' on subsystem '" << targetSubsystem
3731 <<
"' targets [" << uidCSV <<
"]: " << spec.totalIterations
3732 <<
" iteration(s) from loop spec '" << inputArgs <<
"'";
3734 hdr <<
". Output saving is enabled: the remote MacroMaker writes "
3735 "macroOutput_<time>.txt under its OTSDAQ_DATA (OutputFilePath/Radix "
3737 "not applied to remote targets)";
3738 __COUT_INFO__ << hdr.str() << __E__;
3741 std::string outputCSV;
3742 for(
size_t i = 0; i < outputNames.size(); ++i)
3743 outputCSV += (i ?
"," :
"") + StringMacros::encodeURIComponent(outputNames[i]);
3745 auto run = std::make_shared<IteratorWorkLoopStruct::RemoteMacroRun>();
3746 run->iterationsTotal = spec.totalIterations;
3747 iteratorStruct->remoteMacroRun_ = run;
3758 macroType = std::string(isFEMacro ?
"fe" :
"public"),
3764 targetSubsystem]() {
3767 const uint64_t total = spec.totalIterations;
3768 for(uint64_t i = 0; i < total; ++i)
3772 __COUT_INFO__ <<
"Remote macro '" << macroName
3773 <<
"' aborted before iteration " << i + 1 <<
" of "
3780 const auto values = macroLoopIteration(spec, i);
3781 std::string inputStr,
3783 for(
size_t k = 0; k < inputNames.size(); ++k)
3785 const std::string val = inputToArgIndex[k] == SIZE_MAX
3786 ? std::string(
"Default")
3787 : values[inputToArgIndex[k]].second;
3788 inputStr += (k ?
";" :
"") +
3789 StringMacros::encodeURIComponent(inputNames[k]) +
"," +
3790 StringMacros::encodeURIComponent(val);
3791 argsSummary += (k ?
", " :
"") + feMacroArgBaseName(inputNames[k]) +
3792 " = " + macroArgValueForLabel(val);
3796 std::string cmd =
"RunFrontendMacro;*;" + uidCSV +
";" + macroType +
";" +
3797 StringMacros::encodeURIComponent(macroName) +
";" +
3798 StringMacros::encodeURIComponent(inputStr) +
";" +
3799 StringMacros::encodeURIComponent(outputCSV) +
";" +
3800 (saveOutputs ?
"1" :
"0");
3802 __COUT_INFO__ <<
"Remote macro '" << macroName <<
"' iteration " << i + 1
3803 <<
" of " << total <<
" inputs: " << inputStr << __E__;
3805 std::string response = GatewaySupervisor::queryRemoteMacroMaker(
3811 std::lock_guard<std::mutex> lock(run->mutex);
3812 run->progress = pct;
3816 if(response.find(
"Error") == 0)
3818 std::lock_guard<std::mutex> lock(run->mutex);
3819 run->error =
"iteration " + std::to_string(i + 1) +
" of " +
3820 std::to_string(total) +
": " + response;
3829 std::string argName;
3831 response,
"feMacroRunArgs_name", 0, fAfter, &fAfter)) !=
3834 fAfter += strlen(
"feMacroRunArgs_name");
3836 response,
"feMacroRunArgs_value", 0, fAfter, &fAfter);
3837 fAfter += strlen(
"feMacroRunArgs_value");
3838 if(argName ==
"Filename" && argValue !=
"")
3840 __COUT_INFO__ <<
"Remote macro '" << macroName
3841 <<
"' iteration " << i + 1
3842 <<
" output file on '" << targetSubsystem
3843 <<
"': " << argValue << __E__;
3844 std::lock_guard<std::mutex> lock(run->mutex);
3845 run->outputFiles.emplace_back(argValue, argsSummary);
3854 response,
"fe_uid", 0, after, &after)) !=
"")
3856 after += strlen(
"fe_uid");
3857 size_t argAfter = after;
3858 std::string outName, outValue, outputs;
3860 size_t nextFe = response.find(
"<fe_uid", after);
3862 response,
"outputArgs_name", 0, argAfter, &argAfter)) !=
3864 (nextFe == std::string::npos || argAfter < nextFe))
3866 argAfter += strlen(
"outputArgs_name");
3868 response,
"outputArgs_value", 0, argAfter, &argAfter);
3869 argAfter += strlen(
"outputArgs_value");
3870 outputs +=
" " + outName +
"=" +
3873 __COUT_INFO__ <<
"Remote macro '" << macroName <<
"' iteration "
3874 << i + 1 <<
" FE '" << feUid <<
"' outputs:" << outputs
3878 std::lock_guard<std::mutex> lock(run->mutex);
3879 ++run->iterationsDone;
3883 catch(
const std::runtime_error& e)
3886 __COUT_INFO__ <<
"Remote macro '" << macroName
3887 <<
"' aborted mid-iteration: " << e.what() << __E__;
3890 std::lock_guard<std::mutex> lock(run->mutex);
3891 run->error = e.what();
3896 std::lock_guard<std::mutex> lock(run->mutex);
3897 run->error =
"unknown error";
3902 __COUT__ <<
"startRemoteCommandMacro launched for '" << targetSubsystem <<
"'"
3911 bool Iterator::checkRemoteCommandMacro(IteratorWorkLoopStruct* iteratorStruct,
3916 auto run = iteratorStruct->remoteMacroRun_;
3919 __SS__ <<
"No remote macro run in progress!?" << __E__;
3923 if(iteratorStruct->doHaltAction_ && !run->abort)
3925 __COUT_INFO__ <<
"Halt requested: interrupting the remote macro run." << __E__;
3930 uint64_t itDone, itTotal;
3933 std::lock_guard<std::mutex> lock(run->mutex);
3935 itDone = run->iterationsDone;
3936 itTotal = run->iterationsTotal;
3937 progress = run->progress;
3942 iteratorStruct->remoteMacroRun_.reset();
3943 auto& command = iteratorStruct->commands_[iteratorStruct->commandIndex_];
3944 __SS__ <<
"Remote macro '"
3945 << command.params_[IterateTable::commandExecuteMacroParams_.MacroName_]
3946 <<
"' on subsystem '" << command.targetSubsystem_ <<
"' failed: " << error
3951 __COUT__ <<
"Remote macro progress: " << itDone <<
" of " << itTotal
3952 <<
" iteration(s) done, current iteration " << progress <<
"%" << __E__;
3957 std::vector<std::pair<std::string, std::string>> files;
3959 std::lock_guard<std::mutex> lock(run->mutex);
3960 files = run->outputFiles;
3964 auto& command = iteratorStruct->commands_[iteratorStruct->commandIndex_];
3965 const std::string macroName =
3966 command.params_[IterateTable::commandExecuteMacroParams_.MacroName_];
3968 for(
size_t t = 0; t < command.targets_.size(); ++t)
3969 uids += (t ?
"," :
"") + command.targets_[t].UID_;
3970 const std::string iconName = findRemoteCodeEditorIconName(
3971 iteratorStruct->theIterator_->theSupervisor_, command.targetSubsystem_);
3975 const std::string pass = std::to_string(
3976 iteratorStruct->commandIterations_[iteratorStruct->commandIndex_]);
3977 for(
size_t i = 0; i < files.size(); ++i)
3979 std::string label = macroName +
" on " + uids +
" iteration #" + pass;
3980 if(files.size() > 1)
3981 label +=
"." + std::to_string(i + 1);
3982 if(files[i].second !=
"")
3983 label +=
" [" + files[i].second +
"]";
3984 iteratorStruct->outputFiles_.push_back(
3985 {command.targetSubsystem_, files[i].first, label, iconName});
3989 iteratorStruct->remoteMacroRun_.reset();
3990 __COUT__ <<
"checkRemoteCommandMacro complete." << __E__;
4001 std::string Iterator::findRemoteCodeEditorIconName(
GatewaySupervisor* supervisor,
4002 const std::string& targetSubsystem)
4004 std::string iconString, folderPath;
4007 for(
const auto& app : supervisor->remoteGatewayApps_)
4008 if(app.appInfo.name == targetSubsystem)
4010 iconString = app.iconString;
4011 folderPath = app.parentIconFolderPath;
4015 if(iconString ==
"")
4021 for(
size_t i = 0; i + 6 < parts.size(); i += 7)
4023 const std::string& caption = parts[i];
4024 const std::string& linkurl = parts[i + 5];
4025 if(linkurl.find(
"CodeEditor") != std::string::npos ||
4026 caption.find(
"Code Editor") != std::string::npos)
4029 std::string folder = parts[i + 6];
4030 while(folder.size() && folder[0] ==
'/')
4031 folder = folder.substr(1);
4032 while(folder.size() && folder.back() ==
'/')
4034 return folder.size() ? folder +
"/" + caption : caption;
4037 __COUT_WARN__ <<
"No Code Editor desktop icon found for remote subsystem '"
4038 << targetSubsystem <<
"' (folder '" << folderPath
4039 <<
"'); output file links will show the path only." << __E__;
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 groupTypeToLoad=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false)
std::map< std::string, std::map< std::string, TableVersion > > getVersionAliases(void) const
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
std::string ipAddressForStateChangesOverUDP_
IP used for UDP reverse-login propagation to remote gateways.
std::mutex remoteGatewayAppsMutex_
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)
defines used also by OtsConfigurationWizardSupervisor
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static std::string extractXmlField(const std::string &xml, const std::string &field, uint32_t occurrence, size_t after, size_t *returnFindPos=nullptr, const std::string &valueField="value=", const std::string "eType="'")
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 bool splitMacroArgTriple(const std::string &inputString, std::string &name, std::string &initValue, std::string &stepValue, char delimiter=':')
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
setToString ~
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)