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