otsdaq  3.09.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 retransmission indicator
366  bool retransmittedCommand = false;
367  try
368  {
369  retransmittedCommand =
370  (SOAPUtilities::translate(message).getParameters().getValue(
371  "retransmission") == "1");
372  }
373  catch(
374  ...) // ignore errors for retransmission indicator (assume it is not a retransmission)
375  {
376  ;
377  }
378 
379  if(retransmittedCommand)
380  {
381  // handle retransmission
382  __GEN_COUT__ << "retransmission identified..." << __E__;
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_COUTS__(2) << "Iteration index " << iterationIndex_ << "."
428  << subIterationIndex_ << " for "
429  << theStateMachine_.getStateMachineName() << " from "
430  << currentState << " attempting to " << command << std::endl;
431  }
432 
433  RunControlStateMachine::theProgressBar_.step();
434 
435  std::string result = command + "Done";
436  lastIterationResult_ = result;
437 
438  // if error is received, immediately go to fail state
439  // likely error was sent by central FSM or external xoap
440  if(command == "Error" || command == "Fail")
441  {
442  __GEN_SS__ << command << " was received! Halting immediately." << std::endl;
443  __GEN_COUT_ERR__ << "\n" << ss.str();
444 
445  try
446  {
447  if(currentState == "Configured")
448  theStateMachine_.execTransition(
449  RunControlStateMachine::HALT_TRANSITION_NAME, message);
450  else if(currentState == "Running" || currentState == "Paused")
451  theStateMachine_.execTransition(
452  RunControlStateMachine::ABORT_TRANSITION_NAME, message);
453  }
454  catch(...)
455  {
456  __GEN_COUT_ERR__ << "Halting failed in reaction to " << command
457  << "... ignoring." << __E__;
458  }
459  theProgressBar_.complete();
460  return SOAPUtilities::makeSOAPMessageReference(result);
461  }
462  else if(command == "AsyncError")
463  {
464  std::string errorMessage =
465  SOAPUtilities::translate(message).getParameters().getValue("ErrorMessage");
466 
467  __GEN_SS__ << command << " was received! Error'ing immediately: " << errorMessage
468  << std::endl;
469  __GEN_COUT_ERR__ << "\n" << ss.str();
470  theStateMachine_.setErrorMessage(ss.str());
471 
472  if(!asyncFailureReceived_.exchange(true))
473  {
474  // Thread safety: execTransition("fail") spins on inTransition_ and
475  // checks for already-FAILED. No use-after-free: XDAQ supervisors
476  // live for the process lifetime. stateMachineAccessMutex_ is
477  // GatewaySupervisor-specific and not available here.
478  std::thread([this]() {
479  try
480  {
481  theStateMachine_.execTransition("fail");
482  }
483  catch(...)
484  {
485  __GEN_COUT_ERR__ << "AsyncError: execTransition(fail) threw" << __E__;
486  }
487  }).detach();
488  }
489 
490  return SOAPUtilities::makeSOAPMessageReference(result);
491  }
492  else if(command == "AsyncPauseException")
493  {
494  std::string errorMessage =
495  SOAPUtilities::translate(message).getParameters().getValue("ErrorMessage");
496 
497  __GEN_SS__ << command << " was received! Pause'ing immediately: " << errorMessage
498  << std::endl;
499  __GEN_COUT_ERR__ << "\n" << ss.str();
500  theStateMachine_.setErrorMessage(ss.str());
501 
502  if(!asyncPauseExceptionReceived_.exchange(true))
503  {
504  // Thread safety: inTransition_ rejects concurrent transitions.
505  // No use-after-free: XDAQ supervisors live for the process lifetime.
506  std::thread([this]() {
507  try
508  {
509  theStateMachine_.execTransition("Pause");
510  }
511  catch(...)
512  {
513  __GEN_COUT_ERR__ << "AsyncPauseException: execTransition(Pause) threw"
514  << __E__;
515  }
516  }).detach();
517  }
518 
519  return SOAPUtilities::makeSOAPMessageReference(result);
520  }
521  else if(command == "AsyncStopException")
522  {
523  std::string errorMessage =
524  SOAPUtilities::translate(message).getParameters().getValue("ErrorMessage");
525 
526  __GEN_SS__ << command << " was received! Stop'ing immediately: " << errorMessage
527  << std::endl;
528  __GEN_COUT_ERR__ << "\n" << ss.str();
529  theStateMachine_.setErrorMessage(ss.str());
530 
531  if(!asyncStopExceptionReceived_.exchange(true))
532  {
533  // Thread safety: inTransition_ rejects concurrent transitions.
534  // No use-after-free: XDAQ supervisors live for the process lifetime.
535  std::thread([this]() {
536  try
537  {
538  theStateMachine_.execTransition("Stop");
539  }
540  catch(...)
541  {
542  __GEN_COUT_ERR__ << "AsyncStopException: execTransition(Stop) threw"
543  << __E__;
544  }
545  }).detach();
546  }
547 
548  return SOAPUtilities::makeSOAPMessageReference(result);
549  }
550 
551  // if already Halted, respond to Initialize with "done"
552  // (this avoids race conditions involved with artdaq mpi reset)
553  if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
554  currentState == RunControlStateMachine::HALTED_STATE_NAME)
555  {
556  __GEN_COUT__ << "Already Initialized.. ignoring Initialize command." << std::endl;
557 
558  theStateMachine_.setErrorMessage("", false /*append*/); // clear error message
559  return SOAPUtilities::makeSOAPMessageReference(result);
560  }
561 
562  if(command == RunControlStateMachine::INIT_TRANSITION_NAME &&
563  currentState == RunControlStateMachine::FAILED_STATE_NAME)
564  {
565  __GEN_COUT__ << "Converting Initialize command to Halt, since currently in "
566  << currentState << " state." << std::endl;
567  command = RunControlStateMachine::HALT_TRANSITION_NAME;
568  message = SOAPUtilities::makeSOAPMessageReference(command);
569  }
570 
571  if((command == RunControlStateMachine::HALT_TRANSITION_NAME ||
572  command == RunControlStateMachine::SHUTDOWN_TRANSITION_NAME) &&
573  currentState == RunControlStateMachine::FAILED_STATE_NAME)
574  {
575  __GEN_COUT__ << "Clearing Errors after failure..." << std::endl;
576  theStateMachine_.setErrorMessage("", false /*append*/); // clear error message
577  asyncFailureReceived_ = false;
578  asyncPauseExceptionReceived_ = false;
579  asyncStopExceptionReceived_ = false;
580  }
581 
582  if(command == RunControlStateMachine::RESUME_TRANSITION_NAME)
583  asyncPauseExceptionReceived_ = false;
584  if(command == RunControlStateMachine::START_TRANSITION_NAME)
585  asyncStopExceptionReceived_ = false;
586 
587  __GEN_COUTVS__(2, command);
588  __GEN_COUTVS__(2, currentState);
589  __GEN_COUTVS__(2, asyncFailureReceived_);
590  __GEN_COUTVS__(2, asyncPauseExceptionReceived_);
591  __GEN_COUTVS__(2, asyncStopExceptionReceived_);
592  __GEN_COUTVS__(2, getErrorMessage());
593  __GEN_COUTVS__(2, retransmittedCommand);
594 
595  // handle normal transitions here
596  try
597  {
598  // Clear error message if starting a normal transition.
599  // Do not clear soft PAUSE or harder STOP exception
600  // Do not clear if retransmission transition from Failed (likely an error just occured that we do not want to lose!)
601  if(!((asyncPauseExceptionReceived_ &&
602  command == RunControlStateMachine::PAUSE_TRANSITION_NAME) ||
603  (asyncStopExceptionReceived_ &&
604  command == RunControlStateMachine::STOP_TRANSITION_NAME)))
605  theStateMachine_.setErrorMessage("",
606  false /*append*/); // clear error message
607 
608  if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
609  currentState == RunControlStateMachine::INITIAL_STATE_NAME)
610  {
611  command = RunControlStateMachine::INIT_TRANSITION_NAME;
612  __GEN_COUT__ << "Converting Halt command to " << command
613  << ", since currently in " << currentState << " state."
614  << std::endl;
615  message = SOAPUtilities::makeSOAPMessageReference(command);
616  }
617  if(command == RunControlStateMachine::HALT_TRANSITION_NAME &&
618  (currentState == RunControlStateMachine::PAUSED_STATE_NAME ||
619  currentState == RunControlStateMachine::RUNNING_STATE_NAME))
620  {
621  command = RunControlStateMachine::ABORT_TRANSITION_NAME;
622  __GEN_COUT__ << "Converting Halt command to " << command
623  << ", since currently in " << currentState << " state."
624  << std::endl;
625  message = SOAPUtilities::makeSOAPMessageReference(command);
626  }
627  if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME &&
628  currentState == RunControlStateMachine::INITIAL_STATE_NAME)
629  {
630  __GEN_COUT__
631  << "Pre-empting Configure command with Initialize, since currently in "
632  << currentState << " state." << std::endl;
633  std::string precommand = RunControlStateMachine::INIT_TRANSITION_NAME;
634  xoap::MessageReference premessage =
635  SOAPUtilities::makeSOAPMessageReference(precommand);
636  theStateMachine_.execTransition(precommand, premessage);
637  __GEN_COUT__ << "Now proceeding with Configure command" << __E__;
638  }
639 
640  iterationWorkFlag_ = false;
641  subIterationWorkFlag_ = false;
642  if(iterationIndex_ || subIterationIndex_)
643  {
644  __GEN_COUTS__(2) << command << " iteration " << iterationIndex_ << "."
645  << subIterationIndex_ << __E__;
646  toolbox::Event::Reference event(new toolbox::Event(command, this));
647 
648  // call inheriting transition function based on last state and command
649  {
650  // e.g. transitionConfiguring(event);
651  __GEN_COUTS__(2)
652  << "Iterating on the transition function from " << currentState
653  << " through " << lastIterationCommand_ << __E__;
654 
655  auto itFrom = stateTransitionFunctionTable_.find(lastIterationState_);
656  if(itFrom == stateTransitionFunctionTable_.end())
657  {
658  __GEN_SS__ << "Cannot find transition function from '" << currentState
659  << "' with transition '" << lastIterationCommand_ << "!'"
660  << __E__;
661  __GEN_COUT_ERR__ << ss.str();
662  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
663  }
664 
665  auto itTransition = itFrom->second.find(lastIterationCommand_);
666  if(itTransition == itFrom->second.end())
667  {
668  __GEN_SS__ << "Cannot find transition function from '" << currentState
669  << "' with transition '" << lastIterationCommand_ << "!'"
670  << __E__;
671  __GEN_COUT_ERR__ << ss.str();
672  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
673  }
674 
675  (this->*(itTransition->second))(event); // call the transition function
676  }
677  }
678  else
679  {
680  // save the lookup parameters for the last function to be called for the case
681  // of additional iterations
682  lastIterationState_ = theStateMachine_.getCurrentState();
683  lastIterationCommand_ = command;
684  if(command == RunControlStateMachine::CONFIGURE_TRANSITION_NAME)
685  {
686  lastAttemptedConfigureGroup_ =
687  SOAPUtilities::translate(message).getParameters().getValue(
688  "ConfigurationAlias");
689 
690  //all entities but Gateway will have alias group name and key translation:
691  try
692  {
693  lastAttemptedConfigureGroup_ +=
694  " " +
695  SOAPUtilities::translate(message).getParameters().getValue(
696  "ConfigurationTableGroupName") +
697  "(" +
698  SOAPUtilities::translate(message).getParameters().getValue(
699  "ConfigurationTableGroupKey") +
700  ")";
701  }
702  catch(...)
703  { /* ignore missing parameters */
704  }
705  }
706 
707  theStateMachine_.execTransition(command, message);
708  }
709 
710  if(subIterationWorkFlag_) // sub-iteration has priority over 'Working'
711  {
712  __GEN_COUTV__(subIterationWorkFlag_);
713  result =
714  command + "SubIterate"; // indicate another sub-iteration back to Gateway
715  }
716  else if(iterationWorkFlag_)
717  {
718  __GEN_COUTVS__(2, iterationWorkFlag_);
719  result = command + "Iterate"; // indicate another iteration back to Gateway
720  }
721  }
722  catch(const std::runtime_error& e)
723  {
724  __GEN_SS__ << "Run Control Message Handling Failed with command '" << command
725  << "': " << e.what() << " " << theStateMachine_.getErrorMessage()
726  << __E__;
727  __GEN_COUT_ERR__ << ss.str();
728  theStateMachine_.setErrorMessage(ss.str());
729 
730  result = command + RunControlStateMachine::FAILED_STATE_NAME;
731  }
732  catch(toolbox::fsm::exception::Exception& e)
733  {
734  __GEN_SS__ << "Run Control Message Handling Failed with command '" << command
735  << "': " << e.what() << " " << theStateMachine_.getErrorMessage()
736  << __E__;
737  __GEN_COUT_ERR__ << ss.str();
738  theStateMachine_.setErrorMessage(ss.str());
739 
740  result = command + RunControlStateMachine::FAILED_STATE_NAME;
741  }
742  catch(...)
743  {
744  __GEN_SS__ << "Run Control Message Handling Failed with command '" << command
745  << "' and encountered an unknown error."
746  << theStateMachine_.getErrorMessage() << __E__;
747  try
748  {
749  throw;
750  } //one more try to printout extra info
751  catch(const std::exception& e)
752  {
753  ss << "Exception message: " << e.what();
754  }
755  catch(...)
756  {
757  }
758  __GEN_COUT_ERR__ << ss.str();
759  theStateMachine_.setErrorMessage(ss.str());
760 
761  result = command + RunControlStateMachine::FAILED_STATE_NAME;
762  }
763 
764  RunControlStateMachine::theProgressBar_.step();
765 
766  currentState = theStateMachine_.getCurrentStateName();
767 
768  if(currentState == RunControlStateMachine::FAILED_STATE_NAME)
769  {
770  result = command + RunControlStateMachine::FAILED_STATE_NAME;
771  __GEN_COUT_ERR__ << "Unexpected Failure state for "
772  << theStateMachine_.getStateMachineName() << " is "
773  << currentState << std::endl;
774  __GEN_COUT_ERR__ << "Error message was as follows: "
775  << theStateMachine_.getErrorMessage() << std::endl;
776  }
777 
778  RunControlStateMachine::theProgressBar_.step();
779 
780  if(!iterationWorkFlag_ && !subIterationWorkFlag_)
781  theProgressBar_.complete();
782  else
783  {
784  __GEN_COUTVS__(2, theProgressBar_.read());
785  __GEN_COUTVS__(2, theProgressBar_.isComplete());
786  }
787 
788  __GEN_COUTS__(2) << "Ending state for " << theStateMachine_.getStateMachineName()
789  << " is " << currentState << std::endl;
790  __GEN_COUTS__(2) << "result = " << result << std::endl;
791  lastIterationResult_ = result;
792  return SOAPUtilities::makeSOAPMessageReference(result);
793 } // 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)