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