tdaq-develop-2025-02-12
RunControlStateMachine.cc
1 #include "otsdaq/FiniteStateMachine/RunControlStateMachine.h"
2 #include "otsdaq/MessageFacility/MessageFacility.h"
3 
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/Macros/StringMacros.h"
6 
7 #include "otsdaq/SOAPUtilities/SOAPCommand.h"
8 #include "otsdaq/SOAPUtilities/SOAPUtilities.h"
9 
10 #include <toolbox/fsm/FailedEvent.h>
11 #include <xdaq/NamespaceURI.h>
12 #include <xoap/Method.h>
13 
14 #include <iostream>
15 
16 #undef __MF_SUBJECT__
17 #define __MF_SUBJECT__ "FSM"
18 #define mfSubject_ std::string("FSM-") + theStateMachine_.getStateMachineName()
19 
20 using namespace ots;
21 
22 // clang-format off
23 
24 const std::string RunControlStateMachine::FAILED_STATE_NAME = FiniteStateMachine::FAILED_STATE_NAME;
25 const std::string RunControlStateMachine::INITIAL_STATE_NAME = "Initial";
26 const std::string RunControlStateMachine::HALTED_STATE_NAME = "Halted";
27 const std::string RunControlStateMachine::PAUSED_STATE_NAME = "Paused";
28 const std::string RunControlStateMachine::RUNNING_STATE_NAME = "Running";
29 const std::string RunControlStateMachine::SHUTDOWN_STATE_NAME = "Shutdown";
30 const std::string RunControlStateMachine::CONFIGURED_STATE_NAME = "Configured";
31 
32 const std::string RunControlStateMachine::SHUTDOWN_TRANSITION_NAME = "Shutdown";
33 const std::string RunControlStateMachine::STARTUP_TRANSITION_NAME = "Startup";
34 const std::string RunControlStateMachine::INIT_TRANSITION_NAME = "Initialize";
35 const std::string RunControlStateMachine::ERROR_TRANSITION_NAME = FiniteStateMachine::ERROR_TRANSITION_NAME;
36 const std::string RunControlStateMachine::FAIL_TRANSITION_NAME = "Fail";
37 const std::string RunControlStateMachine::CONFIGURE_TRANSITION_NAME = "Configure";
38 const std::string RunControlStateMachine::HALT_TRANSITION_NAME = "Halt";
39 const std::string RunControlStateMachine::ABORT_TRANSITION_NAME = "Abort";
40 const std::string RunControlStateMachine::PAUSE_TRANSITION_NAME = "Pause";
41 const std::string RunControlStateMachine::RESUME_TRANSITION_NAME = "Resume";
42 const std::string RunControlStateMachine::START_TRANSITION_NAME = "Start";
43 const std::string RunControlStateMachine::STOP_TRANSITION_NAME = "Stop";
44 
45 // clang-format on
46 
47 //==============================================================================
48 RunControlStateMachine::RunControlStateMachine(const std::string& name)
49  : theStateMachine_(name)
50  , asyncFailureReceived_(false)
51  , asyncPauseExceptionReceived_(false)
52  , asyncStopExceptionReceived_(false)
53 {
54  INIT_MF("." /*directory used is USER_DATA/LOG/.*/);
55 
56  theStateMachine_.addState('I',
57  RunControlStateMachine::INITIAL_STATE_NAME,
58  this,
59  &RunControlStateMachine::stateInitial);
60  theStateMachine_.addState('H',
61  RunControlStateMachine::HALTED_STATE_NAME,
62  this,
63  &RunControlStateMachine::stateHalted);
64  theStateMachine_.addState('C',
65  RunControlStateMachine::CONFIGURED_STATE_NAME,
66  this,
67  &RunControlStateMachine::stateConfigured);
68  theStateMachine_.addState('R',
69  RunControlStateMachine::RUNNING_STATE_NAME,
70  this,
71  &RunControlStateMachine::stateRunning);
72  theStateMachine_.addState('P',
73  RunControlStateMachine::PAUSED_STATE_NAME,
74  this,
75  &RunControlStateMachine::statePaused);
76  theStateMachine_.addState('X',
77  RunControlStateMachine::SHUTDOWN_STATE_NAME,
78  this,
79  &RunControlStateMachine::stateShutdown);
80  // theStateMachine_.addState('v', "Recovering", this,
81  // &RunControlStateMachine::stateRecovering); theStateMachine_.addState('T',
82  // "TTSTestMode", this, &RunControlStateMachine::stateTTSTestMode);
83 
84  // RAR added back in on 11/20/2016.. why was it removed..
85  // exceptions like..
86  // XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());)
87  // take state machine to "failed" otherwise
88  theStateMachine_.setStateName(FiniteStateMachine::FAILED_STATE,
89  RunControlStateMachine::FAILED_STATE_NAME);
90  theStateMachine_.setFailedStateTransitionAction(
91  this, &RunControlStateMachine::enteringError);
92  theStateMachine_.setFailedStateTransitionChanged(this,
93  &RunControlStateMachine::inError);
94 
95  //clang-format off
96  // this line was added to get out of Failed state
97  RunControlStateMachine::addStateTransition(
98  FiniteStateMachine::FAILED_STATE,
99  'H',
100  RunControlStateMachine::HALT_TRANSITION_NAME,
101  "Halting",
102  this,
103  &RunControlStateMachine::transitionHalting);
104  RunControlStateMachine::addStateTransition(
105  FiniteStateMachine::FAILED_STATE,
106  'X',
107  RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
108  "Shutting Down",
109  this,
110  &RunControlStateMachine::transitionShuttingDown);
111  RunControlStateMachine::addStateTransition(
112  FiniteStateMachine::FAILED_STATE,
113  FiniteStateMachine::FAILED_STATE,
114  RunControlStateMachine::ERROR_TRANSITION_NAME,
115  "Erroring",
116  this,
117  &RunControlStateMachine::enteringError);
118  RunControlStateMachine::addStateTransition(
119  FiniteStateMachine::FAILED_STATE,
120  FiniteStateMachine::FAILED_STATE,
121  RunControlStateMachine::FAIL_TRANSITION_NAME,
122  "Failing",
123  this,
124  &RunControlStateMachine::transitionShuttingDown);
125 
126  RunControlStateMachine::addStateTransition(
127  'H',
128  'C',
129  RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
130  "Configuring",
131  "ConfigurationAlias",
132  this,
133  &RunControlStateMachine::transitionConfiguring);
134  RunControlStateMachine::addStateTransition(
135  'H',
136  'X',
137  RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
138  "Shutting Down",
139  this,
140  &RunControlStateMachine::transitionShuttingDown);
141  RunControlStateMachine::addStateTransition(
142  'X',
143  'I',
144  RunControlStateMachine::STARTUP_TRANSITION_NAME,
145  "Starting Up",
146  this,
147  &RunControlStateMachine::transitionStartingUp);
148 
149  // Every state can transition to halted
150  RunControlStateMachine::addStateTransition(
151  'I',
152  'H',
153  RunControlStateMachine::INIT_TRANSITION_NAME,
154  "Initializing",
155  this,
156  &RunControlStateMachine::transitionInitializing);
157  RunControlStateMachine::addStateTransition(
158  'H',
159  'H',
160  RunControlStateMachine::HALT_TRANSITION_NAME,
161  "Halting",
162  this,
163  &RunControlStateMachine::transitionHalting);
164  RunControlStateMachine::addStateTransition(
165  'C',
166  'H',
167  RunControlStateMachine::HALT_TRANSITION_NAME,
168  "Halting",
169  this,
170  &RunControlStateMachine::transitionHalting);
171  RunControlStateMachine::addStateTransition(
172  'R',
173  'H',
174  RunControlStateMachine::ABORT_TRANSITION_NAME,
175  "Aborting",
176  this,
177  &RunControlStateMachine::transitionHalting);
178  RunControlStateMachine::addStateTransition(
179  'P',
180  'H',
181  RunControlStateMachine::ABORT_TRANSITION_NAME,
182  "Aborting",
183  this,
184  &RunControlStateMachine::transitionHalting);
185 
186  RunControlStateMachine::addStateTransition(
187  'R',
188  'P',
189  RunControlStateMachine::PAUSE_TRANSITION_NAME,
190  "Pausing",
191  this,
192  &RunControlStateMachine::transitionPausing);
193  RunControlStateMachine::addStateTransition(
194  'P',
195  'R',
196  RunControlStateMachine::RESUME_TRANSITION_NAME,
197  "Resuming",
198  this,
199  &RunControlStateMachine::transitionResuming);
200  RunControlStateMachine::addStateTransition(
201  'C',
202  'R',
203  RunControlStateMachine::START_TRANSITION_NAME,
204  "Starting",
205  this,
206  &RunControlStateMachine::transitionStarting);
207  RunControlStateMachine::addStateTransition(
208  'R',
209  'C',
210  RunControlStateMachine::STOP_TRANSITION_NAME,
211  "Stopping",
212  this,
213  &RunControlStateMachine::transitionStopping);
214  RunControlStateMachine::addStateTransition(
215  'P',
216  'C',
217  RunControlStateMachine::STOP_TRANSITION_NAME,
218  "Stopping",
219  this,
220  &RunControlStateMachine::transitionStopping);
221  //clang-format on
222 
223  // NOTE!! There must be a defined message handler for each transition name created
224  // above
225  xoap::bind(this,
226  &RunControlStateMachine::runControlMessageHandler,
227  RunControlStateMachine::INIT_TRANSITION_NAME,
228  XDAQ_NS_URI);
229  xoap::bind(this,
230  &RunControlStateMachine::runControlMessageHandler,
231  RunControlStateMachine::CONFIGURE_TRANSITION_NAME,
232  XDAQ_NS_URI);
233  xoap::bind(this,
234  &RunControlStateMachine::runControlMessageHandler,
235  RunControlStateMachine::START_TRANSITION_NAME,
236  XDAQ_NS_URI);
237  xoap::bind(this,
238  &RunControlStateMachine::runControlMessageHandler,
239  RunControlStateMachine::STOP_TRANSITION_NAME,
240  XDAQ_NS_URI);
241  xoap::bind(this,
242  &RunControlStateMachine::runControlMessageHandler,
243  RunControlStateMachine::PAUSE_TRANSITION_NAME,
244  XDAQ_NS_URI);
245  xoap::bind(this,
246  &RunControlStateMachine::runControlMessageHandler,
247  RunControlStateMachine::RESUME_TRANSITION_NAME,
248  XDAQ_NS_URI);
249  xoap::bind(this,
250  &RunControlStateMachine::runControlMessageHandler,
251  RunControlStateMachine::HALT_TRANSITION_NAME,
252  XDAQ_NS_URI);
253  xoap::bind(this,
254  &RunControlStateMachine::runControlMessageHandler,
255  RunControlStateMachine::ABORT_TRANSITION_NAME,
256  XDAQ_NS_URI);
257  xoap::bind(this,
258  &RunControlStateMachine::runControlMessageHandler,
259  RunControlStateMachine::SHUTDOWN_TRANSITION_NAME,
260  XDAQ_NS_URI);
261  xoap::bind(this,
262  &RunControlStateMachine::runControlMessageHandler,
263  RunControlStateMachine::STARTUP_TRANSITION_NAME,
264  XDAQ_NS_URI);
265  xoap::bind(this,
266  &RunControlStateMachine::runControlMessageHandler,
267  RunControlStateMachine::FAIL_TRANSITION_NAME,
268  XDAQ_NS_URI);
269  xoap::bind(this,
270  &RunControlStateMachine::runControlMessageHandler,
271  RunControlStateMachine::ERROR_TRANSITION_NAME,
272  XDAQ_NS_URI);
273 
274  xoap::bind(this,
275  &RunControlStateMachine::runControlMessageHandler,
276  "AsyncError",
277  XDAQ_NS_URI);
278  xoap::bind(this,
279  &RunControlStateMachine::runControlMessageHandler,
280  "AsyncPauseException",
281  XDAQ_NS_URI);
282 
283  reset();
284 }
285 
286 //==============================================================================
287 RunControlStateMachine::~RunControlStateMachine(void) {}
288 
289 //==============================================================================
290 void RunControlStateMachine::reset(void)
291 {
292  __GEN_COUT__ << "Resetting RunControlStateMachine with name '"
293  << theStateMachine_.getStateMachineName() << "'..." << __E__;
294  theStateMachine_.setInitialState('I');
295  theStateMachine_.reset();
296 
297  theStateMachine_.setErrorMessage("", false /*append*/); // clear error message
298 
299  asyncFailureReceived_ = false;
300  asyncPauseExceptionReceived_ = false;
301  asyncStopExceptionReceived_ = false;
302 } // end reset()
303 
308 //{
309 // auto itFrom = stateTransitionFunctionTable_.find(from);
310 // if(itFrom == stateTransitionFunctionTable_.end())
311 // {
312 // __GEN_SS__ << "Cannot find transition function from '" << from <<
313 // "' with transition '" << transition << "!'" << __E__;
314 // XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
315 // }
316 //
317 // auto itTrans = itFrom->second.find(transition);
318 // if(itTrans == itFrom->second.end())
319 // {
320 // __GEN_SS__ << "Cannot find transition function from '" << from <<
321 // "' with transition '" << transition << "!'" << __E__;
322 // XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
323 // }
324 //
325 // return itTrans->second;
326 //}
327 
328 //==============================================================================
334  xoap::MessageReference message)
335 {
336  __GEN_COUT__ << "Received... \t" << SOAPUtilities::translate(message) << std::endl;
337 
338  std::string command = SOAPUtilities::translate(message).getCommand();
339 
340  // get iteration index
341  try
342  {
344  SOAPUtilities::translate(message).getParameters().getValue("iterationIndex"),
345  iterationIndex_);
346  }
347  catch(...) // ignore errors and set iteration index to 0
348  {
349  __GEN_COUT__ << "Defaulting iteration index to 0." << __E__;
350  iterationIndex_ = 0;
351  }
352  // get subIteration index
353  try
354  {
356  SOAPUtilities::translate(message).getParameters().getValue(
357  "subIterationIndex"),
358  subIterationIndex_);
359  }
360  catch(...) // ignore errors and set subIteration index to 0
361  {
362  __GEN_COUT__ << "Defaulting subIterationIndex_ index to 0." << __E__;
363  subIterationIndex_ = 0;
364  }
365 
366  // get retransmission indicator
367  bool retransmittedCommand = false;
368  try
369  {
370  retransmittedCommand =
371  (SOAPUtilities::translate(message).getParameters().getValue(
372  "retransmission") == "1");
373  }
374  catch(
375  ...) // ignore errors for retransmission indicator (assume it is not a retransmission)
376  {
377  ;
378  }
379 
380  if(retransmittedCommand)
381  {
382  // handle retransmission
383 
384  // attempt to stop an error if last command was same
385  if(lastIterationCommand_ == command && lastIterationIndex_ == iterationIndex_ &&
386  lastSubIterationIndex_ == subIterationIndex_)
387  {
388  __GEN_COUT__
389  << "Assuming a timeout occurred at Gateway waiting for a response. "
390  << "Attempting to avoid error, by giving last result for command '"
391  << command << "': " << lastIterationResult_ << __E__;
392  try
393  {
394  return SOAPUtilities::makeSOAPMessageReference(lastIterationResult_);
395  }
396  catch(const std::exception&
397  e) // if an illegal result ever propagates here, it is bug!
398  {
399  __GEN_COUT__ << "There was an illegal result propagation: "
400  << lastIterationResult_
401  << ". Here was the error: " << e.what() << __E__;
402  throw;
403  }
404  }
405  else
406  __GEN_COUT__ << "Looks like Gateway command '" << command
407  << "' was lost - attempting to handle retransmission." << __E__;
408  }
409 
410  lastIterationIndex_ = iterationIndex_;
411  lastSubIterationIndex_ = subIterationIndex_;
412 
413  std::string currentState;
414  if(iterationIndex_ == 0 && subIterationIndex_ == 0)
415  {
416  // this is the first iteration attempt for this transition
417  theProgressBar_.reset(command, theStateMachine_.getStateMachineName());
418  currentState = theStateMachine_.getCurrentStateName();
419  __GEN_COUT__ << "Starting state for " << theStateMachine_.getStateMachineName()
420  << " is " << currentState << " and attempting to " << command
421  << std::endl;
422  }
423  else
424  {
425  currentState = theStateMachine_.getStateName(lastIterationState_);
426 
427  __GEN_COUT__ << "Iteration index " << iterationIndex_ << "." << subIterationIndex_
428  << " for " << theStateMachine_.getStateMachineName() << " from "
429  << currentState << " attempting to " << command << std::endl;
430  }
431 
432  RunControlStateMachine::theProgressBar_.step();
433 
434  std::string result = command + "Done";
435  lastIterationResult_ = result;
436 
437  // if error is received, immediately go to fail state
438  // likely error was sent by central FSM or external xoap
439  if(command == "Error" || command == "Fail")
440  {
441  __GEN_SS__ << command << " was received! Halting immediately." << std::endl;
442  __GEN_COUT_ERR__ << "\n" << ss.str();
443 
444  try
445  {
446  if(currentState == "Configured")
447  theStateMachine_.execTransition(
448  RunControlStateMachine::HALT_TRANSITION_NAME, message);
449  else if(currentState == "Running" || currentState == "Paused")
450  theStateMachine_.execTransition(
451  RunControlStateMachine::ABORT_TRANSITION_NAME, message);
452  }
453  catch(...)
454  {
455  __GEN_COUT_ERR__ << "Halting failed in reaction to " << command
456  << "... ignoring." << __E__;
457  }
458  return SOAPUtilities::makeSOAPMessageReference(result);
459  }
460  else if(command == "AsyncError")
461  {
462  std::string errorMessage =
463  SOAPUtilities::translate(message).getParameters().getValue("ErrorMessage");
464 
465  __GEN_SS__ << command << " was received! Error'ing immediately: " << errorMessage
466  << std::endl;
467  __GEN_COUT_ERR__ << "\n" << ss.str();
468  theStateMachine_.setErrorMessage(ss.str());
469 
470  asyncFailureReceived_ = true; // mark flag, to be used to abort next transition
471  // determine any valid transition from where we are
472  theStateMachine_.execTransition("fail");
473  // XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
474 
475  return SOAPUtilities::makeSOAPMessageReference(result);
476  }
477  else if(command == "AsyncPauseException")
478  {
479  std::string errorMessage =
480  SOAPUtilities::translate(message).getParameters().getValue("ErrorMessage");
481 
482  __GEN_SS__ << command << " was received! Pause'ing immediately: " << errorMessage
483  << std::endl;
484  __GEN_COUT_ERR__ << "\n" << ss.str();
485  theStateMachine_.setErrorMessage(ss.str());
486 
487  if(!asyncPauseExceptionReceived_) // launch pause only first time
488  {
489  asyncPauseExceptionReceived_ = true; // mark flag, to be used to avoid double
490  // pausing and identify pause was due to
491  // soft error
492  theStateMachine_.execTransition("Pause");
493  }
494 
495  return SOAPUtilities::makeSOAPMessageReference(result);
496  }
497  else if(command == "AsyncStopException")
498  {
499  std::string errorMessage =
500  SOAPUtilities::translate(message).getParameters().getValue("ErrorMessage");
501 
502  __GEN_SS__ << command << " was received! Stop'ing immediately: " << errorMessage
503  << std::endl;
504  __GEN_COUT_ERR__ << "\n" << ss.str();
505  theStateMachine_.setErrorMessage(ss.str());
506 
507  if(!asyncStopExceptionReceived_) // launch stop only first time
508  {
509  asyncStopExceptionReceived_ = true; // mark flag, to be used to avoid double
510  // pausing and identify pause was due to
511  // soft error
512  theStateMachine_.execTransition("Stop");
513  }
514 
515  return SOAPUtilities::makeSOAPMessageReference(result);
516  }
517 
518  // if already Halted, respond to Initialize with "done"
519  // (this avoids race conditions involved with artdaq mpi reset)
520  if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
521  currentState == RunControlStateMachine::HALTED_STATE_NAME)
522  {
523  __GEN_COUT__ << "Already Initialized.. ignoring Initialize command." << std::endl;
524 
525  theStateMachine_.setErrorMessage("", false /*append*/); // clear error message
526  return SOAPUtilities::makeSOAPMessageReference(result);
527  }
528 
529  if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
530  currentState == RunControlStateMachine::FAILED_STATE_NAME)
531  {
532  __GEN_COUT__ << "Converting Initialize command to Halt, since currently in "
533  << currentState << " state." << std::endl;
534  command = RunControlStateMachine::HALT_TRANSITION_NAME;
535  message = SOAPUtilities::makeSOAPMessageReference(command);
536  }
537 
538  if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
539  currentState == RunControlStateMachine::FAILED_STATE_NAME)
540  {
541  __GEN_COUT__ << "Clearing Errors after failure..." << std::endl;
542  theStateMachine_.setErrorMessage("", false /*append*/); // clear error message
543  asyncFailureReceived_ = false;
544  }
545 
546  __GEN_COUTV__(command);
547  __GEN_COUTV__(currentState);
548  __GEN_COUTV__(asyncFailureReceived_);
549  __GEN_COUTV__(asyncPauseExceptionReceived_);
550  __GEN_COUTV__(asyncStopExceptionReceived_);
551  __GEN_COUTV__(getErrorMessage());
552  __GEN_COUTV__(retransmittedCommand);
553 
554  // handle normal transitions here
555  try
556  {
557  // Clear error message if starting a normal transition.
558  // Do not clear soft PAUSE or harder STOP exception
559  // Do not clear if retransmission transition from Failed (likely an error just occured that we do not want to lose!)
560  if(!((asyncPauseExceptionReceived_ &&
561  command == RunControlStateMachine::PAUSE_TRANSITION_NAME) ||
562  (asyncStopExceptionReceived_ &&
563  command == RunControlStateMachine::STOP_TRANSITION_NAME)))
564  theStateMachine_.setErrorMessage("",
565  false /*append*/); // clear error message
566 
567  if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
568  currentState == RunControlStateMachine::INITIAL_STATE_NAME)
569  {
570  command = RunControlStateMachine::INIT_TRANSITION_NAME;
571  __GEN_COUT__ << "Converting Halt command to " << command
572  << ", since currently in " << currentState << " state."
573  << std::endl;
574  message = SOAPUtilities::makeSOAPMessageReference(command);
575  }
576  if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
577  (currentState == RunControlStateMachine::PAUSED_STATE_NAME ||
578  currentState == RunControlStateMachine::RUNNING_STATE_NAME))
579  {
580  command = RunControlStateMachine::ABORT_TRANSITION_NAME;
581  __GEN_COUT__ << "Converting Halt command to " << command
582  << ", since currently in " << currentState << " state."
583  << std::endl;
584  message = SOAPUtilities::makeSOAPMessageReference(command);
585  }
586  if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME &&
587  currentState == RunControlStateMachine::INITIAL_STATE_NAME)
588  {
589  __GEN_COUT__
590  << "Pre-empting Configure command with Initialize, since currently in "
591  << currentState << " state." << std::endl;
592  std::string precommand = RunControlStateMachine::INIT_TRANSITION_NAME;
593  xoap::MessageReference premessage =
594  SOAPUtilities::makeSOAPMessageReference(precommand);
595  theStateMachine_.execTransition(precommand, premessage);
596  __GEN_COUT__ << "Now proceeding with Configure command" << __E__;
597  }
598 
599  iterationWorkFlag_ = false;
600  subIterationWorkFlag_ = false;
601  if(iterationIndex_ || subIterationIndex_)
602  {
603  __GEN_COUT__ << command << " iteration " << iterationIndex_ << "."
604  << subIterationIndex_ << __E__;
605  toolbox::Event::Reference event(new toolbox::Event(command, this));
606 
607  // call inheriting transition function based on last state and command
608  {
609  // e.g. transitionConfiguring(event);
610  __GEN_COUT__ << "Iterating on the transition function from "
611  << currentState << " through " << lastIterationCommand_
612  << __E__;
613 
614  auto itFrom = stateTransitionFunctionTable_.find(lastIterationState_);
615  if(itFrom == stateTransitionFunctionTable_.end())
616  {
617  __GEN_SS__ << "Cannot find transition function from '" << currentState
618  << "' with transition '" << lastIterationCommand_ << "!'"
619  << __E__;
620  __GEN_COUT_ERR__ << ss.str();
621  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
622  }
623 
624  auto itTransition = itFrom->second.find(lastIterationCommand_);
625  if(itTransition == itFrom->second.end())
626  {
627  __GEN_SS__ << "Cannot find transition function from '" << currentState
628  << "' with transition '" << lastIterationCommand_ << "!'"
629  << __E__;
630  __GEN_COUT_ERR__ << ss.str();
631  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
632  }
633 
634  (this->*(itTransition->second))(event); // call the transition function
635  }
636  }
637  else
638  {
639  // save the lookup parameters for the last function to be called for the case
640  // of additional iterations
641  lastIterationState_ = theStateMachine_.getCurrentState();
642  lastIterationCommand_ = command;
643  if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME)
644  {
645  lastAttemptedConfigureGroup_ =
646  SOAPUtilities::translate(message).getParameters().getValue(
647  "ConfigurationAlias");
648 
649  //all entities but Gateway will have alias group name and key translation:
650  try
651  {
652  lastAttemptedConfigureGroup_ +=
653  " " +
654  SOAPUtilities::translate(message).getParameters().getValue(
655  "ConfigurationTableGroupName") +
656  "(" +
657  SOAPUtilities::translate(message).getParameters().getValue(
658  "ConfigurationTableGroupKey") +
659  ")";
660  }
661  catch(...)
662  { /* ignore missing parameters */
663  }
664  }
665 
666  theStateMachine_.execTransition(command, message);
667  }
668 
669  if(subIterationWorkFlag_) // sub-iteration has priority over 'Working'
670  {
671  __GEN_COUTV__(subIterationWorkFlag_);
672  result =
673  command + "SubIterate"; // indicate another sub-iteration back to Gateway
674  }
675  else if(iterationWorkFlag_)
676  {
677  __GEN_COUTV__(iterationWorkFlag_);
678  result = command + "Iterate"; // indicate another iteration back to Gateway
679  }
680  }
681  catch(const std::runtime_error& e)
682  {
683  __GEN_SS__ << "Run Control Message Handling Failed with command '" << command
684  << "': " << e.what() << " " << theStateMachine_.getErrorMessage()
685  << __E__;
686  __GEN_COUT_ERR__ << ss.str();
687  theStateMachine_.setErrorMessage(ss.str());
688 
689  result = command + RunControlStateMachine::FAILED_STATE_NAME;
690  }
691  catch(toolbox::fsm::exception::Exception& e)
692  {
693  __GEN_SS__ << "Run Control Message Handling Failed with command '" << command
694  << "': " << e.what() << " " << theStateMachine_.getErrorMessage()
695  << __E__;
696  __GEN_COUT_ERR__ << ss.str();
697  theStateMachine_.setErrorMessage(ss.str());
698 
699  result = command + RunControlStateMachine::FAILED_STATE_NAME;
700  }
701  catch(...)
702  {
703  __GEN_SS__ << "Run Control Message Handling Failed with command '" << command
704  << "' and encountered an unknown error."
705  << theStateMachine_.getErrorMessage() << __E__;
706  try
707  {
708  throw;
709  } //one more try to printout extra info
710  catch(const std::exception& e)
711  {
712  ss << "Exception message: " << e.what();
713  }
714  catch(...)
715  {
716  }
717  __GEN_COUT_ERR__ << ss.str();
718  theStateMachine_.setErrorMessage(ss.str());
719 
720  result = command + RunControlStateMachine::FAILED_STATE_NAME;
721  }
722 
723  RunControlStateMachine::theProgressBar_.step();
724 
725  currentState = theStateMachine_.getCurrentStateName();
726 
727  if(currentState == RunControlStateMachine::FAILED_STATE_NAME)
728  {
729  result = command + RunControlStateMachine::FAILED_STATE_NAME;
730  __GEN_COUT_ERR__ << "Unexpected Failure state for "
731  << theStateMachine_.getStateMachineName() << " is "
732  << currentState << std::endl;
733  __GEN_COUT_ERR__ << "Error message was as follows: "
734  << theStateMachine_.getErrorMessage() << std::endl;
735  }
736 
737  RunControlStateMachine::theProgressBar_.step();
738 
739  if(!iterationWorkFlag_ && !subIterationWorkFlag_)
740  theProgressBar_.complete();
741  else
742  {
743  __GEN_COUTV__(theProgressBar_.read());
744  __GEN_COUTV__(theProgressBar_.isComplete());
745  }
746 
747  __GEN_COUT__ << "Ending state for " << theStateMachine_.getStateMachineName()
748  << " is " << currentState << std::endl;
749  __GEN_COUT__ << "result = " << result << std::endl;
750  lastIterationResult_ = result;
751  return SOAPUtilities::makeSOAPMessageReference(result);
752 } // end runControlMessageHandler()
bool isComplete()
get functions
Definition: ProgressBar.cc:89
void reset(std::string file, std::string lineNumber, int id=0)
will call this reset:
Definition: ProgressBar.cc:41
int read()
if stepsToComplete==0, then define any progress as 50%, thread safe
Definition: ProgressBar.cc:121
void complete()
declare complete, thread safe
Definition: ProgressBar.cc:96
xoap::MessageReference runControlMessageHandler(xoap::MessageReference message)
Run Control Messages.
void INIT_MF(const char *name)
static bool getNumber(const std::string &s, T &retValue)