otsdaq  v1_01_03
 All Classes Namespaces Functions
Supervisor.cc
1 #include "otsdaq-core/Supervisor/Supervisor.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
4 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
5 #include "otsdaq-core/CgiDataUtilities/CgiDataUtilities.h"
6 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
7 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
8 
9 #include "otsdaq-core/WorkLoopManager/WorkLoopManager.h"
10 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
11 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
12 #include "otsdaq-core/ConfigurationPluginDataFormats/XDAQContextConfiguration.h"
13 #include <cgicc/HTMLClasses.h>
14 #include <cgicc/HTTPCookie.h>
15 #include <cgicc/HTMLDoctype.h>
16 #include <cgicc/HTTPHeader.h>
17 #include <xgi/Utils.h>
18 
19 #include <xoap/Method.h>
20 #include <xdaq/NamespaceURI.h>
21 #include <toolbox/task/WorkLoopFactory.h>
22 #include <toolbox/fsm/FailedEvent.h>
23 
24 #include <fstream>
25 #include <thread> // std::this_thread::sleep_for
26 #include <chrono> // std::chrono::seconds
27 #include <sys/stat.h> //for mkdir
28 
29 using namespace ots;
30 
31 
32 #define ICON_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/iconList.dat"
33 #define RUN_NUMBER_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/RunNumber/"
34 #define RUN_NUMBER_FILE_NAME "NextRunNumber.txt"
35 #define FSM_LAST_GROUP_ALIAS_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/RunControlData/"
36 #define FSM_LAST_GROUP_ALIAS_FILE_START std::string("FSMLastGroupAlias-")
37 #define FSM_USERS_PREFERENCES_FILETYPE "pref"
38 
39 
40 #undef __MF_SUBJECT__
41 #define __MF_SUBJECT__ "OmniSuper"
42 
43 
44 XDAQ_INSTANTIATOR_IMPL(Supervisor)
45 
46 
47 //========================================================================================================================
48 Supervisor::Supervisor(xdaq::ApplicationStub * s) throw (xdaq::exception::Exception)
49 :xdaq::Application (s)
50 ,SOAPMessenger (this)
52 ,outputDir_ ("")
53 ,theConfigurationManager_ (new ConfigurationManager)
54 //,theConfigurationGroupKey_ (nullptr)
55 ,stateMachineWorkLoopManager_(toolbox::task::bind(this, &Supervisor::stateMachineThread,"StateMachine"))
56 ,stateMachineSemaphore_ (toolbox::BSem::FULL)
57 ,infoRequestWorkLoopManager_ (toolbox::task::bind(this, &Supervisor::infoRequestThread, "InfoRequest"))
58 ,infoRequestSemaphore_ (toolbox::BSem::FULL)
59 , activeStateMachineName_ ("")
60 ,counterTest_ (0)
61 {
62  INIT_MF("Supervisor");
63  __MOUT__ << std::endl;
64 
65  //attempt to make directory structure (just in case)
66  mkdir((FSM_LAST_GROUP_ALIAS_PATH).c_str(), 0755);
67  mkdir((RUN_NUMBER_PATH).c_str(), 0755);
68 
69  securityType_ = theWebUsers_.getSecurity();
70 
71  __MOUT__ << "Security: " << securityType_ << std::endl;
72 
73  xgi::bind(this, &Supervisor::Default, "Default");
74  xgi::bind(this, &Supervisor::loginRequest, "LoginRequest");
75  xgi::bind(this, &Supervisor::request, "Request");
76  xgi::bind(this, &Supervisor::stateMachineXgiHandler, "StateMachineXgiHandler");
77  xgi::bind(this, &Supervisor::infoRequestHandler, "InfoRequestHandler");
78  xgi::bind(this, &Supervisor::infoRequestResultHandler, "InfoRequestResultHandler");
79  xgi::bind(this, &Supervisor::tooltipRequest, "TooltipRequest");
80 
81  xoap::bind(this, &Supervisor::supervisorCookieCheck, "SupervisorCookieCheck", XDAQ_NS_URI);
82  xoap::bind(this, &Supervisor::supervisorGetActiveUsers, "SupervisorGetActiveUsers", XDAQ_NS_URI);
83  xoap::bind(this, &Supervisor::supervisorSystemMessage, "SupervisorSystemMessage", XDAQ_NS_URI);
84  xoap::bind(this, &Supervisor::supervisorGetUserInfo, "SupervisorGetUserInfo", XDAQ_NS_URI);
85  xoap::bind(this, &Supervisor::supervisorSystemLogbookEntry, "SupervisorSystemLogbookEntry", XDAQ_NS_URI);
86  xoap::bind(this, &Supervisor::supervisorLastConfigGroupRequest, "SupervisorLastConfigGroupRequest", XDAQ_NS_URI);
87 
88 
89  //old:
90  //I always load all configuration even the one that is not related to the particular FEW/FER,
91  //so I can load it once and is good for all applications I am scared about threads so I comment it out!
92  //theConfigurationManager_ = Singleton<ConfigurationManager>::getInstance();
93 
94  init();
95 
96  //Note: print out handled by StartOTS.sh now
97  //std::thread([](Supervisor *supervisorPtr){ Supervisor::URLDisplayThread(supervisorPtr); }, this).detach();
98 }
99 
100 //========================================================================================================================
101 // TODO: Lore needs to detect program quit through killall or ctrl+c so that Logbook entry is made when ots is halted
102 Supervisor::~Supervisor(void)
103 {
104  delete theConfigurationManager_;
105  makeSystemLogbookEntry("ots halted.");
106 }
107 
108 //========================================================================================================================
109 void Supervisor::init(void)
110 {
111  //This can be done in the constructor because when you start xdaq it loads the configuration that can't be changed while running!
112  theSupervisorDescriptorInfo_.init(getApplicationContext());
113  theSupervisorsInfo_.init(theSupervisorDescriptorInfo_);
114 
115  supervisorGuiHasBeenLoaded_ = false;
116 
117  const XDAQContextConfiguration* contextConfiguration = theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration);
118 
119  supervisorContextUID_ = contextConfiguration->getContextUID(
120  getApplicationContext()->getContextDescriptor()->getURL()
121  );
122  __MOUT__ << "Context UID:" << supervisorContextUID_ << std::endl;
123 
124  supervisorApplicationUID_ = contextConfiguration->getApplicationUID(
125  getApplicationContext()->getContextDescriptor()->getURL(),
126  getApplicationDescriptor()->getLocalId()
127  );
128 
129  __MOUT__ << "Application UID:" << supervisorApplicationUID_ << std::endl;
130 
131  ConfigurationTree configLinkNode = theConfigurationManager_->getSupervisorConfigurationNode(
132  supervisorContextUID_, supervisorApplicationUID_);
133  // getNode(
134  // "/XDAQContextConfiguration/" + supervisorContextUID_ +
135  // "/LinkToApplicationConfiguration/" + supervisorApplicationUID_ +
136  // "/LinkToSupervisorConfiguration");
137  std::string supervisorUID;
138  if(!configLinkNode.isDisconnected())
139  supervisorUID = configLinkNode.getValue();
140  else
141  supervisorUID = ViewColumnInfo::DATATYPE_LINK_DEFAULT;
142 
143  __MOUT__ << "Supervisor UID:" << supervisorUID << std::endl;
144 }
145 
146 //========================================================================================================================
147 void Supervisor::URLDisplayThread(Supervisor *supervisorPtr)
148 {
149  INIT_MF("Supervisor");
150  //_Exit(0); //Uncomment to stop print out
151  // child process
152  int i = 0;
153  for (; i < 5; ++i)
154  {
155  std::this_thread::sleep_for (std::chrono::seconds(2));
156  std:: cout << __COUT_HDR_FL__ << "\n*********************************************************************" << std::endl;
157  std:: cout << __COUT_HDR_FL__ << "\n\n"
158  << supervisorPtr->getApplicationContext()->getContextDescriptor()->getURL() //<<// ":" // getenv("SUPERVISOR_SERVER") << ":"
159  //<< this->getApplicationDescriptor()-> getenv("PORT") <<
160  << "/urn:xdaq-application:lid="
161  << supervisorPtr->getApplicationDescriptor()->getLocalId() << "/"
162  << "\n" << std::endl;
163  std:: cout << __COUT_HDR_FL__ << "\n*********************************************************************" << std::endl;
164  }
165 }
166 
167 //========================================================================================================================
168 //makeSystemLogbookEntry
169 // makes a logbook entry into the current active experiments logbook for a system event
170 // escape entryText to make it html/xml safe!!
172 void Supervisor::makeSystemLogbookEntry(std::string entryText)
173 {
174  __MOUT__ << "Making System Logbook Entry: " << entryText << std::endl;
175 
176  //make sure Logbook has been configured into xdaq context
177  if(!theSupervisorDescriptorInfo_.getLogbookDescriptor())
178  {
179  __MOUT__ << "Just kidding... Logbook Descriptor not found." << std:: endl;
180  return;
181  }
182 
183  //__MOUT__ << "before: " << entryText << std::endl;
184  { //input entryText
185  std::string replace[] =
186  {"\"", "'", "&", "<", ">", "\n", " "};
187  std::string with[] =
188  {"%22","%27", "%26", "%3C", "%3E", "%0A%0D", "%20%20"};
189 
190  int numOfKeys = 7;
191 
192  size_t f;
193  for(int i=0;i<numOfKeys;++i)
194  {
195  while((f=entryText.find(replace[i])) != std::string::npos)
196  {
197  entryText = entryText.substr(0,f) + with[i] + entryText.substr(f+replace[i].length());
198  //__MOUT__ << "found " << " " << entryText << std::endl;
199  }
200  }
201  }
202  //__MOUT__ << "after: " << entryText << std::endl;
203 
204  SOAPParameters parameters("EntryText",entryText);
205  //SOAPParametersV parameters(1);
206  //parameters[0].setName("EntryText"); parameters[0].setValue(entryText);
207 
208  xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(theSupervisorDescriptorInfo_.getLogbookDescriptor(), "MakeSystemLogbookEntry",parameters);
209 
210  SOAPParameters retParameters("Status");
211  //SOAPParametersV retParameters(1);
212  //retParameters[0].setName("Status");
213  receive(retMsg, retParameters);
214 
215  __MOUT__ << "Returned Status: " << retParameters.getValue("Status") << std::endl;//retParameters[0].getValue() << std::endl << std::endl;
216 
217 }
218 
219 //========================================================================================================================
220 void Supervisor::Default(xgi::Input* in, xgi::Output* out)
221 throw (xgi::exception::Exception)
222 {
223  //
224  if (!supervisorGuiHasBeenLoaded_ && (supervisorGuiHasBeenLoaded_ = true)) //make system logbook entry that ots has been started
225  makeSystemLogbookEntry("ots started.");
226 
227  *out <<
228  "<!DOCTYPE HTML><html lang='en'><head><title>ots</title>" <<
229  //show ots icon
230  // from http://www.favicon-generator.org/
231  "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
232  <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
233  <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
234  <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
235  <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
236  <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
237  <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
238  <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
239  <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
240  <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
241  <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
242  <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
243  <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
244  <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
245  <meta name='msapplication-TileColor' content='#ffffff'>\
246  <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
247  <meta name='theme-color' content='#ffffff'>" <<
248  //end show ots icon
249  "</head>" <<
250  "<frameset col='100%' row='100%'>" <<
251  "<frame src='/WebPath/html/Supervisor.html?urn=" <<
252  this->getApplicationDescriptor()->getLocalId() << "=securityType=" <<
253  securityType_ << "'></frameset></html>";
254 }
255 
256 
257 
258 //========================================================================================================================
259 void Supervisor::stateMachineXgiHandler(xgi::Input* in, xgi::Output* out)
260 throw (xgi::exception::Exception)
261 {
262  cgicc::Cgicc cgi(in);
263 
264  uint8_t userPermissions;
265  uint64_t uid;
266  std::string userWithLock;
267  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
268  if (!theWebUsers_.cookieCodeIsActiveForRequest(cookieCode, &userPermissions,
269  &uid, "0", 1, &userWithLock))
270  {
271  *out << cookieCode;
272  return;
273  }
274 
275  //**** start LOCK GATEWAY CODE ***//
276  std::string username = "";
277  username = theWebUsers_.getUsersUsername(uid);
278  if (userWithLock != "" && userWithLock != username)
279  {
280  *out << WebUsers::REQ_USER_LOCKOUT_RESPONSE;
281  __MOUT__ << "User " << username << " is locked out. " << userWithLock << " has lock." << std::endl;
282  return;
283  }
284  //**** end LOCK GATEWAY CODE ***//
285 
286  HttpXmlDocument xmldoc(cookieCode);
287  std::string command = CgiDataUtilities::getData(cgi, "StateMachine");
288  std::string fsmName = CgiDataUtilities::getData(cgi, "fsmName");
289  std::string fsmWindowName = CgiDataUtilities::getData(cgi, "fsmWindowName");
290  fsmWindowName = CgiDataUtilities::decodeURIComponent(fsmWindowName);
291  std::string currentState = theStateMachine_.getCurrentStateName();
292 
293  __MOUT__ << "fsmName = " << fsmName << std::endl;
294  __MOUT__ << "fsmWindowName = " << fsmWindowName << std::endl;
295  __MOUT__ << "activeStateMachineName_ = " << activeStateMachineName_ << std::endl;
296 
297  //Do not allow transition while in transition
298  if (theStateMachine_.isInTransition())
299  {
300  __SS__ << "Error - Can not accept request since State Machine is already in transition!" << std::endl;
301  __MOUT_ERR__ << "\n" << ss.str();
302 
303  xmldoc.addTextElementToData("state_tranisition_attempted", "0"); //indicate to GUI transition NOT attempted
304  xmldoc.addTextElementToData("state_tranisition_attempted_err",
305  ss.str()); //indicate to GUI transition NOT attempted
306  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
307  return;
308  }
309 
311  //Validate FSM name
312  // if fsm name != active fsm name
313  // only allow, if current state is halted or init
314  // take active fsm name when configured
315  // else, allow
316  if(activeStateMachineName_ != "" &&
317  activeStateMachineName_ != fsmName)
318  {
319  __MOUT__ << "currentState = " <<
320  currentState << std::endl;
321  if(currentState != "Halted" &&
322  currentState != "Initial")
323  {
324  //illegal for this FSM name to attempt transition
325 
326  __SS__ << "Error - Can not accept request since State Machine " <<
327  "with window name '" <<
328  activeStateMachineWindowName_ << "' (UID: " <<
329  activeStateMachineName_ << ") "
330  "is currently " <<
331  "in control of State Machine progress. ";
332  ss << "\n\nIn order for this State Machine with window name '" <<
333  fsmWindowName << "' (UID: " << fsmName << ") "
334  "to control progress, please transition to Halted using the active " <<
335  "State Machine '" << activeStateMachineWindowName_ << ".'" << std::endl;
336  __MOUT_ERR__ << "\n" << ss.str();
337 
338  xmldoc.addTextElementToData("state_tranisition_attempted", "0"); //indicate to GUI transition NOT attempted
339  xmldoc.addTextElementToData("state_tranisition_attempted_err",
340  ss.str()); //indicate to GUI transition NOT attempted
341  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
342  return;
343  }
344  else //clear active state machine
345  {
346  activeStateMachineName_ = "";
347  activeStateMachineWindowName_ = "";
348  }
349  }
350 
351 
352  //At this point, attempting transition!
353 
354  SOAPParameters parameters;
355  if (command == "Configure")
356  {
357  if(currentState != "Halted") //check if out of sync command
358  {
359  __SS__ << "Error - Can only transition to Configured if the current " <<
360  "state is Halted. Perhaps your state machine is out of sync." <<
361  std::endl;
362  __MOUT_ERR__ << "\n" << ss.str();
363 
364  xmldoc.addTextElementToData("state_tranisition_attempted", "0"); //indicate to GUI transition NOT attempted
365  xmldoc.addTextElementToData("state_tranisition_attempted_err",
366  ss.str()); //indicate to GUI transition NOT attempted
367  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
368  return;
369  }
370 
371  //NOTE Original name of the configuration key
372  //parameters.addParameter("RUN_KEY",CgiDataUtilities::postData(cgi,"ConfigurationAlias"));
373  parameters.addParameter("ConfigurationAlias",
374  CgiDataUtilities::postData(cgi, "ConfigurationAlias"));
375 
376  std::string configurationAlias = parameters.getValue("ConfigurationAlias");
377  __MOUT__ << "Configure --> Name: ConfigurationAlias Value: " <<
378  configurationAlias << std::endl;
379 
380  //save last used config alias
381  std::string fn = FSM_LAST_GROUP_ALIAS_PATH + FSM_LAST_GROUP_ALIAS_FILE_START +
382  username + "." + FSM_USERS_PREFERENCES_FILETYPE;
383 
384  __MOUT__ << "Save FSM preferences: " << fn << std::endl;
385  FILE *fp = fopen(fn.c_str(),"w");
386  if(!fp)
387  throw std::runtime_error("Could not open file: " + fn);
388  fprintf(fp,"FSM_last_configuration_alias %s",configurationAlias.c_str());
389  fclose(fp);
390 
391  activeStateMachineName_ = fsmName;
392  activeStateMachineWindowName_ = fsmWindowName;
393  }
394  else if (command == "Start")
395  {
396  if(currentState != "Configured") //check if out of sync command
397  {
398  __SS__ << "Error - Can only transition to Configured if the current " <<
399  "state is Halted. Perhaps your state machine is out of sync. " <<
400  "(Likely the server was restarted or another user changed the state)" <<
401  std::endl;
402  __MOUT_ERR__ << "\n" << ss.str();
403 
404  xmldoc.addTextElementToData("state_tranisition_attempted", "0"); //indicate to GUI transition NOT attempted
405  xmldoc.addTextElementToData("state_tranisition_attempted_err",
406  ss.str()); //indicate to GUI transition NOT attempted
407  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
408  return;
409  }
410 
411  unsigned int runNumber = getNextRunNumber();
412  parameters.addParameter("RunNumber", runNumber);
413  setNextRunNumber(++runNumber);
414  }
415 
416  xoap::MessageReference message = SOAPUtilities::makeSOAPMessageReference(
417  command, parameters);
418  //Maybe we return an acknowledgment that the message has been received and processed
419  xoap::MessageReference reply = stateMachineXoapHandler(message);
420  //stateMachineWorkLoopManager_.removeProcessedRequests();
421  //stateMachineWorkLoopManager_.processRequest(message);
422 
423  xmldoc.addTextElementToData("state_tranisition_attempted", "1"); //indicate to GUI transition attempted
424  xmldoc.outputXmlDocument((std::ostringstream*) out, false);
425  __MOUT__ << "Done - Xgi Request!" << std::endl;
426 }
427 
428 //========================================================================================================================
429 void Supervisor::stateMachineResultXgiHandler(xgi::Input* in, xgi::Output* out)
430 throw (xgi::exception::Exception)
431 {
432  cgicc::Cgicc cgi(in);
433  __MOUT__ << "Xgi Request!" << std::endl;
434 
435  uint8_t userPermissions; // uint64_t uid;
436  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
437  if (!theWebUsers_.cookieCodeIsActiveForRequest(cookieCode,
438  &userPermissions))
439  {
440  *out << cookieCode;
441  return;
442  }
443 
444  HttpXmlDocument xmldoc(cookieCode);
445 
446  std::string command = CgiDataUtilities::getData(cgi, "StateMachine");
447 
448  SOAPParameters parameters;
449  /*
450  //FIXME I don't think that there should be this if statement and I guess it has been copied from the stateMachineXgiHandler method
451  if (command == "Configure")
452 
453 {
454  parameters.addParameter("RUN_KEY", CgiDataUtilities::postData(cgi, "ConfigurationAlias"));
455  __MOUT__ << "Configure --> Name: RUN_KEY Value: " << parameters.getValue("RUN_KEY") << std::endl;
456  }
457  else if (command == "Start")
458 
459 {
460  unsigned int runNumber = getNextRunNumber();
461  std::stringstream runNumberStream;
462  runNumberStream << runNumber;
463  parameters.addParameter("RUN_NUMBER", runNumberStream.str().c_str());
464  setNextRunNumber(++runNumber);
465  }
466  */
467  xoap::MessageReference message = SOAPUtilities::makeSOAPMessageReference(
468  CgiDataUtilities::getData(cgi, "StateMachine"), parameters);
469  //Maybe we return an aknowledgment that the message has been received and processed
470  xoap::MessageReference reply = stateMachineResultXoapHandler(message);
471  //stateMachineWorkLoopManager_.removeProcessedRequests();
472  //stateMachineWorkLoopManager_.processRequest(message);
473  //xmldoc.outputXmlDocument((ostringstream*)out,false);
474  __MOUT__ << "Done - Xgi Request!" << std::endl;
475 }
476 
477 //========================================================================================================================
478 xoap::MessageReference Supervisor::stateMachineXoapHandler(xoap::MessageReference message)
479 throw (xoap::exception::Exception)
480 {
481  __MOUT__ << "Soap Handler!" << std::endl;
482  stateMachineWorkLoopManager_.removeProcessedRequests();
483  stateMachineWorkLoopManager_.processRequest(message);
484  __MOUT__ << "Done - Soap Handler!" << std::endl;
485  return message;
486 }
487 
488 //========================================================================================================================
489 xoap::MessageReference Supervisor::stateMachineResultXoapHandler(
490  xoap::MessageReference message)
491 throw (xoap::exception::Exception)
492 {
493  __MOUT__ << "Soap Handler!" << std::endl;
494  //stateMachineWorkLoopManager_.removeProcessedRequests();
495  //stateMachineWorkLoopManager_.processRequest(message);
496  __MOUT__ << "Done - Soap Handler!" << std::endl;
497  return message;
498 }
499 
500 //========================================================================================================================
501 bool Supervisor::stateMachineThread(toolbox::task::WorkLoop* workLoop)
502 {
503  stateMachineSemaphore_.take();
504  __MOUT__ << "Re-sending message..." << SOAPUtilities::translate( stateMachineWorkLoopManager_.getMessage(workLoop)).getCommand() << std::endl;
505  std::string reply = send(
506  theSupervisorDescriptorInfo_.getSupervisorDescriptor(),
507  stateMachineWorkLoopManager_.getMessage(workLoop));
508  stateMachineWorkLoopManager_.report(workLoop, reply, 100, true);
509 
510  __MOUT__ << "Done with message" << std::endl;
511  stateMachineSemaphore_.give();
512  return false; //execute once and automatically remove the workloop so in WorkLoopManager the try workLoop->remove(job_) could be commented out
513  //return true;//go on and then you must do the workLoop->remove(job_) in WorkLoopManager
514 }
515 
516 //========================================================================================================================
517 //infoRequestHandler ~~
518 // Call from JS GUI
519 // parameter:
520 //
521 void Supervisor::infoRequestHandler(xgi::Input* in, xgi::Output* out)
522 throw (xgi::exception::Exception)
523 {
524  __MOUT__ << "Starting to Request!" << std::endl;
525  cgicc::Cgicc cgi(in);
526 
527  //**** start LOGIN GATEWAY CODE ***//
528  //If TRUE, cookie code is good, and refreshed code is in cookieCode, also pointers optionally for uint8_t userPermissions, uint64_t uid
529  //Else, error message is returned in cookieCode
530  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
531  uint8_t userPermissions;// uint64_t uid;
532  if (!theWebUsers_.cookieCodeIsActiveForRequest(cookieCode, &userPermissions))
533  {
534  *out << cookieCode;
535  return;
536  }
537  //**** end LOGIN GATEWAY CODE ***//
538 
539  HttpXmlDocument xmldoc(cookieCode);
540 
541  //If the thread is canceled when you are still in this method that activated it, then everything will freeze.
542  //The way the workloop manager now works is safe since it cancel the thread only when the infoRequestResultHandler is called
543  //and that methid can be called ONLY when I am already out of here!
544 
545  HttpXmlDocument tmpDoc = infoRequestWorkLoopManager_.processRequest(cgi);
546 
547  xmldoc.copyDataChildren(tmpDoc);
548 
549  xmldoc.outputXmlDocument((std::ostringstream*) out, false);
550 }
551 
552 //========================================================================================================================
553 void Supervisor::infoRequestResultHandler(xgi::Input* in, xgi::Output* out)
554 throw (xgi::exception::Exception)
555 {
556  __MOUT__ << "Starting ask!" << std::endl;
557  cgicc::Cgicc cgi(in);
558 
559  //**** start LOGIN GATEWAY CODE ***//
560  //If TRUE, cookie code is good, and refreshed code is in cookieCode, also pointers optionally for uint8_t userPermissions, uint64_t uid
561  //Else, error message is returned in cookieCode
562  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
563  uint8_t userPermissions;// uint64_t uid;
564  if (!theWebUsers_.cookieCodeIsActiveForRequest(cookieCode, &userPermissions))
565  {
566  *out << cookieCode;
567  return;
568  }
569  //**** end LOGIN GATEWAY CODE ***//
570 
571  HttpXmlDocument xmldoc(cookieCode);
572 
573  infoRequestWorkLoopManager_.getRequestResult(cgi, xmldoc);
574 
575  //return xml doc holding server response
576  xmldoc.outputXmlDocument((std::ostringstream*) out, false);
577 
578  __MOUT__ << "Done asking!" << std::endl;
579 }
580 
581 //========================================================================================================================
582 bool Supervisor::infoRequestThread(toolbox::task::WorkLoop* workLoop)
583 {
584  // std::string workLoopName = workLoop->getName();
585  // __MOUT__ << " Starting WorkLoop: " << workLoopName << std::endl;
586  // __MOUT__ << " Ready to lock" << std::endl;
587  infoRequestSemaphore_.take();
588  // __MOUT__ << " Locked" << std::endl;
589  vectorTest_.clear();
590 
591  for (unsigned long long i = 0; i < 100000000; i++)
592  {
593  counterTest_ += 2;
594  vectorTest_.push_back(counterTest_);
595  }
596 
597  infoRequestWorkLoopManager_.report(workLoop,
598  "RESULT: This is the best result ever", 50, false);
599  std::string workLoopName = workLoop->getName();
600  __MOUT__ << workLoopName << " test: " << counterTest_
601  << " vector size: " << vectorTest_.size() << std::endl;
602  wait(400, "InfoRequestThread ----- locked");
603  infoRequestSemaphore_.give();
604  // __MOUT__ << " Lock released" << std::endl;
605  wait(200, "InfoRequestThread");
606  // __MOUT__ << " Ready to lock again" << std::endl;
607  infoRequestSemaphore_.take();
608  // __MOUT__ << " Locked again" << std::endl;
609  vectorTest_.clear();
610 
611  for (unsigned long long i = 0; i < 100000000; i++)
612  {
613  counterTest_ += 2;
614  vectorTest_.push_back(counterTest_);
615  }
616 
617  wait(400, "InfoRequestThread ----- locked");
618  __MOUT__ << workLoopName << " test: " << counterTest_ << " vector size: " << vectorTest_.size() << std::endl;
619  infoRequestSemaphore_.give();
620  // __MOUT__ << " Lock released again" << std::endl;
621  //infoRequestWorkLoopManager_->report(workLoop,"RESULT: This is the best result ever");
622  infoRequestWorkLoopManager_.report(workLoop,
623  theStateMachine_.getCurrentStateName(), 100, true);
624  // __MOUT__ << " Done with WorkLoop: " << workLoopName << std::endl;
625  return false; //execute once and automatically remove the workloop so in WorkLoopManager the try workLoop->remove(job_) could be commented out
626  //return true;//go on and then you must do the workLoop->remove(job_) in WorkLoopManager
627 }
628 
629 //========================================================================================================================
630 void Supervisor::stateInitial(toolbox::fsm::FiniteStateMachine & fsm)
631 throw (toolbox::fsm::exception::Exception)
632 {
633  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
634  //diagService_->reportError("--- Supervisor is in its Initial state ---",DIAGINFO);
635  //diagService_->reportError("Supervisor::stateInitial: workloop active: "+stringF(calibWorkloop_->isActive())+", workloop type: "+calibWorkloop_->getType(),DIAGINFO);
636 }
637 
638 //========================================================================================================================
639 void Supervisor::statePaused(toolbox::fsm::FiniteStateMachine & fsm)
640 throw (toolbox::fsm::exception::Exception)
641 {
642  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
643  /*
644  try
645 {
646  rcmsStateNotifier_.stateChanged("Paused", "");
647  }
648  catch(xcept::Exception &e)
649 {
650  diagService_->reportError("Failed to notify state change : "+ xcept::stdformat_exception_history(e),DIAGERROR);
651  }
652 
653  diagService_->reportError("Supervisor::statePaused: workloop active: "+stringF(calibWorkloop_->isActive())+", workloop type: "+calibWorkloop_->getType(),DIAGINFO);
654  */
655 }
656 
657 //========================================================================================================================
658 void Supervisor::stateRunning(toolbox::fsm::FiniteStateMachine & fsm)
659 throw (toolbox::fsm::exception::Exception)
660 {
661 
662  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
663  /*
664  try
665 {
666  rcmsStateNotifier_.stateChanged("Running", "");
667  }
668  catch(xcept::Exception &e)
669 {
670  diagService_->reportError("Failed to notify state change : "+ xcept::stdformat_exception_history(e),DIAGERROR);
671  }
672 
673  diagService_->reportError("Supervisor::stateRunning: workloop active: "+stringF(calibWorkloop_->isActive())+", workloop type: "+calibWorkloop_->getType(),DIAGINFO);
674  */
675 }
676 
677 //========================================================================================================================
678 void Supervisor::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
679 throw (toolbox::fsm::exception::Exception)
680 {
681  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
682  __MOUT__ << "Fsm is in transition?" << theStateMachine_.isInTransition() << std::endl;
683 
684 
685  /*
686  percentageConfigured_=0.0;
687  aliasesAndKeys_=PixelConfigInterface::getAliases();
688  diagService_->reportError("Supervisor::stateHalted: aliases and keys reloaded",DIAGINFO);
689  previousState_ = theStateMachine_.getCurrentStateName();
690  diagService_->reportError("Supervisor::stateHalted: workloop active: "+stringF(calibWorkloop_->isActive())+", workloop type: "+calibWorkloop_->getType(),DIAGINFO);
691 
692  //(hopefully) make RCMS aware of successful Recovery
693  //need to test that: (a) this works and (b) this does not break anything (regular Halt transition)
694  //update -- condition (b) seems to be satisfied. not yet sure about condition (a)
695  try
696 {
697  rcmsStateNotifier_.stateChanged("Halted", "");
698  }
699  catch(xcept::Exception &e)
700 
701 {
702  diagService_->reportError("Failed to notify state change : "+ xcept::stdformat_exception_history(e),DIAGERROR);
703  }
704  */
705 }
706 
707 //========================================================================================================================
708 void Supervisor::stateConfigured(toolbox::fsm::FiniteStateMachine & fsm)
709 throw (toolbox::fsm::exception::Exception)
710 {
711  /*
712  // Notify RCMS of having entered the Configured state
713  try
714 
715 {
716  //rcmsStateNotifier_.stateChanged(previousState_.toString(), "");
717  rcmsStateNotifier_.stateChanged("Configured", std::stringF(theGlobalKey_->key()) );
718  }
719  catch(xcept::Exception &e)
720 
721 {
722  diagService_->reportError("Failed to notify state change : "+ xcept::stdformat_exception_history(e),DIAGERROR);
723  }
724 
725  PixelTimer debugTimer;
726  if (extratimers_)
727 {
728  debugTimer.setName("Supervisor::stateConfigured");
729  debugTimer.printTime("RCMS notified of Configured state");
730  }
731  if (configurationTimer_.started() )
732 {
733  configurationTimer_.stop();
734 
735  std::string confsource(getenv("PIXELCONFIGURATIONBASE"));
736  if (confsource != "DB") confsource = "files";
737 
738  diagService_->reportError("Total configuration time ["+confsource+"] = "+stringF(configurationTimer_.tottime()),DIAGUSERINFO);
739  configurationTimer_.reset();
740  }
741 
742  diagService_->reportError( "Supervisor::stateConfigured: workloop active: "+stringF(calibWorkloop_->isActive())+", workloop type: "+calibWorkloop_->getType(),DIAGDEBUG);
743  */
744 }
745 
746 //void Supervisor::stateTTSTestMode (toolbox::fsm::FiniteStateMachine & fsm) throw (toolbox::fsm::exception::Exception)
747 //{
748 // previousState_ = theStateMachine_.getCurrentStateName();
749 //}
750 
751 //void Supervisor::inError (toolbox::fsm::FiniteStateMachine & fsm) throw (toolbox::fsm::exception::Exception)
752 //{
753 // previousState_ = theStateMachine_.getCurrentStateName();
754 //rcmsStateNotifier_.stateChanged("Error", "");
755 //}
756 
757 /*
758  xoap::MessageReference Supervisor::reset (xoap::MessageReference message) throw (xoap::exception::Exception)
759 
760 {
761  //diagService_->reportError("New state before reset is: " + theStateMachine_.getCurrentStateName(),DIAGINFO);
762 
763  theStateMachine_.reset();
764 
765  xoap::MessageReference reply = xoap::createMessage();
766  xoap::SOAPEnvelope envelope = reply->getSOAPPart().getEnvelope();
767  xoap::SOAPName responseName = envelope.createName("ResetResponse", "xdaq", XDAQ_NS_URI);
768  (void) envelope.getBody().addBodyElement ( responseName );
769 
770  diagService_->reportError("New state after reset is: " + theStateMachine_.getCurrentStateName(),DIAGINFO);
771 
772  return reply;
773  }
774  */
775 
776 //========================================================================================================================
777 void Supervisor::inError(toolbox::fsm::FiniteStateMachine & fsm)
778 throw (toolbox::fsm::exception::Exception)
779 {
780  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
781  //rcmsStateNotifier_.stateChanged("Error", "");
782 }
783 
784 //========================================================================================================================
785 void Supervisor::enteringError(toolbox::Event::Reference e)
786 throw (toolbox::fsm::exception::Exception)
787 {
788  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
789 
790  //extract error message and save for user interface access
791  toolbox::fsm::FailedEvent& failedEvent = dynamic_cast<toolbox::fsm::FailedEvent&> (*e);
792  __SS__ << "\nFailure performing transition from " << failedEvent.getFromState() << "-" <<
793  theStateMachine_.getStateName(failedEvent.getFromState()) <<
794  " to " << failedEvent.getToState() << "-" <<
795  theStateMachine_.getStateName(failedEvent.getToState()) <<
796  ".\n\nException:\n" << failedEvent.getException().what() << std::endl;
797  __MOUT_ERR__ << "\n" << ss.str();
798 
799  theStateMachine_.setErrorMessage(ss.str());
800 
801  //FIXME .. move everything else to Error!
802  //broadcastMessage(SOAPUtilities::makeSOAPMessageReference("Error"));
803 
804  //diagService_->reportError(errstr.str(),DIAGERROR);
805 
806 }
807 
811 
812 void Supervisor::getSupervisorsStatus(void)
813 throw (toolbox::fsm::exception::Exception)
814 {
815  theSupervisorsInfo_.getSupervisorInfo().setStatus(
816  theStateMachine_.getCurrentStateName());
817  //FIXME This need to be incorporated in the broadcast method
818  try
819  {
820  SupervisorDescriptors::const_iterator it =
821  theSupervisorDescriptorInfo_.getFEDescriptors().begin();
822  for (; it != theSupervisorDescriptorInfo_.getFEDescriptors().end();
823  it++)
824  {
825  try
826  {
827  std::string state = send(it->second,
828  "StateMachineStateRequest");
829 
830  theSupervisorsInfo_.getFESupervisorInfo(it->first).setStatus(
831  state);
832  //diagService_->reportError("PixelFESupervisor instance "+stringF((*i_set_PixelFESupervisor)->getInstance())+" is in FSM state "+fsmState, DIAGDEBUG);
833  __MOUT__ << "PixelFESupervisor instance " << it->first << " is in FSM state " << state << std::endl;
834  __MOUT__ << "Look! Here's a FEW! @@@" << std::endl;
835  }
836  catch (xdaq::exception::Exception& e)
837  {
838  //diagService_->reportError("PixelFESupervisor instance "+stringF((*i_set_PixelFESupervisor)->getInstance())+" could not report its FSM state", DIAGERROR);
839  }
840  }
841  // it = theSupervisorDescriptorInfo_.getARTDAQFEDescriptors().begin();
842  // for (; it != theSupervisorDescriptorInfo_.getARTDAQFEDescriptors().end();
843  // it++)
844  // {
845  // try
846  // {
847  // std::string state = send(it->second,
848  // "StateMachineStateRequest");
849  // theSupervisorsInfo_.getARTDAQFESupervisorInfo(it->first).setStatus(
850  // state);
851  // __MOUT__ << "PixelFERSupervisor instance " << it->first << " is in FSM state " << state << std::endl;
852  // __MOUT__ << "Look! Here's a FER! @@@" << std::endl;
853  // }
854  // catch (xdaq::exception::Exception& e)
855  // {
856  // //diagService_->reportError("PixelFESupervisor instance "+stringF((*i_set_PixelFESupervisor)->getInstance())+" could not report its FSM state", DIAGERROR);
857  // }
858  // }
859  for (auto& it : theSupervisorDescriptorInfo_.getARTDAQFEDataManagerDescriptors())
860  {
861  try
862  {
863  std::string state = send(it.second,
864  "StateMachineStateRequest");
865  theSupervisorsInfo_.getARTDAQFEDataManagerSupervisorInfo(it.first).setStatus(
866  state);
867  __MOUT__ << "PixelFERSupervisor instance " << it.first << " is in FSM state " << state << std::endl;
868  __MOUT__ << "Look! Here's a FER! @@@" << std::endl;
869  }
870  catch (xdaq::exception::Exception& e)
871  {
872  //diagService_->reportError("PixelFESupervisor instance "+stringF((*i_set_PixelFESupervisor)->getInstance())+" could not report its FSM state", DIAGERROR);
873  }
874  }
875  for (auto& it : theSupervisorDescriptorInfo_.getARTDAQDataManagerDescriptors())
876  {
877  try
878  {
879  std::string state = send(it.second,
880  "StateMachineStateRequest");
881  theSupervisorsInfo_.getARTDAQDataManagerSupervisorInfo(it.first).setStatus(
882  state);
883  __MOUT__ << "PixelFERSupervisor instance " << it.first << " is in FSM state " << state << std::endl;
884  __MOUT__ << "Look! Here's a FER! @@@" << std::endl;
885  }
886  catch (xdaq::exception::Exception& e)
887  {
888  //diagService_->reportError("PixelFESupervisor instance "+stringF((*i_set_PixelFESupervisor)->getInstance())+" could not report its FSM state", DIAGERROR);
889  }
890  }
891  }
892  catch (xdaq::exception::Exception& e)
893  {
894  __MOUT__
895  << "No PixelFESupervisor found in the \"daq\" group in the Configuration XML file."
896  << std::endl;
897  //diagService_->reportError("No PixelFESupervisor found in the \"daq\" group in the Configuration XML file.", DIAGERROR);
898  }
899 
900 }
901 
902 //========================================================================================================================
903 void Supervisor::transitionConfiguring(toolbox::Event::Reference e)
904 throw (toolbox::fsm::exception::Exception)
905 {
906  //theProgressBar_.resetProgressBar(0);
907 
908  theProgressBar_.step();
909 
910  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
911 
912  std::string systemAlias = SOAPUtilities::translate(
913  theStateMachine_.getCurrentMessage()).getParameters().getValue("ConfigurationAlias");
914 
915  __MOUT__ << "Transition parameter: " << systemAlias << std::endl;
916 
917  theProgressBar_.step();
918 
919 
920  try
921  {
922  theConfigurationManager_->init(); //completely reset to re-align with any changes
923  }
924  catch(...)
925  {
926  __SS__ << "\nTransition to Configuring interrupted! " <<
927  "The Configuration Manager could not be initialized." << std::endl;
928 
929  __MOUT_ERR__ << "\n" << ss.str();
930  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
931  return;
932  }
933 
934  theProgressBar_.step();
935 
936  //Translate the system alias to a group name/key
937  try
938  {
939  theConfigurationGroup_ = theConfigurationManager_->getConfigurationGroupFromAlias(systemAlias);
940  }
941  catch(...)
942  {
943  __MOUT_INFO__ << "Exception occurred" << std::endl;
944  }
945 
946  theProgressBar_.step();
947 
948  if(theConfigurationGroup_.second.isInvalid())
949  {
950  __SS__ << "\nTransition to Configuring interrupted! System Alias " <<
951  systemAlias << " could not be translated to a group name and key." << std::endl;
952 
953  __MOUT_ERR__ << "\n" << ss.str();
954  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
955  return;
956  }
957 
958  theProgressBar_.step();
959 
960  __MOUT__ << "Configuration group name: " << theConfigurationGroup_.first << " key: " <<
961  theConfigurationGroup_.second << std::endl;
962 
963  //make logbook entry
964  {
965  std::stringstream ss;
966  ss << "Configuring '" << systemAlias << "' which translates to " <<
967  theConfigurationGroup_.first << " (" << theConfigurationGroup_.second << ").";
968  makeSystemLogbookEntry(ss.str());
969  }
970 
971  theProgressBar_.step();
972 
973  //load and activate
974  try
975  {
976  theConfigurationManager_->loadConfigurationGroup(theConfigurationGroup_.first, theConfigurationGroup_.second, true);
977 
978  //When configured, set the translated System Alias to be persistently active
979  ConfigurationManagerRW tmpCfgMgr("TheSupervisor");
980  tmpCfgMgr.activateConfigurationGroup(theConfigurationGroup_.first, theConfigurationGroup_.second);
981  }
982  catch(...)
983  {
984  __SS__ << "\nTransition to Configuring interrupted! System Alias " <<
985  systemAlias << " was translated to " << theConfigurationGroup_.first <<
986  " (" << theConfigurationGroup_.second << ") but could not be loaded and initialized." << std::endl;
987  ss << "\n\nTo debug this problem, try activating this group in the Configuration GUI " <<
988  " and detailed errors will be shown." << std::endl;
989  __MOUT_ERR__ << "\n" << ss.str();
990  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
991  return;
992  }
993 
994  //check if configuration dump is enabled on configure transition
995  {
996  ConfigurationTree configLinkNode = theConfigurationManager_->getSupervisorConfigurationNode(
997  supervisorContextUID_, supervisorApplicationUID_);
998  if(!configLinkNode.isDisconnected())
999  {
1000  try //for backwards compatibility
1001  {
1002  ConfigurationTree fsmLinkNode = configLinkNode.getNode("LinkToStateMachineConfiguration");
1003  if(!fsmLinkNode.isDisconnected() &&
1004  fsmLinkNode.getNode(activeStateMachineName_ +
1005  "/EnableConfigurationDumpOnConfigureTransition").getValue<bool>())
1006  {
1007  //dump configuration
1008  theConfigurationManager_->dumpActiveConfiguration(
1009  fsmLinkNode.getNode(activeStateMachineName_ +
1010  "/ConfigurationDumpOnConfigureFilePath").getValue<std::string>() +
1011  "/" +
1012  fsmLinkNode.getNode(activeStateMachineName_ +
1013  "/ConfigurationDumpOnConfigureFileRadix").getValue<std::string>() +
1014  "_" +
1015  std::to_string(time(0)) +
1016  ".dump",
1017  fsmLinkNode.getNode(activeStateMachineName_ +
1018  "/ConfigurationDumpOnConfigureFormat").getValue<std::string>()
1019  );
1020  }
1021  else
1022  __MOUT_INFO__ << "FSM Link disconnected." << std::endl;
1023  }
1024  catch(std::runtime_error &e) {
1025  __SS__ << "\nTransition to Configuring interrupted! There was an error identified " <<
1026  "during the configuration dump attempt:\n\n " <<
1027  e.what() << std::endl;
1028  __MOUT_ERR__ << "\n" << ss.str();
1029  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
1030  return;
1031  }
1032  catch(...) {
1033  __SS__ << "\nTransition to Configuring interrupted! There was an error identified " <<
1034  "during the configuration dump attempt.\n\n " <<
1035  std::endl;
1036  __MOUT_ERR__ << "\n" << ss.str();
1037  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
1038  return;
1039  }
1040 
1041  }
1042  }
1043 
1044  theProgressBar_.step();
1045  SOAPParameters parameters;
1046  parameters.addParameter("ConfigurationGroupName", theConfigurationGroup_.first);
1047  parameters.addParameter("ConfigurationGroupKey", theConfigurationGroup_.second.toString());
1048 
1049  //xoap::MessageReference message = SOAPUtilities::makeSOAPMessageReference(SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).getCommand(), parameters);
1050  xoap::MessageReference message = theStateMachine_.getCurrentMessage();
1051  SOAPUtilities::addParameters(message,parameters);
1052  broadcastMessage(message);
1053  theProgressBar_.step();
1054  // Advertise the exiting of this method
1055  //diagService_->reportError("Supervisor::stateConfiguring: Exiting",DIAGINFO);
1056 
1057  //save last configured group name/key
1058  saveGroupNameAndKey(theConfigurationGroup_,FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE);
1059 
1060  __MOUT__ << "Done" << std::endl;
1061  theProgressBar_.complete();
1062 }
1063 
1064 //========================================================================================================================
1065 void Supervisor::transitionHalting(toolbox::Event::Reference e)
1066 throw (toolbox::fsm::exception::Exception)
1067 {
1068  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
1069 
1070  makeSystemLogbookEntry("Run halting.");
1071 
1072  broadcastMessage(theStateMachine_.getCurrentMessage());
1073 }
1074 
1075 //========================================================================================================================
1076 void Supervisor::transitionInitializing(toolbox::Event::Reference e)
1077 throw (toolbox::fsm::exception::Exception)
1078 {
1079  __MOUT__ << theStateMachine_.getCurrentStateName() << std::endl;
1080  // Get all Supervisors mentioned in the Configuration XML file, and
1081  // Try to handshake with them by asking for their FSM state.
1082  getSupervisorsStatus();
1083 
1084  if(!broadcastMessage(theStateMachine_.getCurrentMessage()))
1085  {
1086  __MOUT__ << "I can't Initialize the supervisors!" << std::endl;
1087  }
1088 
1089  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
1090  __MOUT__ << "Fsm current transition: " << theStateMachine_.getCurrentTransitionName(e->type()) << std::endl;
1091  __MOUT__ << "Fsm final state: " << theStateMachine_.getTransitionFinalStateName(e->type()) << std::endl;
1092 }
1093 
1094 //========================================================================================================================
1095 void Supervisor::transitionPausing(toolbox::Event::Reference e)
1096 throw (toolbox::fsm::exception::Exception)
1097 {
1098  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
1099 
1100  makeSystemLogbookEntry("Run pausing.");
1101 
1102  broadcastMessage(theStateMachine_.getCurrentMessage());
1103 }
1104 
1105 //========================================================================================================================
1106 void Supervisor::transitionResuming(toolbox::Event::Reference e)
1107 throw (toolbox::fsm::exception::Exception)
1108 {
1109  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
1110 
1111  makeSystemLogbookEntry("Run resuming.");
1112 
1113  broadcastMessage(theStateMachine_.getCurrentMessage());
1114 }
1115 
1116 //========================================================================================================================
1117 void Supervisor::transitionStarting(toolbox::Event::Reference e)
1118 throw (toolbox::fsm::exception::Exception)
1119 {
1120  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
1121 
1122  SOAPParameters parameters("RunNumber");
1123  receive(theStateMachine_.getCurrentMessage(), parameters);
1124 
1125  std::string runNumber = parameters.getValue("RunNumber");
1126  __MOUT__ << runNumber << std::endl;
1127 
1128  //check if configuration dump is enabled on configure transition
1129  {
1130  ConfigurationTree configLinkNode = theConfigurationManager_->getSupervisorConfigurationNode(
1131  supervisorContextUID_, supervisorApplicationUID_);
1132  if(!configLinkNode.isDisconnected())
1133  {
1134  try //for backwards compatibility
1135  {
1136  ConfigurationTree fsmLinkNode = configLinkNode.getNode("LinkToStateMachineConfiguration");
1137  if(!fsmLinkNode.isDisconnected() &&
1138  fsmLinkNode.getNode(activeStateMachineName_ +
1139  "/EnableConfigurationDumpOnRunTransition").getValue<bool>())
1140  {
1141  //dump configuration
1142  theConfigurationManager_->dumpActiveConfiguration(
1143  fsmLinkNode.getNode(activeStateMachineName_ +
1144  "/ConfigurationDumpOnRunFilePath").getValue<std::string>() +
1145  "/" +
1146  fsmLinkNode.getNode(activeStateMachineName_ +
1147  "/ConfigurationDumpOnRunFileRadix").getValue<std::string>() +
1148  "_Run" +
1149  runNumber +
1150  "_" +
1151  std::to_string(time(0)) +
1152  ".dump",
1153  fsmLinkNode.getNode(activeStateMachineName_ +
1154  "/ConfigurationDumpOnRunFormat").getValue<std::string>()
1155  );
1156  }
1157  else
1158  __MOUT_INFO__ << "FSM Link disconnected." << std::endl;
1159  }
1160  catch(std::runtime_error &e) {
1161  __SS__ << "\nTransition to Configuring interrupted! There was an error identified " <<
1162  "during the configuration dump attempt:\n\n " <<
1163  e.what() << std::endl;
1164  __MOUT_ERR__ << "\n" << ss.str();
1165  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
1166  return;
1167  }
1168  catch(...) {
1169  __SS__ << "\nTransition to Configuring interrupted! There was an error identified " <<
1170  "during the configuration dump attempt.\n\n " <<
1171  std::endl;
1172  __MOUT_ERR__ << "\n" << ss.str();
1173  XCEPT_RAISE (toolbox::fsm::exception::Exception, ss.str());
1174  return;
1175  }
1176 
1177  }
1178  }
1179 
1180 
1181  makeSystemLogbookEntry("Run " + runNumber + " starting.");
1182 
1183  broadcastMessage(theStateMachine_.getCurrentMessage());
1184 
1185  //save last started group name/key
1186  saveGroupNameAndKey(theConfigurationGroup_,FSM_LAST_STARTED_GROUP_ALIAS_FILE);
1187 }
1188 
1189 //========================================================================================================================
1190 void Supervisor::transitionStopping(toolbox::Event::Reference e)
1191 throw (toolbox::fsm::exception::Exception)
1192 {
1193  __MOUT__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
1194 
1195  makeSystemLogbookEntry("Run stopping.");
1196 
1197  broadcastMessage(theStateMachine_.getCurrentMessage());
1198 }
1199 
1203 
1204 //========================================================================================================================
1205 bool Supervisor::broadcastMessage(xoap::MessageReference message)
1206 throw (toolbox::fsm::exception::Exception)
1207 {
1208  std::string command = SOAPUtilities::translate(message).getCommand();
1209  bool proceed = true;
1210  std::string reply;
1211 
1212  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1213  // Send a SOAP message to FESupervisor
1214  for(auto& it: theSupervisorDescriptorInfo_.getFEDescriptors())
1215  {
1216  RunControlStateMachine::theProgressBar_.step();
1217  __MOUT__ << "Sending message to FESupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1218  __MOUT__ << "Sending message to FESupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1219  __MOUT__ << "Sending message to FESupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1220  __MOUT__ << "Sending message to FESupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1221  __MOUT__ << "Sending message to FESupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1222 
1223  try
1224  {
1225  reply = send(it.second, message);
1226  }
1227  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1228  {
1229  //do not kill whole system if xdaq xoap failure
1230  __SS__ << "Can NOT " << command << " FESupervisors, instance = " << it.first << ".\n\n" <<
1231  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1232  __MOUT_ERR__ << ss.str();
1233  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1234  proceed = false;
1235  }
1236 
1237  if (reply != command + "Done")
1238  {
1239  //diagService_->reportError("FESupervisor supervisor "+stringF(it->first) + " could not be initialized!",DIAGFATAL);
1240 
1241  __SS__ << "Can NOT " << command << " FESupervisor, instance = " << it.first << ".\n\n" <<
1242  reply;
1243  __MOUT_ERR__ << ss.str() << std::endl;
1244 
1245  __MOUT__ << "Getting error message..." << std::endl;
1246  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1247  SOAPParameters parameters;
1248  parameters.addParameter("ErrorMessage");
1249  SOAPMessenger::receive(errorMessage, parameters);
1250  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1251  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1252  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1253  proceed = false;
1254  //}
1255  }
1256  else
1257  {
1258  __MOUT__ << "FESupervisor supervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1259  }
1260  }
1261 
1262  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1263  for(auto& it: theSupervisorDescriptorInfo_.getDataManagerDescriptors())
1264  {
1265  RunControlStateMachine::theProgressBar_.step();
1266  __MOUT__ << "Sending message to DataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1267  __MOUT__ << "Sending message to DataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1268  __MOUT__ << "Sending message to DataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1269  __MOUT__ << "Sending message to DataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1270  __MOUT__ << "Sending message to DataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1271 
1272  try
1273  {
1274  reply = send(it.second, message);
1275  }
1276  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1277  {
1278  //do not kill whole system if xdaq xoap failure
1279  __SS__ << "Can NOT " << command << " DataManagerSupervisors, instance = " << it.first << ".\n\n" <<
1280  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1281  __MOUT_ERR__ << ss.str();
1282  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1283  proceed = false;
1284  }
1285 
1286  if (reply != command + "Done")
1287  {
1288  __SS__ << "Can NOT " << command << " DataManagerSupervisor, instance = " << it.first << ".\n\n" <<
1289  reply;
1290  __MOUT_ERR__ << ss.str() << std::endl;
1291  __MOUT__ << "Getting error message..." << std::endl;
1292  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1293  SOAPParameters parameters;
1294  parameters.addParameter("ErrorMessage");
1295  SOAPMessenger::receive(errorMessage, parameters);
1296  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1297  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1298  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1299  proceed = false;
1300  }
1301  else
1302  {
1303  __MOUT__ << "DataManagerSupervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1304  }
1305  }
1306 
1307  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1308  for (auto& it: theSupervisorDescriptorInfo_.getFEDataManagerDescriptors())
1309  {
1310  RunControlStateMachine::theProgressBar_.step();
1311  __MOUT__ << "Sending message to FEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1312  __MOUT__ << "Sending message to FEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1313  __MOUT__ << "Sending message to FEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1314  __MOUT__ << "Sending message to FEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1315  __MOUT__ << "Sending message to FEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1316 
1317  try
1318  {
1319  reply = send(it.second, message);
1320  }
1321  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1322  {
1323  //do not kill whole system if xdaq xoap failure
1324  __SS__ << "Can NOT " << command << " FEDataManagerSupervisors, instance = " << it.first << ".\n\n" <<
1325  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1326  __MOUT_ERR__ << ss.str();
1327  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1328  proceed = false;
1329  }
1330 
1331  if (reply != command + "Done")
1332  {
1333  __SS__ << "Can NOT " << command << " FEDataManagerSupervisor, instance = " << it.first << ".\n\n" <<
1334  reply;
1335  __MOUT_ERR__ << ss.str() << std::endl;
1336  __MOUT__ << "Getting error message..." << std::endl;
1337  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1338  SOAPParameters parameters;
1339  parameters.addParameter("ErrorMessage");
1340  SOAPMessenger::receive(errorMessage, parameters);
1341  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1342  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1343  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1344  proceed = false;
1345  }
1346  else
1347  {
1348  __MOUT__ << "FEDataManagerSupervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1349  }
1350  }
1351 
1352  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1353  for(auto& it: theSupervisorDescriptorInfo_.getVisualDescriptors())
1354  {
1355  RunControlStateMachine::theProgressBar_.step();
1356  __MOUT__ << "Sending message to VisualSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1357  __MOUT__ << "Sending message to VisualSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1358  __MOUT__ << "Sending message to VisualSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1359  __MOUT__ << "Sending message to VisualSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1360  __MOUT__ << "Sending message to VisualSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1361 
1362 
1363  try
1364  {
1365  reply = send(it.second, message);
1366  }
1367  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1368  {
1369  //do not kill whole system if xdaq xoap failure
1370  __SS__ << "Can NOT " << command << " VisualSupervisor, instance = " << it.first << ".\n\n" <<
1371  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1372  __MOUT_ERR__ << ss.str();
1373  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1374  proceed = false;
1375  }
1376 
1377 
1378  if (reply != command + "Done")
1379  {
1380  __SS__ << "Can NOT " << command << " VisualSupervisor, instance = " << it.first << ".\n\n" <<
1381  reply;
1382  __MOUT_ERR__ << ss.str() << std::endl;
1383  __MOUT__ << "Getting error message..." << std::endl;
1384  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1385  SOAPParameters parameters;
1386  parameters.addParameter("ErrorMessage");
1387  SOAPMessenger::receive(errorMessage, parameters);
1388  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1389  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1390  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1391  proceed = false;
1392  }
1393  else
1394  {
1395  __MOUT__ << "VisualSupervisor supervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1396  }
1397  }
1398 
1399  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1400  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1401  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1402 
1403  bool artdaqRestarted = false;
1404  bool artdaqWasRestarted = false;
1405 
1406  RunControlStateMachine::theProgressBar_.step();
1407  if(command == "Halt" || command == "Initialize")
1408  {
1409  //FIXME -- temporary solution for keeping artdaq mpi alive through reconfiguring
1410  // Steps: (if Halt or Initialize
1411  // - Restart
1412  // - Send Initialize
1413  // this will place artdaq supervisors in Halt state, same as others
1414  FILE *fp = fopen((std::string(getenv("SERVICE_DATA_PATH")) +
1415  "/StartOTS_action.cmd").c_str(),"w");
1416  if(fp)
1417  {
1418  fprintf(fp,"RESET_MPI");
1419  fclose(fp);
1420 
1421  }
1422 
1423  artdaqRestarted = true;
1424  //change message command to Initialize
1425  SOAPParameters parameters;
1426  message = SOAPUtilities::makeSOAPMessageReference(
1427  "Initialize", parameters);
1428  command = SOAPUtilities::translate(message).getCommand();
1429  __MOUT__ << "command now is " << command << std::endl;
1430  }
1431  RunControlStateMachine::theProgressBar_.step();
1432 
1433 
1434  int MAX_ARTDAQ_RESTARTS = 10;
1435  int ARTDAQ_RESTART_DELAY = 2;
1436  int artdaqRestartCount = 0;
1437  bool preArtdaqProceed = proceed;
1438 
1439 ARTDAQ_RETRY: //label to jump back for artdaq retry
1440  if(artdaqWasRestarted) //wait longer
1441  {
1442  ++artdaqRestartCount;
1443  proceed = preArtdaqProceed; //reset for each try
1444  if(artdaqRestartCount < MAX_ARTDAQ_RESTARTS)
1445  artdaqWasRestarted = false; //allow another restart
1446  for(int i=0;i<ARTDAQ_RESTART_DELAY;++i)
1447  {
1448  sleep(1);
1449  __MOUT_INFO__ << "Waiting on artdaq reboot... " << i << " for " << artdaqRestartCount << "x" << std::endl;
1450  }
1451  }
1452 
1453  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1454  for(auto& it: theSupervisorDescriptorInfo_.getARTDAQFEDataManagerDescriptors())
1455  {
1456  RunControlStateMachine::theProgressBar_.step();
1457  __MOUT__ << "Sending message to ARTDAQFEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1458  __MOUT__ << "Sending message to ARTDAQFEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1459  __MOUT__ << "Sending message to ARTDAQFEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1460  __MOUT__ << "Sending message to ARTDAQFEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1461  __MOUT__ << "Sending message to ARTDAQFEDataManagerSupervisors: " << it.second->getLocalId() << " : " << command << std::endl;
1462 
1463  try
1464  {
1465  reply = send(it.second, message);
1466  if (reply != command + "Done")
1467  {
1468  __SS__ << "Can NOT " << command << " ARTDAQFEDataManagerSupervisor, instance = " << it.first << ".\n\n" <<
1469  reply;
1470  __MOUT_ERR__ << ss.str() << std::endl;
1471  __MOUT__ << "Getting error message..." << std::endl;
1472  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1473  SOAPParameters parameters;
1474  parameters.addParameter("ErrorMessage");
1475  SOAPMessenger::receive(errorMessage, parameters);
1476  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1477  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1478  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1479  proceed = false;
1480  }
1481  else
1482  {
1483  __MOUT__ << "ARTDAQFEDataManagerSupervisors supervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1484  }
1485  }
1486  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1487  {
1488  if(artdaqRestarted && !artdaqWasRestarted)
1489  {
1490  artdaqWasRestarted = true;
1491  goto ARTDAQ_RETRY;
1492  }
1493  else
1494  {
1495  //do not kill whole system if xdaq xoap failure
1496  __SS__ << "Can NOT " << command << " ARTDAQFEDataManagerSupervisor, instance = " << it.first << ".\n\n" <<
1497  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1498  __MOUT_ERR__ << ss.str();
1499  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1500  proceed = false;
1501  }
1502  }
1503  catch(const toolbox::fsm::exception::Exception &e) //due to state machine failure
1504  {
1505  if(artdaqRestarted && !artdaqWasRestarted)
1506  {
1507  artdaqWasRestarted = true;
1508  goto ARTDAQ_RETRY;
1509  }
1510  else
1511  throw;
1512  }
1513  }
1514 
1515  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1516  // Whe artdaq FEs exist
1517  // for(auto& it: theSupervisorDescriptorInfo_.getARTDAQFEDescriptors())
1518  // {
1519  // ...
1520  //}
1521 
1522  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1523  for(auto& it: theSupervisorDescriptorInfo_.getARTDAQDataManagerDescriptors())
1524  {
1525  RunControlStateMachine::theProgressBar_.step();
1526  __MOUT__ << "Sending message to ARTDAQDataManagerSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1527  __MOUT__ << "Sending message to ARTDAQDataManagerSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1528  __MOUT__ << "Sending message to ARTDAQDataManagerSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1529  __MOUT__ << "Sending message to ARTDAQDataManagerSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1530  __MOUT__ << "Sending message to ARTDAQDataManagerSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1531  try
1532  {
1533  reply = send(it.second, message);
1534  if (reply != command + "Done")
1535  {
1536  __SS__ << "Can NOT " << command << " ARTDAQDataManagerSupervisor, instance = " << it.first << ".\n\n" <<
1537  reply;
1538  __MOUT_ERR__ << ss.str() << std::endl;
1539  __MOUT__ << "Getting error message..." << std::endl;
1540  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1541  SOAPParameters parameters;
1542  parameters.addParameter("ErrorMessage");
1543  SOAPMessenger::receive(errorMessage, parameters);
1544  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1545  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1546  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1547  proceed = false;
1548  }
1549  else
1550  {
1551  __MOUT__ << "ARTDAQDataManagerSupervisor supervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1552  }
1553  }
1554  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1555  {
1556  if(artdaqRestarted && !artdaqWasRestarted)
1557  {
1558  artdaqWasRestarted = true;
1559  goto ARTDAQ_RETRY;
1560  }
1561  else
1562  {
1563  //do not kill whole system if xdaq xoap failure
1564  __SS__ << "Can NOT " << command << " ARTDAQDataManagerSupervisor, instance = " << it.first << ".\n\n" <<
1565  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1566  __MOUT_ERR__ << ss.str();
1567  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1568  proceed = false;
1569  }
1570  }
1571  catch(const toolbox::fsm::exception::Exception &e) //due to state machine failure
1572  {
1573  if(artdaqRestarted && !artdaqWasRestarted)
1574  {
1575  artdaqWasRestarted = true;
1576  goto ARTDAQ_RETRY;
1577  }
1578  else
1579  throw;
1580  }
1581  }
1582 
1583  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1584  for(auto& it: theSupervisorDescriptorInfo_.getARTDAQBuilderDescriptors())
1585  {
1586  RunControlStateMachine::theProgressBar_.step();
1587  __MOUT__ << "Sending message to ARTDAQBuilderSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1588  __MOUT__ << "Sending message to ARTDAQBuilderSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1589  __MOUT__ << "Sending message to ARTDAQBuilderSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1590  __MOUT__ << "Sending message to ARTDAQBuilderSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1591  __MOUT__ << "Sending message to ARTDAQBuilderSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1592 
1593  try
1594  {
1595  reply = send(it.second, message);
1596  if (reply != command + "Done")
1597  {
1598  __SS__ << "Can NOT " << command << " ARTDAQBuilderSupervisor, instance = " << it.first << ".\n\n" <<
1599  reply;
1600  __MOUT_ERR__ << ss.str() << std::endl;
1601  __MOUT__ << "Getting error message..." << std::endl;
1602  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1603  SOAPParameters parameters;
1604  parameters.addParameter("ErrorMessage");
1605  SOAPMessenger::receive(errorMessage, parameters);
1606  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1607  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1608  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1609  proceed = false;
1610  }
1611  else
1612  {
1613  __MOUT__ << "ARTDAQBuilderSupervisor supervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1614  }
1615  }
1616  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1617  {
1618  if(artdaqRestarted && !artdaqWasRestarted)
1619  {
1620  artdaqWasRestarted = true;
1621  goto ARTDAQ_RETRY;
1622  }
1623  else
1624  {
1625  //do not kill whole system if xdaq xoap failure
1626  __SS__ << "Can NOT " << command << " ARTDAQBuilderSupervisor, instance = " << it.first << ".\n\n" <<
1627  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1628  __MOUT_ERR__ << ss.str();
1629  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1630  proceed = false;
1631  }
1632  }
1633  catch(const toolbox::fsm::exception::Exception &e) //due to state machine failure
1634  {
1635  if(artdaqRestarted && !artdaqWasRestarted)
1636  {
1637  artdaqWasRestarted = true;
1638  goto ARTDAQ_RETRY;
1639  }
1640  else
1641  throw;
1642  }
1643  }
1644 
1645  //:::::::::::::::::::::::::::::::::::::::::::::::::::::
1646  for(auto& it: theSupervisorDescriptorInfo_.getARTDAQAggregatorDescriptors())
1647  {
1648  RunControlStateMachine::theProgressBar_.step();
1649  __MOUT__ << "Sending message to ARTDAQAggregatorSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1650  __MOUT__ << "Sending message to ARTDAQAggregatorSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1651  __MOUT__ << "Sending message to ARTDAQAggregatorSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1652  __MOUT__ << "Sending message to ARTDAQAggregatorSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1653  __MOUT__ << "Sending message to ARTDAQAggregatorSupervisor: " << it.second->getLocalId() << " : " << command << std::endl;
1654 
1655  try
1656  {
1657  reply = send(it.second, message);
1658  if (reply != command + "Done")
1659  {
1660  __SS__ << "Can NOT " << command << " ARTDAQAggregatorSupervisor, instance = " << it.first << ".\n\n" <<
1661  reply;
1662  __MOUT_ERR__ << ss.str() << std::endl;
1663  __MOUT__ << "Getting error message..." << std::endl;
1664  xoap::MessageReference errorMessage = sendWithSOAPReply(it.second, SOAPUtilities::makeSOAPMessageReference("StateMachineErrorMessageRequest"));
1665  SOAPParameters parameters;
1666  parameters.addParameter("ErrorMessage");
1667  SOAPMessenger::receive(errorMessage, parameters);
1668  __MOUT_ERR__ << "errorMessage = " << parameters.getValue("ErrorMessage") << std::endl;
1669  ss << "\n\nError Message: " << parameters.getValue("ErrorMessage") << std::endl;
1670  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1671  proceed = false;
1672  }
1673  else
1674  {
1675  __MOUT__ << "ARTDAQAggregatorSupervisor supervisor " << (it.first) << " was " << command << "'d correctly!" << std::endl;
1676  }
1677  }
1678  catch(const xdaq::exception::Exception &e) //due to xoap send failure
1679  {
1680  if(artdaqRestarted && !artdaqWasRestarted)
1681  {
1682  artdaqWasRestarted = true;
1683  goto ARTDAQ_RETRY;
1684  }
1685  else
1686  {
1687  //do not kill whole system if xdaq xoap failure
1688  __SS__ << "Can NOT " << command << " ARTDAQAggregatorSupervisor, instance = " << it.first << ".\n\n" <<
1689  "Xoap failure. Did the target Supervisor crash? Try restarting re-initializing or restarting otsdaq." << std::endl;
1690  __MOUT_ERR__ << ss.str();
1691  XCEPT_RAISE(toolbox::fsm::exception::Exception, ss.str());
1692  proceed = false;
1693  }
1694  }
1695  catch(const toolbox::fsm::exception::Exception &e) //due to state machine failure
1696  {
1697  if(artdaqRestarted && !artdaqWasRestarted)
1698  {
1699  artdaqWasRestarted = true;
1700  goto ARTDAQ_RETRY;
1701  }
1702  else
1703  throw;
1704  }
1705  }
1706 
1707  return proceed;
1708 }
1709 
1710 //========================================================================================================================
1711 void Supervisor::wait(int milliseconds, std::string who) const
1712 {
1713  for (int s = 1; s <= milliseconds; s++)
1714  {
1715  usleep(1000);
1716 
1717  if (s % 100 == 0)
1718  __MOUT__ << s << " msecs " << who << std::endl;
1719  }
1720 }
1721 
1722 //========================================================================================================================
1723 //LoginRequest
1724 // handles all users login/logout actions from web GUI.
1725 // NOTE: there are two ways for a user to be logged out: timeout or manual logout
1726 // System logbook messages are generated for login and logout
1727 void Supervisor::loginRequest(xgi::Input * in, xgi::Output * out)
1728 throw (xgi::exception::Exception)
1729 {
1730  cgicc::Cgicc cgi(in);
1731  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
1732 
1733  __MOUT__ << Command << std::endl;
1734 
1735  //RequestType Commands:
1736  //login
1737  //sessionId
1738  //checkCookie
1739  //logout
1740 
1741  //always cleanup expired entries and get a vector std::string of logged out users
1742  std::vector<std::string> loggedOutUsernames;
1743  theWebUsers_.cleanupExpiredEntries(&loggedOutUsernames);
1744  for (unsigned int i = 0; i < loggedOutUsernames.size(); ++i) //Log logout for logged out users
1745  makeSystemLogbookEntry(loggedOutUsernames[i] + " login timed out.");
1746 
1747  if (Command == "sessionId")
1748  {
1749  // When client loads page, client submits unique user id and receives random sessionId from server
1750  // Whenever client submits user name and password it is jumbled by sessionId when sent to server and sent along with UUID. Server uses sessionId to unjumble.
1751  //
1752  // Server maintains list of active sessionId by UUID
1753  // sessionId expires after set time if no login attempt (e.g. 5 minutes)
1754  std::string uuid = CgiDataUtilities::postData(cgi, "uuid");
1755 
1756  std::string sid = theWebUsers_.createNewLoginSession(uuid);
1757 
1758  __MOUT__ << "uuid = " << uuid << std::endl;
1759  __MOUT__ << "SessionId = " << sid.substr(0, 10) << std::endl;
1760  *out << sid;
1761  }
1762  else if (Command == "checkCookie")
1763  {
1764  uint64_t uid;
1765  std::string uuid;
1766  std::string jumbledUser;
1767  std::string cookieCode;
1768 
1769  // If client has a cookie, client submits cookie and username, jumbled, to see if cookie and user are still active
1770  // if active, valid cookie code is returned and name to display, in XML
1771  // if not, return 0
1772  // params:
1773  // uuid - unique user id, to look up sessionId
1774  // ju - jumbled user name
1775  // CookieCode - cookie code to check
1776 
1777  uuid = CgiDataUtilities::postData(cgi, "uuid");
1778  jumbledUser = CgiDataUtilities::postData(cgi, "ju");
1779  cookieCode = CgiDataUtilities::postData(cgi, "cc");
1780 
1781  __MOUT__ << "Cookie Code = " << cookieCode.substr(0, 10) << std::endl;
1782  __MOUT__ << "jumbledUser = " << jumbledUser.substr(0, 10) << std::endl;
1783  __MOUT__ << "uuid = " << uuid << std::endl;
1784 
1785  //If cookie code is good, then refresh and return with display name, else return 0 as CookieCode value
1786  uid = theWebUsers_.isCookieCodeActiveForLogin(uuid, cookieCode,
1787  jumbledUser); //after call jumbledUser holds displayName on success
1788 
1789  if (uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
1790  {
1791  __MOUT__ << "cookieCode invalid" << std::endl;
1792  jumbledUser = ""; //clear display name if failure
1793  cookieCode = "0";//clear cookie code if failure
1794  }
1795 
1796  //return xml holding cookie code and display name
1797  HttpXmlDocument xmldoc(cookieCode, jumbledUser);
1798 
1799  theWebUsers_.insertSettingsForUser(uid, &xmldoc); //insert settings
1800 
1801  xmldoc.outputXmlDocument((std::ostringstream*) out);
1802 
1803  }
1804  else if (Command == "login")
1805  {
1806  // If login attempt or create account, jumbled user and pw are submitted
1807  // if successful, valid cookie code and display name returned.
1808  // if not, return 0
1809  // params:
1810  // uuid - unique user id, to look up sessionId
1811  // nac - new account code for first time logins
1812  // ju - jumbled user name
1813  // jp - jumbled password
1814 
1815  std::string uuid = CgiDataUtilities::postData(cgi, "uuid");
1816  std::string newAccountCode = CgiDataUtilities::postData(cgi, "nac");
1817  std::string jumbledUser = CgiDataUtilities::postData(cgi, "ju");
1818  std::string jumbledPw = CgiDataUtilities::postData(cgi, "jp");
1819 
1820  __MOUT__ << "jumbledUser = " << jumbledUser.substr(0, 10) << std::endl;
1821  __MOUT__ << "jumbledPw = " << jumbledPw.substr(0, 10) << std::endl;
1822  __MOUT__ << "uuid = " << uuid << std::endl;
1823  __MOUT__ << "nac =-" << newAccountCode << "-" << std::endl;
1824 
1825  uint64_t uid = theWebUsers_.attemptActiveSession(uuid, jumbledUser,
1826  jumbledPw, newAccountCode); //after call jumbledUser holds displayName on success
1827 
1828 
1829  if (uid == theWebUsers_.NOT_FOUND_IN_DATABASE)
1830  {
1831  __MOUT__ << "cookieCode invalid" << std::endl;
1832  jumbledUser = ""; //clear display name if failure
1833  if (newAccountCode != "1")//indicates uuid not found
1834  newAccountCode = "0";//clear cookie code if failure
1835  }
1836 
1837  __MOUT__ << "new cookieCode = " << newAccountCode.substr(0, 10) << std::endl;
1838 
1839  HttpXmlDocument xmldoc(newAccountCode, jumbledUser);
1840 
1841  theWebUsers_.insertSettingsForUser(uid, &xmldoc); //insert settings
1842 
1843  //insert active session count for user
1844 
1845  if (uid != theWebUsers_.NOT_FOUND_IN_DATABASE)
1846  {
1847  uint64_t asCnt = theWebUsers_.getActiveSessionCountForUser(uid) - 1; //subtract 1 to remove just started session from count
1848  char asStr[20];
1849  sprintf(asStr, "%lu", asCnt);
1850  xmldoc.addTextElementToData("user_active_session_count", asStr);
1851  }
1852 
1853  xmldoc.outputXmlDocument((std::ostringstream*) out);
1854 
1855  //Log login in logbook for active experiment
1856  makeSystemLogbookEntry(
1857  theWebUsers_.getUsersUsername(uid) + " logged in.");
1858  }
1859  else if (Command == "logout")
1860  {
1861  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
1862  std::string logoutOthers = CgiDataUtilities::postData(cgi,
1863  "LogoutOthers");
1864 
1865  __MOUT__ << "Cookie Code = " << cookieCode.substr(0, 10) << std::endl;
1866  __MOUT__ << "logoutOthers = " << logoutOthers << std::endl;
1867 
1868  uint64_t uid; //get uid for possible system logbook message
1869  if (theWebUsers_.cookieCodeLogout(cookieCode, logoutOthers == "1", &uid)
1870  != theWebUsers_.NOT_FOUND_IN_DATABASE) //user logout
1871  {
1872  //if did some logging out, check if completely logged out
1873  //if so, system logbook message should be made.
1874  if (!theWebUsers_.isUserIdActive(uid))
1875  makeSystemLogbookEntry(
1876  theWebUsers_.getUsersUsername(uid) + " logged out.");
1877  }
1878  }
1879  else
1880  {
1881  __MOUT__ << __LINE__ << "\tInvalid Command" << std::endl;
1882  *out << "0";
1883  }
1884 }
1885 
1886 //========================================================================================================================
1887 void Supervisor::tooltipRequest(xgi::Input * in, xgi::Output * out)
1888 throw (xgi::exception::Exception)
1889 {
1890  cgicc::Cgicc cgi(in);
1891 
1892  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
1893  __MOUT__ << Command << std::endl;
1894 
1895  //**** start LOGIN GATEWAY CODE ***//
1896  //If TRUE, cookie code is good, and refreshed code is in cookieCode, also pointers optionally for uint8_t userPermissions, uint64_t uid
1897  //Else, error message is returned in cookieCode
1898  //Notes: cookie code not refreshed if RequestType = getSystemMessages
1899  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
1900  uint8_t userPermissions;
1901  uint64_t uid;
1902 
1903  if (!theWebUsers_.cookieCodeIsActiveForRequest(cookieCode, &userPermissions,
1904  &uid, "0", false))
1905  {
1906  *out << cookieCode;
1907  return;
1908  }
1909 
1910  //**** end LOGIN GATEWAY CODE ***//
1911 
1912  HttpXmlDocument xmldoc(cookieCode);
1913 
1914  if(Command == "check")
1915  {
1916  WebUsers::tooltipCheckForUsername(
1917  theWebUsers_.getUsersUsername(uid),
1918  &xmldoc,
1919  CgiDataUtilities::getData(cgi, "srcFile"),
1920  CgiDataUtilities::getData(cgi, "srcFunc"),
1921  CgiDataUtilities::getData(cgi, "srcId"));
1922  }
1923  else if(Command == "setNeverShow")
1924  {
1925  WebUsers::tooltipSetNeverShowForUsername(
1926  theWebUsers_.getUsersUsername(uid),
1927  &xmldoc,
1928  CgiDataUtilities::getData(cgi, "srcFile"),
1929  CgiDataUtilities::getData(cgi, "srcFunc"),
1930  CgiDataUtilities::getData(cgi, "srcId"),
1931  CgiDataUtilities::getData(cgi, "doNeverShow") == "1"?true:false,
1932  CgiDataUtilities::getData(cgi, "temporarySilence") == "1"?true:false);
1933 
1934  }
1935  else
1936  __MOUT__ << "Command Request, " << Command << ", not recognized." << std::endl;
1937 
1938  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
1939 }
1940 
1941 //========================================================================================================================
1942 void Supervisor::request(xgi::Input * in, xgi::Output * out)
1943 throw (xgi::exception::Exception)
1944 {
1945  cgicc::Cgicc cgi(in);
1946 
1947  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
1948  //__MOUT__ << Command << std::endl;
1949 
1950  //**** start LOGIN GATEWAY CODE ***//
1951  //If TRUE, cookie code is good, and refreshed code is in cookieCode, also pointers optionally for uint8_t userPermissions, uint64_t uid
1952  //Else, error message is returned in cookieCode
1953  //Notes: cookie code not refreshed if RequestType = getSystemMessages
1954  std::string cookieCode = CgiDataUtilities::postData(cgi, "CookieCode");
1955  uint8_t userPermissions;
1956  uint64_t uid;
1957  std::string userWithLock;
1958 
1959  if (!theWebUsers_.cookieCodeIsActiveForRequest(cookieCode, &userPermissions,
1960  &uid, "0", Command != "getSystemMessages", &userWithLock))
1961  {
1962  *out << cookieCode;
1963  return;
1964  }
1965 
1966  //**** end LOGIN GATEWAY CODE ***//
1967 
1968  //RequestType Commands:
1969  //getSettings
1970  //setSettings
1971  //accountSettings
1972  //getAliasList
1973  //getFecList
1974  //getSystemMessages
1975  //setUserWithLock
1976  //getStateMatchine
1977  //stateMatchinePreferences
1978  //getCurrentState
1979  //getErrorInStateMatchine
1980  //getDesktopIcons
1981  //launchConfig
1982  //resetUserTooltips
1983 
1984 
1985  HttpXmlDocument xmldoc(cookieCode);
1986 
1987  if (Command == "getSettings")
1988  {
1989  std::string accounts = CgiDataUtilities::getData(cgi, "accounts");
1990 
1991  __MOUT__ << "Get Settings Request" << std::endl;
1992  __MOUT__ << "accounts = " << accounts << std::endl;
1993  theWebUsers_.insertSettingsForUser(uid, &xmldoc, accounts == "1");
1994  }
1995  else if (Command == "setSettings")
1996  {
1997  std::string bgcolor = CgiDataUtilities::postData(cgi, "bgcolor");
1998  std::string dbcolor = CgiDataUtilities::postData(cgi, "dbcolor");
1999  std::string wincolor = CgiDataUtilities::postData(cgi, "wincolor");
2000  std::string layout = CgiDataUtilities::postData(cgi, "layout");
2001  std::string syslayout = CgiDataUtilities::postData(cgi, "syslayout");
2002 
2003  __MOUT__ << "Set Settings Request" << std::endl;
2004  __MOUT__ << "bgcolor = " << bgcolor << std::endl;
2005  __MOUT__ << "dbcolor = " << dbcolor << std::endl;
2006  __MOUT__ << "wincolor = " << wincolor << std::endl;
2007  __MOUT__ << "layout = " << layout << std::endl;
2008  __MOUT__ << "syslayout = " << syslayout << std::endl;
2009  theWebUsers_.changeSettingsForUser(uid, bgcolor, dbcolor, wincolor,
2010  layout, syslayout);
2011  theWebUsers_.insertSettingsForUser(uid, &xmldoc, true); //include user accounts
2012  }
2013  else if (Command == "accountSettings")
2014  {
2015  std::string type = CgiDataUtilities::postData(cgi, "type"); //updateAccount, createAccount, deleteAccount
2016  int type_int = -1;
2017 
2018  if (type == "updateAccount")
2019  type_int = 0;
2020  else if (type == "createAccount")
2021  type_int = 1;
2022  else if (type == "deleteAccount")
2023  type_int = 2;
2024 
2025  std::string username = CgiDataUtilities::postData(cgi, "username");
2026  std::string displayname = CgiDataUtilities::postData(cgi,
2027  "displayname");
2028  std::string permissions = CgiDataUtilities::postData(cgi,
2029  "permissions");
2030  std::string accounts = CgiDataUtilities::getData(cgi, "accounts");
2031 
2032  __MOUT__ << "accountSettings Request" << std::endl;
2033  __MOUT__ << "type = " << type << " - " << type_int << std::endl;
2034  __MOUT__ << "username = " << username << std::endl;
2035  __MOUT__ << "displayname = " << displayname << std::endl;
2036  __MOUT__ << "permissions = " << permissions << std::endl;
2037 
2038  theWebUsers_.modifyAccountSettings(uid, type_int, username, displayname,
2039  permissions);
2040 
2041  __MOUT__ << "accounts = " << accounts << std::endl;
2042 
2043  theWebUsers_.insertSettingsForUser(uid, &xmldoc, accounts == "1");
2044  }
2045  else if(Command == "stateMatchinePreferences")
2046  {
2047  std::string set = CgiDataUtilities::getData(cgi, "set");
2048  const std::string DEFAULT_FSM_VIEW = "Default_FSM_View";
2049  if(set == "1")
2050  theWebUsers_.setGenericPreference(uid, DEFAULT_FSM_VIEW,
2051  CgiDataUtilities::getData(cgi, DEFAULT_FSM_VIEW));
2052  else
2053  theWebUsers_.getGenericPreference(uid, DEFAULT_FSM_VIEW, &xmldoc);
2054  }
2055  else if(Command == "getAliasList")
2056  {
2057  std::string username = theWebUsers_.getUsersUsername(uid);
2058  std::string fsmName = CgiDataUtilities::getData(cgi, "fsmName");
2059  __MOUT__ << "fsmName = " << fsmName << std::endl;
2060 
2061  std::string stateMachineAliasFilter = "*"; //default to all
2062 
2063  std::map<std::string /*alias*/,
2064  std::pair<std::string /*group name*/, ConfigurationGroupKey> > aliasMap =
2065  theConfigurationManager_->getGroupAliasesConfiguration();
2066 
2067 
2068  // get stateMachineAliasFilter if possible
2069  ConfigurationTree configLinkNode = theConfigurationManager_->getSupervisorConfigurationNode(
2070  supervisorContextUID_, supervisorApplicationUID_);
2071 
2072  if(!configLinkNode.isDisconnected())
2073  {
2074  try //for backwards compatibility
2075  {
2076  ConfigurationTree fsmLinkNode = configLinkNode.getNode("LinkToStateMachineConfiguration");
2077  if(!fsmLinkNode.isDisconnected())
2078  stateMachineAliasFilter =
2079  fsmLinkNode.getNode(fsmName + "/SystemAliasFilter").getValue<std::string>();
2080  else
2081  __MOUT_INFO__ << "FSM Link disconnected." << std::endl;
2082  }
2083  catch(std::runtime_error &e) { __MOUT_INFO__ << e.what() << std::endl; }
2084  catch(...) { __MOUT_ERR__ << "Unknown error. Should never happen." << std::endl; }
2085  }
2086  else
2087  __MOUT_INFO__ << "FSM Link disconnected." << std::endl;
2088 
2089  __MOUT__ << "stateMachineAliasFilter = " << stateMachineAliasFilter << std::endl;
2090 
2091 
2092  //filter list of aliases based on stateMachineAliasFilter
2093  // ! as first character means choose those that do NOT match filter
2094  // * can be used as wild card.
2095  {
2096  bool invertFilter = stateMachineAliasFilter.size() && stateMachineAliasFilter[0] == '!';
2097  std::vector<std::string> filterArr;
2098 
2099  size_t i = 0;
2100  if(invertFilter) ++i;
2101  size_t f;
2102  std::string tmp;
2103  while((f = stateMachineAliasFilter.find('*',i)) != std::string::npos)
2104  {
2105  tmp = stateMachineAliasFilter.substr(i,f-i);
2106  i = f+1;
2107  filterArr.push_back(tmp);
2108  //__MOUT__ << filterArr[filterArr.size()-1] << " " << i <<
2109  // " of " << stateMachineAliasFilter.size() << std::endl;
2110 
2111  }
2112  if(i <= stateMachineAliasFilter.size())
2113  {
2114  tmp = stateMachineAliasFilter.substr(i);
2115  filterArr.push_back(tmp);
2116  //__MOUT__ << filterArr[filterArr.size()-1] << " last." << std::endl;
2117  }
2118 
2119 
2120  bool filterMatch;
2121 
2122 
2123  for(auto& aliasMapPair : aliasMap)
2124  {
2125  //__MOUT__ << "aliasMapPair.first: " << aliasMapPair.first << std::endl;
2126 
2127  filterMatch = true;
2128 
2129  if(filterArr.size() == 1)
2130  {
2131  if(filterArr[0] != "" &&
2132  filterArr[0] != "*" &&
2133  aliasMapPair.first != filterArr[0])
2134  filterMatch = false;
2135  }
2136  else
2137  {
2138  i = -1;
2139  for(f=0;f<filterArr.size();++f)
2140  {
2141  if(!filterArr[f].size()) continue; //skip empty filters
2142 
2143  if(f == 0) //must start with this filter
2144  {
2145  if((i = aliasMapPair.first.find(filterArr[f])) != 0)
2146  {
2147  filterMatch = false;
2148  break;
2149  }
2150  }
2151  else if(f == filterArr.size()-1) //must end with this filter
2152  {
2153  if(aliasMapPair.first.rfind(filterArr[f]) !=
2154  aliasMapPair.first.size() - filterArr[f].size())
2155  {
2156  filterMatch = false;
2157  break;
2158  }
2159  }
2160  else if((i = aliasMapPair.first.find(filterArr[f])) ==
2161  std::string::npos)
2162  {
2163  filterMatch = false;
2164  break;
2165  }
2166  }
2167  }
2168 
2169  if(invertFilter) filterMatch = !filterMatch;
2170 
2171  //__MOUT__ << "filterMatch=" << filterMatch << std::endl;
2172 
2173  if(!filterMatch) continue;
2174 
2175  xmldoc.addTextElementToData("config_alias", aliasMapPair.first);
2176  xmldoc.addTextElementToData("config_key",
2177  ConfigurationGroupKey::getFullGroupString(aliasMapPair.second.first,
2178  aliasMapPair.second.second).c_str());
2179 
2180  std::string groupComment, groupAuthor, groupCreationTime;
2181  try
2182  {
2183  theConfigurationManager_->loadConfigurationGroup(
2184  aliasMapPair.second.first,aliasMapPair.second.second,
2185  false,0,0,
2186  &groupComment, &groupAuthor, &groupCreationTime, false /*false to not load member map*/);
2187 
2188  xmldoc.addTextElementToData("config_comment", groupComment);
2189  xmldoc.addTextElementToData("config_author", groupAuthor);
2190  xmldoc.addTextElementToData("config_create_time", groupCreationTime);
2191  }
2192  catch(...)
2193  {
2194  __MOUT_WARN__ << "Failed to load group metadata." << std::endl;
2195  }
2196  }
2197  }
2198 
2199  //return last group alias
2200  std::string fn = FSM_LAST_GROUP_ALIAS_PATH + FSM_LAST_GROUP_ALIAS_FILE_START +
2201  username + "." + FSM_USERS_PREFERENCES_FILETYPE;
2202  __MOUT__ << "Load preferences: " << fn << std::endl;
2203  FILE *fp = fopen(fn.c_str(),"r");
2204  if(fp)
2205  {
2206  char tmpLastAlias[500];
2207  fscanf(fp,"%*s %s",tmpLastAlias);
2208  __MOUT__ << "tmpLastAlias: " << tmpLastAlias << std::endl;
2209 
2210  xmldoc.addTextElementToData("UserLastConfigAlias",tmpLastAlias);
2211  fclose(fp);
2212  }
2213  }
2214  else if (Command == "getFecList")
2215  {
2216  xmldoc.addTextElementToData("fec_list", "");
2217 
2218  for (unsigned int i = 0; i< theSupervisorDescriptorInfo_.getFEDescriptors().size(); ++i)
2219  {
2220  xmldoc.addTextElementToParent("fec_url",
2221  theSupervisorDescriptorInfo_.getFEURL(i), "fec_list");
2222  xmldoc.addTextElementToParent(
2223  "fec_urn",
2224  theSupervisorDescriptorInfo_.getFEDescriptor(i)->getURN(),
2225  "fec_list");
2226  }
2227  }
2228  else if (Command == "getSystemMessages")
2229  {
2230  xmldoc.addTextElementToData("systemMessages",
2231  theSysMessenger_.getSysMsg(
2232  theWebUsers_.getUsersDisplayName(uid)));
2233 
2234  xmldoc.addTextElementToData("username_with_lock",
2235  theWebUsers_.getUserWithLock()); //always give system lock update
2236 
2237  //__MOUT__ << "userWithLock " << theWebUsers_.getUserWithLock() << std::endl;
2238  }
2239  else if (Command == "setUserWithLock")
2240  {
2241  std::string username = CgiDataUtilities::postData(cgi, "username");
2242  std::string lock = CgiDataUtilities::postData(cgi, "lock");
2243  std::string accounts = CgiDataUtilities::getData(cgi, "accounts");
2244 
2245  __MOUT__ << Command << std::endl;
2246  __MOUT__ << "username " << username << std::endl;
2247  __MOUT__ << "lock " << lock << std::endl;
2248  __MOUT__ << "accounts " << accounts << std::endl;
2249  __MOUT__ << "uid " << uid << std::endl;
2250 
2251  std::string tmpUserWithLock = theWebUsers_.getUserWithLock();
2252  if(!theWebUsers_.setUserWithLock(uid, lock == "1", username))
2253  xmldoc.addTextElementToData("server_alert",
2254  std::string("Set user lock action failed. You must have valid permissions and ") +
2255  "locking user must be currently logged in.");
2256 
2257  theWebUsers_.insertSettingsForUser(uid, &xmldoc, accounts == "1");
2258 
2259  if (tmpUserWithLock != theWebUsers_.getUserWithLock()) //if there was a change, broadcast system message
2260  theSysMessenger_.addSysMsg("*", theWebUsers_.getUserWithLock()
2261  == "" ? tmpUserWithLock + " has unlocked ots."
2262  : theWebUsers_.getUserWithLock()
2263  + " has locked ots.");
2264  }
2265  else if (Command == "getStateMachine")
2266  {
2267  // __MOUT__ << "Getting state machine" << std::endl;
2268  std::vector<toolbox::fsm::State> states;
2269  states = theStateMachine_.getStates();
2270  char stateStr[2];
2271  stateStr[1] = '\0';
2272  std::string transName;
2273  std::string transParameter;
2274  for (unsigned int i = 0; i < states.size(); ++i)//get all states
2275  {
2276  stateStr[0] = states[i];
2277  DOMElement* stateParent = xmldoc.addTextElementToData("state", stateStr);
2278 
2279  xmldoc.addTextElementToParent("state_name", theStateMachine_.getStateName(states[i]), stateParent);
2280 
2281  //__MOUT__ << "state: " << states[i] << " - " << theStateMachine_.getStateName(states[i]) << std::endl;
2282 
2283  //get all transition final states, transitionNames and actionNames from state
2284  std::map<std::string, toolbox::fsm::State, std::less<std::string> >
2285  trans = theStateMachine_.getTransitions(states[i]);
2286  std::set<std::string> actionNames = theStateMachine_.getInputs(states[i]);
2287 
2288  std::map<std::string, toolbox::fsm::State, std::less<std::string> >::iterator
2289  it = trans.begin();
2290  std::set<std::string>::iterator ait = actionNames.begin();
2291  for (; it != trans.end() && ait != actionNames.end(); ++it, ++ait)
2292  {
2293  //__MOUT__ << states[i] << " => " << it->second << std::endl;
2294 
2295  stateStr[0] = it->second;
2296  xmldoc.addTextElementToParent("state_transition", stateStr, stateParent);
2297 
2298  //__MOUT__ << states[i] << " => " << *ait << std::endl;
2299 
2300  xmldoc.addTextElementToParent("state_transition_action", *ait, stateParent);
2301 
2302  transName = theStateMachine_.getTransitionName(states[i], *ait);
2303  //__MOUT__ << states[i] << " => " << transName << std::endl;
2304 
2305  xmldoc.addTextElementToParent("state_transition_name",
2306  transName, stateParent);
2307  transParameter = theStateMachine_.getTransitionParameter(states[i], *ait);
2308  //__MOUT__ << states[i] << " => " << transParameter<< std::endl;
2309 
2310  xmldoc.addTextElementToParent("state_transition_parameter", transParameter, stateParent);
2311  }
2312  }
2313 
2314  }
2315  else if (Command == "getCurrentState")
2316  {
2317  xmldoc.addTextElementToData("current_state", theStateMachine_.getCurrentStateName());
2318  xmldoc.addTextElementToData("in_transition", theStateMachine_.isInTransition() ? "1" : "0");
2319  if (theStateMachine_.isInTransition())
2320  xmldoc.addTextElementToData("transition_progress", theProgressBar_.readPercentageString());
2321  else
2322  xmldoc.addTextElementToData("transition_progress", "100");
2323 
2324 
2325  char tmp[20];
2326  sprintf(tmp,"%lu",theStateMachine_.getTimeInState());
2327  xmldoc.addTextElementToData("time_in_state", tmp);
2328 
2329 
2330 
2331  //__MOUT__ << "current state: " << theStateMachine_.getCurrentStateName() << std::endl;
2332 
2333 
2335  std::string fsmName = CgiDataUtilities::getData(cgi, "fsmName");
2336  // __MOUT__ << "fsmName = " << fsmName << std::endl;
2337  // __MOUT__ << "activeStateMachineName_ = " << activeStateMachineName_ << std::endl;
2338  // __MOUT__ << "theStateMachine_.getProvenanceStateName() = " <<
2339  // theStateMachine_.getProvenanceStateName() << std::endl;
2340  // __MOUT__ << "theStateMachine_.getCurrentStateName() = " <<
2341  // theStateMachine_.getCurrentStateName() << std::endl;
2342 
2343  if(!theStateMachine_.isInTransition())
2344  {
2345  std::string stateMachineRunAlias = "Run"; //default to "Run"
2346 
2347  // get stateMachineAliasFilter if possible
2348  ConfigurationTree configLinkNode = theConfigurationManager_->getSupervisorConfigurationNode(
2349  supervisorContextUID_, supervisorApplicationUID_);
2350 
2351  if(!configLinkNode.isDisconnected())
2352  {
2353  try //for backwards compatibility
2354  {
2355  ConfigurationTree fsmLinkNode = configLinkNode.getNode("LinkToStateMachineConfiguration");
2356  if(!fsmLinkNode.isDisconnected())
2357  stateMachineRunAlias =
2358  fsmLinkNode.getNode(fsmName + "/RunDisplayAlias").getValue<std::string>();
2359  //else
2360  // __MOUT_INFO__ << "FSM Link disconnected." << std::endl;
2361  }
2362  catch(std::runtime_error &e) { __MOUT_INFO__ << e.what() << std::endl; }
2363  catch(...) { __MOUT_ERR__ << "Unknown error. Should never happen." << std::endl; }
2364  }
2365  //else
2366  // __MOUT_INFO__ << "FSM Link disconnected." << std::endl;
2367 
2368  //__MOUT__ << "stateMachineRunAlias = " << stateMachineRunAlias << std::endl;
2369 
2370  xmldoc.addTextElementToData("stateMachineRunAlias", stateMachineRunAlias);
2372 
2373 
2374 
2375  if(theStateMachine_.getCurrentStateName() == "Running" ||
2376  theStateMachine_.getCurrentStateName() == "Paused")
2377  sprintf(tmp,"Current %s Number: %u",stateMachineRunAlias.c_str(),getNextRunNumber(activeStateMachineName_)-1);
2378  else
2379  sprintf(tmp,"Next %s Number: %u",stateMachineRunAlias.c_str(),getNextRunNumber(fsmName));
2380  xmldoc.addTextElementToData("run_number", tmp);
2381  }
2382  }
2383  else if(Command == "getErrorInStateMatchine")
2384  {
2385  xmldoc.addTextElementToData("FSM_Error", theStateMachine_.getErrorMessage());
2386  }
2387  else if(Command == "getDesktopIcons")
2388  {
2389 
2390  std::string iconFileName = ICON_FILE_NAME;
2391  std::ifstream iconFile;
2392  std::string iconList = "";
2393  std::string line;
2394  iconFile.open(iconFileName.c_str());
2395 
2396  if(!iconFile)
2397  {
2398  __MOUT__ << "Error opening file: "<< iconFileName << std::endl;
2399  system("pause");
2400  return;
2401  }
2402  if(iconFile.is_open())
2403  {
2404  __MOUT__ << "Opened File: " << iconFileName << std::endl;
2405  while(std::getline(iconFile, line))
2406  {
2407  iconList = line;
2408  }
2409  __MOUT__ << iconList << std::endl;
2410 
2411  //Close file
2412  iconFile.close();
2413  }
2414  xmldoc.addTextElementToData("iconList", iconList);
2415 
2416  }
2417  else if(Command == "launchConfig")
2418  {
2419  if(userPermissions != 255)
2420  {
2421  __MOUT__ << "Insufficient Permissions" << std::endl;
2422  }
2423  else
2424  {
2425  __MOUT__ << "Self-destruct." << std::endl;
2426  //FIXME system("StartOTS.sh");
2427  //system("pwd; source /$OTSDAQ_DIR/../otsdaq_demo/tools/quick-start.sh; source setupARTDAQOTS; source StartOTS.sh");
2428  }
2429  }
2430  else if(Command == "resetUserTooltips")
2431  {
2432  WebUsers::resetAllUserTooltips(theWebUsers_.getUsersUsername(uid));
2433  }
2434  else
2435  __MOUT__ << "Command Request, " << Command << ", not recognized." << std::endl;
2436 
2437  //__MOUT__ << "Made it" << std::endl;
2438 
2439  //return xml doc holding server response
2440  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true); //Note: allow white space need for error response
2441 
2442  //__MOUT__ << "done " << Command << std::endl;
2443 }
2444 
2445 //========================================================================================================================
2446 //xoap::supervisorGetUserInfo
2447 // get user info to external supervisors
2448 xoap::MessageReference Supervisor::supervisorGetUserInfo(
2449  xoap::MessageReference message)
2450 throw (xoap::exception::Exception)
2451 {
2452  SOAPParameters parameters;
2453  parameters.addParameter("CookieCode");
2454  receive(message, parameters);
2455  std::string cookieCode = parameters.getValue("CookieCode");
2456 
2457  std::string username, displayName;
2458  uint64_t activeSessionIndex;
2459 
2460  theWebUsers_.getUserInfoForCookie(cookieCode, &username, &displayName,
2461  &activeSessionIndex);
2462 
2463  //__MOUT__ << "username " << username << std::endl;
2464  //__MOUT__ << "displayName " << displayName << std::endl;
2465 
2466  //fill return parameters
2467  SOAPParameters retParameters;
2468  retParameters.addParameter("Username", username);
2469  retParameters.addParameter("DisplayName", displayName);
2470  char tmpStr[100];
2471  sprintf(tmpStr, "%lu", activeSessionIndex);
2472  retParameters.addParameter("ActiveSessionIndex", tmpStr);
2473 
2474  return SOAPUtilities::makeSOAPMessageReference("UserInfoResponse",
2475  retParameters);
2476 }
2477 
2478 //========================================================================================================================
2479 //xoap::supervisorCookieCheck
2480 // verify cookie
2481 xoap::MessageReference Supervisor::supervisorCookieCheck(xoap::MessageReference message)
2482 throw (xoap::exception::Exception)
2483 {
2484  //__MOUT__ << std::endl;
2485 
2486  //receive request parameters
2487  SOAPParameters parameters;
2488  parameters.addParameter("CookieCode");
2489  parameters.addParameter("RefreshOption");
2490  receive(message, parameters);
2491  std::string cookieCode = parameters.getValue("CookieCode");
2492  std::string refreshOption = parameters.getValue("RefreshOption"); //give external supervisors option to refresh cookie or not, "1" to refresh
2493 
2494  //If TRUE, cookie code is good, and refreshed code is in cookieCode, also pointers optionally for uint8_t userPermissions, uint64_t uid
2495  //Else, error message is returned in cookieCode
2496  uint8_t userPermissions = 0;
2497  std::string userWithLock = "";
2498  theWebUsers_.cookieCodeIsActiveForRequest(cookieCode, &userPermissions, 0,
2499  "0", refreshOption == "1", &userWithLock);
2500 
2501  //__MOUT__ << "userWithLock " << userWithLock << std::endl;
2502 
2503  //fill return parameters
2504  SOAPParameters retParameters;
2505  retParameters.addParameter("CookieCode", cookieCode);
2506  char tmp[5];
2507  sprintf(tmp, "%d", userPermissions);
2508  retParameters.addParameter("Permissions", tmp);
2509  retParameters.addParameter("UserWithLock", userWithLock);
2510 
2511  //__MOUT__ << std::endl;
2512 
2513  return SOAPUtilities::makeSOAPMessageReference("CookieResponse",
2514  retParameters);
2515 }
2516 
2517 //========================================================================================================================
2518 //xoap::supervisorGetActiveUsers
2519 // get display names for all active users
2520 xoap::MessageReference Supervisor::supervisorGetActiveUsers(
2521  xoap::MessageReference message)
2522 throw (xoap::exception::Exception)
2523 {
2524  __MOUT__ << std::endl;
2525 
2527  parameters("UserList", theWebUsers_.getActiveUsersString());
2528  return SOAPUtilities::makeSOAPMessageReference("ActiveUserResponse",
2529  parameters);
2530 }
2531 
2532 //========================================================================================================================
2533 //xoap::supervisorSystemMessage
2534 // receive a new system Message from a supervisor
2535 // ToUser wild card * is to all users
2536 xoap::MessageReference Supervisor::supervisorSystemMessage(
2537  xoap::MessageReference message)
2538 throw (xoap::exception::Exception)
2539 {
2540  SOAPParameters parameters;
2541  parameters.addParameter("ToUser");
2542  parameters.addParameter("Message");
2543  receive(message, parameters);
2544 
2545  __MOUT__ << "toUser: " << parameters.getValue("ToUser").substr(
2546  0, 10) << ", message: " << parameters.getValue("Message").substr(0,
2547  10) << std::endl;
2548 
2549  theSysMessenger_.addSysMsg(parameters.getValue("ToUser"),
2550  parameters.getValue("Message"));
2551  return SOAPUtilities::makeSOAPMessageReference("SystemMessageResponse");
2552 }
2553 
2554 //===================================================================================================================
2555 //xoap::supervisorSystemLogbookEntry
2556 // receive a new system Message from a supervisor
2557 // ToUser wild card * is to all users
2558 xoap::MessageReference Supervisor::supervisorSystemLogbookEntry(
2559  xoap::MessageReference message)
2560 throw (xoap::exception::Exception)
2561 {
2562  SOAPParameters parameters;
2563  parameters.addParameter("EntryText");
2564  receive(message, parameters);
2565 
2566  __MOUT__ << "EntryText: " << parameters.getValue("EntryText").substr(
2567  0, 10) << std::endl;
2568 
2569  makeSystemLogbookEntry(parameters.getValue("EntryText"));
2570 
2571  return SOAPUtilities::makeSOAPMessageReference("SystemLogbookResponse");
2572 }
2573 
2574 //===================================================================================================================
2575 //supervisorLastConfigGroupRequest
2576 // return the group name and key for the last state machine activity
2577 //
2578 // Note: same as OtsConfigurationWizardSupervisor::supervisorLastConfigGroupRequest
2579 xoap::MessageReference Supervisor::supervisorLastConfigGroupRequest(
2580  xoap::MessageReference message)
2581 throw (xoap::exception::Exception)
2582 {
2583  SOAPParameters parameters;
2584  parameters.addParameter("ActionOfLastGroup");
2585  receive(message, parameters);
2586 
2587  return Supervisor::lastConfigGroupRequestHandler(parameters);
2588 }
2589 
2590 //===================================================================================================================
2591 //xoap::lastConfigGroupRequestHandler
2592 // handles last config group request.
2593 // called by both:
2594 // Supervisor::supervisorLastConfigGroupRequest
2595 // OtsConfigurationWizardSupervisor::supervisorLastConfigGroupRequest
2596 xoap::MessageReference Supervisor::lastConfigGroupRequestHandler(
2597  const SOAPParameters &parameters)
2598 {
2599  std::string action = parameters.getValue("ActionOfLastGroup");
2600  __MOUT__ << "ActionOfLastGroup: " << action.substr(
2601  0, 10) << std::endl;
2602 
2603  std::string fileName = "";
2604  if(action == "Configured")
2605  fileName = FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE;
2606  else if(action == "Started")
2607  fileName = FSM_LAST_STARTED_GROUP_ALIAS_FILE;
2608  else
2609  {
2610  __MOUT_ERR__ << "Invalid last group action requested." << std::endl;
2611  return SOAPUtilities::makeSOAPMessageReference("LastConfigGroupResponseFailure");
2612  }
2613  std::string timeString;
2614  std::pair<std::string /*group name*/, ConfigurationGroupKey> theGroup =
2615  loadGroupNameAndKey(fileName,timeString);
2616 
2617  //fill return parameters
2618  SOAPParameters retParameters;
2619  retParameters.addParameter("GroupName", theGroup.first);
2620  retParameters.addParameter("GroupKey", theGroup.second.toString());
2621  retParameters.addParameter("GroupAction", action);
2622  retParameters.addParameter("GroupActionTime", timeString);
2623 
2624 
2625  return SOAPUtilities::makeSOAPMessageReference("LastConfigGroupResponse",
2626  retParameters);
2627 }
2628 
2629 //========================================================================================================================
2630 //getNextRunNumber
2631 //
2632 // If fsmName is passed, then get next run number for that FSM name
2633 // Else get next run number for the active FSM name, activeStateMachineName_
2634 //
2635 // Note: the FSM name is sanitized of special characters and used in the filename.
2636 unsigned int Supervisor::getNextRunNumber(const std::string &fsmNameIn)
2637 {
2638  std::string runNumberFileName = RUN_NUMBER_PATH + "/";
2639  std::string fsmName = fsmNameIn == ""?activeStateMachineName_:fsmNameIn;
2640  //prepend sanitized FSM name
2641  for(unsigned int i=0;i<fsmName.size();++i)
2642  if( (fsmName[i] >= 'a' && fsmName[i] <= 'z') ||
2643  (fsmName[i] >= 'A' && fsmName[i] <= 'Z') ||
2644  (fsmName[i] >= '0' && fsmName[i] <= '9'))
2645  runNumberFileName += fsmName[i];
2646  runNumberFileName += RUN_NUMBER_FILE_NAME;
2647  //__MOUT__ << "runNumberFileName: " << runNumberFileName << std::endl;
2648 
2649  std::ifstream runNumberFile(runNumberFileName.c_str());
2650  if (!runNumberFile.is_open())
2651  {
2652  __MOUT__ << "Can't open file: " << runNumberFileName << std::endl;
2653 
2654  __MOUT__ << "Creating file and setting Run Number to 1: " << runNumberFileName << std::endl;
2655  FILE *fp = fopen(runNumberFileName.c_str(),"w");
2656  fprintf(fp,"1");
2657  fclose(fp);
2658 
2659  runNumberFile.open(runNumberFileName.c_str());
2660  if(!runNumberFile.is_open())
2661  {
2662  __MOUT__ << "Can't create file: " << runNumberFileName << std::endl;
2663  throw std::runtime_error("Error.");
2664  }
2665  }
2666  std::string runNumberString;
2667  runNumberFile >> runNumberString;
2668  runNumberFile.close();
2669  return atoi(runNumberString.c_str());
2670 }
2671 
2672 //========================================================================================================================
2673 bool Supervisor::setNextRunNumber(unsigned int runNumber, const std::string &fsmNameIn)
2674 {
2675  std::string runNumberFileName = RUN_NUMBER_PATH + "/";
2676  std::string fsmName = fsmNameIn == ""?activeStateMachineName_:fsmNameIn;
2677  //prepend sanitized FSM name
2678  for(unsigned int i=0;i<fsmName.size();++i)
2679  if( (fsmName[i] >= 'a' && fsmName[i] <= 'z') ||
2680  (fsmName[i] >= 'A' && fsmName[i] <= 'Z') ||
2681  (fsmName[i] >= '0' && fsmName[i] <= '9'))
2682  runNumberFileName += fsmName[i];
2683  runNumberFileName += RUN_NUMBER_FILE_NAME;
2684  __MOUT__ << "runNumberFileName: " << runNumberFileName << std::endl;
2685 
2686  std::ofstream runNumberFile(runNumberFileName.c_str());
2687  if (!runNumberFile.is_open())
2688  {
2689  __MOUT__ << "Can't open file: " << runNumberFileName << std::endl;
2690  throw std::runtime_error("Error.");
2691  }
2692  std::stringstream runNumberStream;
2693  runNumberStream << runNumber;
2694  runNumberFile << runNumberStream.str().c_str();
2695  runNumberFile.close();
2696  return true;
2697 }
2698 
2699 //========================================================================================================================
2700 //loadGroupNameAndKey
2701 // loads group name and key (and time) from specified file
2702 // returns time string in returnedTimeString
2703 //
2704 // Note: this is static so the OtsConfigurationWizardSupervisor can call it
2705 std::pair<std::string /*group name*/,
2706  ConfigurationGroupKey> Supervisor::loadGroupNameAndKey(const std::string &fileName,
2707  std::string &returnedTimeString)
2708 {
2709  std::string fullPath = FSM_LAST_GROUP_ALIAS_PATH + "/" + fileName;
2710 
2711  FILE *groupFile = fopen(fullPath.c_str(),"r");
2712  if (!groupFile)
2713  {
2714  __MOUT__ << "Can't open file: " << fullPath << std::endl;
2715 
2716  __MOUT__ << "Returning empty groupName and key -1" << std::endl;
2717 
2718  return std::pair<std::string /*group name*/,
2719  ConfigurationGroupKey>("",ConfigurationGroupKey());
2720  }
2721 
2722  char line[500]; //assuming no group names longer than 500 chars
2723  //name and then key
2724  std::pair<std::string /*group name*/,
2725  ConfigurationGroupKey> theGroup;
2726 
2727  fgets(line,500,groupFile); //name
2728  theGroup.first = line;
2729 
2730  fgets(line,500,groupFile); //key
2731  int key;
2732  sscanf(line,"%d",&key);
2733  theGroup.second = key;
2734 
2735  fgets(line,500,groupFile); //time
2736  time_t timestamp;
2737  sscanf(line,"%ld",&timestamp); //type long int
2738  struct tm tmstruct;
2739  ::localtime_r(&timestamp, &tmstruct);
2740  ::strftime(line, 30, "%c %Z", &tmstruct);
2741  returnedTimeString = line;
2742  fclose(groupFile);
2743 
2744 
2745  __MOUT__ << "theGroup.first= " << theGroup.first <<
2746  " theGroup.second= " << theGroup.second << std::endl;
2747 
2748  return theGroup;
2749 }
2750 
2751 //========================================================================================================================
2752 void Supervisor::saveGroupNameAndKey(const std::pair<std::string /*group name*/,
2753  ConfigurationGroupKey> &theGroup,
2754  const std::string &fileName)
2755 {
2756  std::string fullPath = FSM_LAST_GROUP_ALIAS_PATH + "/" + fileName;
2757 
2758  std::ofstream groupFile(fullPath.c_str());
2759  if (!groupFile.is_open())
2760  {
2761  __SS__ << "Can't open file: " << fullPath << std::endl;
2762  __MOUT_ERR__ << "\n" << ss.str();
2763  throw std::runtime_error("Error.\n" + ss.str());
2764  }
2765  std::stringstream outss;
2766  outss << theGroup.first << "\n" << theGroup.second << "\n" << time(0);
2767  groupFile << outss.str().c_str();
2768  groupFile.close();
2769 }
2770 
2771 
2772 
2774 
2775 
2778 //void Supervisor::infoRequest(xgi::Input * in, xgi::Output * out ) throw (xgi::exception::Exception)
2779 //{
2780 // __MOUT__ << __LINE__ << std::endl << std::endl;
2781 // cgicc::Cgicc cgi(in);
2782 // std::string Command=cgi.getElement("RequestType")->getValue();
2783 //
2784 // if (Command=="FEWList")
2785 // {
2786 // *out << "<FEWList>" << std::endl;
2787 // for (std::set<xdaq::ApplicationDescriptor*>::iterator pxFESupervisorsIt=pxFESupervisors_.begin(); pxFESupervisorsIt!=pxFESupervisors_.end(); pxFESupervisorsIt++)
2788 // {
2789 // *out << "<FEWInterface id='1' alias='FPIX Disk 1' type='OtsUDPHardware'>" << std::endl
2790 // << "<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>" << std::endl
2791 // << "<circle cx='100' cy='50' r='40' stroke='black' stroke-width='2' fill='red' />" << std::endl
2792 // << "</svg>" << std::endl
2793 // << "</FEWInterface>" << std::endl;
2794 // *out << "<FEWInterface id='2' alias='FPIX Disk 2' type='OtsUDPHardware'>" << std::endl
2795 // << "<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>" << std::endl
2796 // << "<circle cx='100' cy='50' r='40' stroke='black' stroke-width='2' fill='red' />" << std::endl
2797 // << "</svg>" << std::endl
2798 // << "</FEWInterface>" << std::endl;
2799 // }
2800 // *out << "</FEWList>" << std::endl;
2801 // }
2802 //}
2803 //========================================================================================================================
2804