otsdaq  3.06.00
FESupervisor.cc
1 #include "otsdaq/CoreSupervisors/FESupervisor.h"
2 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
3 #include "otsdaq/FECore/FEVInterfacesManager.h"
4 #include "otsdaq/TablePlugins/ARTDAQTableBase/ARTDAQTableBase.h"
5 
6 #include "artdaq/DAQdata/Globals.hh" // instantiates artdaq::Globals::metricMan_
7 
8 #include <cstring>
9 #include <iostream>
10 #include <string>
11 
12 #include "artdaq-core/Utilities/ExceptionHandler.hh" /*for artdaq::ExceptionHandler*/
13 
36 using namespace ots;
37 
38 XDAQ_INSTANTIATOR_IMPL(FESupervisor)
39 
40 //==============================================================================
41 FESupervisor::FESupervisor(xdaq::ApplicationStub* stub)
42  : CoreSupervisorBase(stub)
43  , dp_context_{1} // 1 I/O thread – sufficient for most tests
44  , dp_socket_{dp_context_, zmq::socket_type::pub}
45 {
46  __SUP_COUT__ << "Constructing..." << __E__;
47 
48  xoap::bind(this,
49  &FESupervisor::macroMakerSupervisorRequest,
50  "MacroMakerSupervisorRequest",
51  XDAQ_NS_URI);
52 
53  xoap::bind(
54  this, &FESupervisor::workLoopStatusRequest, "WorkLoopStatusRequest", XDAQ_NS_URI);
55 
56  xoap::bind(this,
57  &FESupervisor::frontEndCommunicationRequest,
58  "FECommunication",
59  XDAQ_NS_URI);
60 
61  std::string dataPublishingEndpoint;
62  try
63  {
64  dataPublishingEndpoint = getSupervisorProperty(
65  "data_publishing_endpoint"); //like "tcp://0.0.0.0:$((OTS_MAIN_PORT-2))"
66  }
67  catch(const std::runtime_error& e)
68  {
69  __SUP_COUT__ << "Data publishing property 'data_publishing_endpoint' not set. "
70  "Defaulting to data publishing disabled."
71  << __E__;
72 
73  try
74  {
75  dataPublishingEndpoint = __ENV__(
76  "DATA_PUBLISHING_ENDPOINT"); //like "tcp://0.0.0.0:$((OTS_MAIN_PORT-2))"
77  }
78  catch(const std::runtime_error& e)
79  {
80  __SUP_COUT__
81  << "Data publishing environment variable 'DATA_PUBLISHING_ENDPOINT' "
82  "not set. Defaulting to data publishing disabled."
83  << __E__;
84  }
85  }
86  __SUP_COUT_INFO__ << "dataPublishingEndpoint = " << dataPublishingEndpoint << __E__;
87 
88  if(dataPublishingEndpoint.size())
89  {
90  __SUP_COUT__ << "Initializing data publishing to endpoint '"
91  << dataPublishingEndpoint << "'..." << __E__;
92 
93  initDataPublishing(dataPublishingEndpoint,
94  getSupervisorProperty("data_publishing_topic", ""));
95  }
96 
97  try
98  {
99  CoreSupervisorBase::theStateMachineImplementation_.push_back(
101  CorePropertySupervisorBase::getContextTreeNode(),
102  CorePropertySupervisorBase::getSupervisorConfigurationPath()));
103  }
104  catch(...)
105  {
106  if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
107  {
108  __SUP_COUT_WARN__ << "Error caught constructing FE Interface Manager. In "
109  "Macro Maker mode, the input fhicl defines the "
110  "configuration tree, make sure you specified a valid "
111  "fcl file path."
112  << __E__;
113  try
114  {
115  throw;
116  }
117  catch(const std::runtime_error& e)
118  {
119  __SUP_COUT_WARN__ << e.what() << __E__;
120  throw;
121  }
122  }
123  throw;
124  }
125 
126  extractFEInterfacesManager();
127 
128  __SUP_COUT__ << "Constructed." << __E__;
129 
130  if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
131  {
132  __SUP_COUT_INFO__ << "Macro Maker mode, so configuring at startup!" << __E__;
133  if(!theFEInterfacesManager_)
134  {
135  __SUP_SS__ << "Missing FE Interface manager!" << __E__;
136  __SUP_SS_THROW__;
137  }
138 
139  // copied from CoreSupervisorBase::transitionConfiguring()
140 
141  // Now that the configuration manager has all the necessary configurations,
142  // create all objects that depend on the configuration (the first iteration)
143 
144  try
145  {
146  __SUP_COUT__ << "Configuring all state machine implementations..." << __E__;
147  __SUP_COUTV__(stateMachinesIterationDone_.size());
148  preStateMachineExecutionLoop();
149  __SUP_COUTV__(stateMachinesIterationDone_.size());
150  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
151  {
152  __SUP_COUT__ << "Configuring state machine i " << i << __E__;
153 
154  // if one state machine is doing a sub-iteration, then target that one
155  if(subIterationWorkStateMachineIndex_ != (unsigned int)-1 &&
156  i != subIterationWorkStateMachineIndex_)
157  continue; // skip those not in the sub-iteration
158 
159  if(stateMachinesIterationDone_[i])
160  continue; // skip state machines already done
161 
162  preStateMachineExecution(i);
163  theStateMachineImplementation_[i]->parentSupervisor_ =
164  this; // for backwards compatibility, kept out of configure
165  // parameters
166  theStateMachineImplementation_[i]->configure(); // e.g. for FESupervisor,
167  // this is configure of
168  // FEVInterfacesManager
169  postStateMachineExecution(i);
170  }
171  postStateMachineExecutionLoop();
172 
173  //ony indicate alive after configure
174  CorePropertySupervisorBase::indicateOtsAlive(0);
175  }
176  catch(const std::runtime_error& e)
177  {
178  __SUP_SS__ << "Error was caught while configuring: " << e.what() << __E__;
179  __SUP_COUT_ERR__ << "\n" << ss.str();
180  throw;
181  }
182  catch(...)
183  {
184  __SUP_SS__
185  << "Unknown error was caught while configuring. Please checked the logs."
186  << __E__;
187  try
188  {
189  throw;
190  } //one more try to printout extra info
191  catch(const std::exception& e)
192  {
193  ss << "Exception message: " << e.what();
194  }
195  catch(...)
196  {
197  }
198  __SUP_COUT_ERR__ << "\n" << ss.str();
199  throw;
200  }
201  } // end Macro Maker mode initial configure
202 } // end constructor
203 
204 //==============================================================================
205 FESupervisor::~FESupervisor(void)
206 {
207  __SUP_COUT__ << "Destroying..." << __E__;
208  // theStateMachineImplementation_ is reset and the object it points to deleted in
209  // ~CoreSupervisorBase()
210 
211  // Destructor must never throw, so we swallow any zmq_error.
212  try
213  {
215  }
216  catch(...)
217  {
218  // nothing – best‑effort cleanup.
219  }
220 
221  artdaq::Globals::CleanUpGlobals(); // destruct metricManager (among other things)
222 
223  __SUP_COUT__ << "Destructed." << __E__;
224 } // end destructor
225 
226 //==============================================================================
227 xoap::MessageReference FESupervisor::frontEndCommunicationRequest(
228  xoap::MessageReference message)
229 try
230 {
231  // LORE__SUP_COUT__ << "FE Request received: " << SOAPUtilities::translate(message) << __E__;
232 
233  if(!theFEInterfacesManager_)
234  {
235  __SUP_SS__ << "No FE Interface Manager!" << __E__;
236  __SUP_SS_THROW__;
237  }
238  SOAPParameters typeParameter, rxParameters; // params for xoap to recv
239  typeParameter.addParameter("type");
240  SOAPUtilities::receive(message, typeParameter);
241 
242  std::string type = typeParameter.getValue("type");
243 
244  // types
245  // feSend
246  // feMacro
247  // feMacroMultiDimensionalStart
248  // macroMultiDimensionalStart
249  // feMacroMultiDimensionalCheck
250  // macroMultiDimensionalCheck
251 
252  rxParameters.addParameter("requester");
253  rxParameters.addParameter("targetInterfaceID");
254 
255  if(type == "feSend")
256  {
257  __SUP_COUTV__(type);
258 
259  rxParameters.addParameter("value");
260  SOAPUtilities::receive(message, rxParameters);
261 
262  std::string requester = rxParameters.getValue("requester");
263  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
264  std::string value = rxParameters.getValue("value");
265 
266  __SUP_COUTV__(requester);
267  __SUP_COUTV__(targetInterfaceID);
268  __SUP_COUTV__(value);
269 
270  // test that the interface exists
271  theFEInterfacesManager_->getFEInterface(targetInterfaceID);
272 
273  // mutex scope
274  {
275  std::lock_guard<std::mutex> lock(
276  theFEInterfacesManager_->frontEndCommunicationReceiveMutex_);
277 
278  theFEInterfacesManager_
279  ->frontEndCommunicationReceiveBuffer_[targetInterfaceID][requester]
280  .emplace(value);
281 
282  __SUP_COUT__ << "Number of target interface ID '" << targetInterfaceID
283  << "' buffers: "
284  << theFEInterfacesManager_
285  ->frontEndCommunicationReceiveBuffer_[targetInterfaceID]
286  .size()
287  << __E__;
288  __SUP_COUT__
289  << "Number of source interface ID '" << requester << "' values received: "
290  << theFEInterfacesManager_
291  ->frontEndCommunicationReceiveBuffer_[targetInterfaceID][requester]
292  .size()
293  << __E__;
294  }
295  return SOAPUtilities::makeSOAPMessageReference("Received");
296  } // end type feSend
297  else if(type == "feMacro")
298  {
299  __SUP_COUTV__(type);
300 
301  rxParameters.addParameter("feMacroName");
302  rxParameters.addParameter("inputArgs");
303 
304  SOAPUtilities::receive(message, rxParameters);
305 
306  std::string requester = rxParameters.getValue("requester");
307  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
308  std::string feMacroName = rxParameters.getValue("feMacroName");
309  std::string inputArgs = rxParameters.getValue("inputArgs");
310 
311  __SUP_COUTV__(requester);
312  __SUP_COUTV__(targetInterfaceID);
313  __SUP_COUTV__(feMacroName);
314  __SUP_COUTV__(inputArgs);
315 
316  std::string outputArgs;
317  try
318  {
319  theFEInterfacesManager_->runFEMacroByFE(
320  requester, targetInterfaceID, feMacroName, inputArgs, outputArgs);
321  }
322  catch(std::runtime_error& e)
323  {
324  __SUP_SS__ << "In Supervisor with LID="
325  << getApplicationDescriptor()->getLocalId()
326  << " the FE Macro named '" << feMacroName << "' with target FE '"
327  << targetInterfaceID << "' failed. Here is the error:\n\n"
328  << e.what() << __E__;
329  __SUP_SS_THROW__;
330  }
331  catch(...)
332  {
333  __SUP_SS__ << "In Supervisor with LID="
334  << getApplicationDescriptor()->getLocalId()
335  << " the FE Macro named '" << feMacroName << "' with target FE '"
336  << targetInterfaceID << "' failed due to an unknown error."
337  << __E__;
338  try
339  {
340  throw;
341  } //one more try to printout extra info
342  catch(const std::exception& e)
343  {
344  ss << "Exception message: " << e.what();
345  }
346  catch(...)
347  {
348  }
349  __SUP_SS_THROW__;
350  }
351 
352  __SUP_COUTV__(outputArgs);
353 
354  xoap::MessageReference replyMessage =
355  SOAPUtilities::makeSOAPMessageReference("feMacrosResponse");
356  SOAPParameters txParameters;
357  txParameters.addParameter("requester", requester);
358  txParameters.addParameter("targetInterfaceID", targetInterfaceID);
359  txParameters.addParameter("feMacroName", feMacroName);
360  txParameters.addParameter("outputArgs", outputArgs);
361  SOAPUtilities::addParameters(replyMessage, txParameters);
362 
363  __SUP_COUT__ << "Sending FE macro result: "
364  << SOAPUtilities::translate(replyMessage) << __E__;
365 
366  return replyMessage;
367  } // end type feMacro
368  else if(type == "feMacroMultiDimensionalStart" || // from iterator
369  type == "macroMultiDimensionalStart") // from iterator
370  {
371  __SUP_COUTV__(type);
372 
373  if(type[0] == 'm')
374  {
375  rxParameters.addParameter("macroString");
376  rxParameters.addParameter("macroName");
377  }
378  else
379  rxParameters.addParameter("feMacroName");
380 
381  rxParameters.addParameter("enableSavingOutput");
382  rxParameters.addParameter("outputFilePath");
383  rxParameters.addParameter("outputFileRadix");
384  rxParameters.addParameter("inputArgs");
385 
386  SOAPUtilities::receive(message, rxParameters);
387 
388  std::string requester = rxParameters.getValue("requester");
389  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
390  std::string macroName, macroString;
391  if(type[0] == 'm')
392  {
393  macroName = rxParameters.getValue("macroName");
394  macroString = rxParameters.getValue("macroString");
395  __SUP_COUTV__(macroString);
396  }
397  else
398  macroName = rxParameters.getValue("feMacroName");
399  bool enableSavingOutput = rxParameters.getValue("enableSavingOutput") == "1";
400  std::string outputFilePath = rxParameters.getValue("outputFilePath");
401  std::string outputFileRadix = rxParameters.getValue("outputFileRadix");
402  std::string inputArgs = rxParameters.getValue("inputArgs");
403 
404  __SUP_COUTV__(requester);
405  __SUP_COUTV__(targetInterfaceID);
406  __SUP_COUTV__(macroName);
407  __SUP_COUTV__(enableSavingOutput);
408  __SUP_COUTV__(outputFilePath);
409  __SUP_COUTV__(outputFileRadix);
410  __SUP_COUTV__(inputArgs);
411 
412  if(type[0] == 'm') // start Macro
413  {
414  try
415  {
416  theFEInterfacesManager_->startMacroMultiDimensional(requester,
417  targetInterfaceID,
418  macroName,
419  macroString,
420  enableSavingOutput,
421  outputFilePath,
422  outputFileRadix,
423  inputArgs);
424  }
425  catch(std::runtime_error& e)
426  {
427  __SUP_SS__ << "In Supervisor with LID="
428  << getApplicationDescriptor()->getLocalId()
429  << " the Macro named '" << macroName << "' with target FE '"
430  << targetInterfaceID
431  << "' failed to start multi-dimensional launch. "
432  << "Here is the error:\n\n"
433  << e.what() << __E__;
434  __SUP_SS_THROW__;
435  }
436  catch(...)
437  {
438  __SUP_SS__ << "In Supervisor with LID="
439  << getApplicationDescriptor()->getLocalId()
440  << " the Macro named '" << macroName << "' with target FE '"
441  << targetInterfaceID
442  << "' failed to start multi-dimensional launch "
443  << "due to an unknown error." << __E__;
444  try
445  {
446  throw;
447  } //one more try to printout extra info
448  catch(const std::exception& e)
449  {
450  ss << "Exception message: " << e.what();
451  }
452  catch(...)
453  {
454  }
455  __SUP_SS_THROW__;
456  }
457  }
458  else // start FE Macro
459  {
460  try
461  {
462  theFEInterfacesManager_->startFEMacroMultiDimensional(requester,
463  targetInterfaceID,
464  macroName,
465  enableSavingOutput,
466  outputFilePath,
467  outputFileRadix,
468  inputArgs);
469  }
470  catch(std::runtime_error& e)
471  {
472  __SUP_SS__ << "In Supervisor with LID="
473  << getApplicationDescriptor()->getLocalId()
474  << " the FE Macro named '" << macroName << "' with target FE '"
475  << targetInterfaceID
476  << "' failed to start multi-dimensional launch. "
477  << "Here is the error:\n\n"
478  << e.what() << __E__;
479  __SUP_SS_THROW__;
480  }
481  catch(...)
482  {
483  __SUP_SS__ << "In Supervisor with LID="
484  << getApplicationDescriptor()->getLocalId()
485  << " the FE Macro named '" << macroName << "' with target FE '"
486  << targetInterfaceID
487  << "' failed to start multi-dimensional launch "
488  << "due to an unknown error." << __E__;
489  try
490  {
491  throw;
492  } //one more try to printout extra info
493  catch(const std::exception& e)
494  {
495  ss << "Exception message: " << e.what();
496  }
497  catch(...)
498  {
499  }
500  __SUP_SS_THROW__;
501  }
502  }
503 
504  xoap::MessageReference replyMessage =
505  SOAPUtilities::makeSOAPMessageReference(type + "Done");
506  SOAPParameters txParameters;
507  // txParameters.addParameter("started", "1");
508  SOAPUtilities::addParameters(replyMessage, txParameters);
509 
510  __SUP_COUT__ << "Sending FE macro result: "
511  << SOAPUtilities::translate(replyMessage) << __E__;
512 
513  return replyMessage;
514  } // end type (fe)MacroMultiDimensionalStart
515  else if(type == "feMacroMultiDimensionalCheck" || // from iterator
516  type == "macroMultiDimensionalCheck")
517  {
518  // LORE__SUP_COUTV__(type);
519  if(type[0] == 'm')
520  rxParameters.addParameter("macroName");
521  else
522  rxParameters.addParameter("feMacroName");
523  rxParameters.addParameter("targetInterfaceID");
524 
525  SOAPUtilities::receive(message, rxParameters);
526 
527  std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID");
528  std::string macroName;
529  if(type[0] == 'm')
530  macroName = rxParameters.getValue("macroName");
531  else
532  macroName = rxParameters.getValue("feMacroName");
533 
534  // LORE__SUP_COUTV__(targetInterfaceID);
535  // LORE__SUP_COUTV__(macroName);
536 
537  bool done = false;
538  try
539  {
540  done = theFEInterfacesManager_->checkMacroMultiDimensional(targetInterfaceID,
541  macroName);
542  }
543  catch(std::runtime_error& e)
544  {
545  __SUP_SS__ << "In Supervisor with LID="
546  << getApplicationDescriptor()->getLocalId()
547  << " the FE Macro named '" << macroName << "' with target FE '"
548  << targetInterfaceID
549  << "' failed to check multi-dimensional launch. "
550  << "Here is the error:\n\n"
551  << e.what() << __E__;
552  __SUP_SS_THROW__;
553  }
554  catch(...)
555  {
556  __SUP_SS__ << "In Supervisor with LID="
557  << getApplicationDescriptor()->getLocalId()
558  << " the FE Macro named '" << macroName << "' with target FE '"
559  << targetInterfaceID
560  << "' failed to check multi-dimensional launch "
561  << "due to an unknown error." << __E__;
562  try
563  {
564  throw;
565  } //one more try to printout extra info
566  catch(const std::exception& e)
567  {
568  ss << "Exception message: " << e.what();
569  }
570  catch(...)
571  {
572  }
573  __SUP_SS_THROW__;
574  }
575 
576  xoap::MessageReference replyMessage =
577  SOAPUtilities::makeSOAPMessageReference(type + "Done");
578  SOAPParameters txParameters;
579  txParameters.addParameter("Done", done ? "1" : "0");
580  SOAPUtilities::addParameters(replyMessage, txParameters);
581 
582  // LORE__SUP_COUT__ << "Sending FE macro result: " << SOAPUtilities::translate(replyMessage) << __E__;
583 
584  return replyMessage;
585  } // end type (fe)MacroMultiDimensionalCheck
586  else
587  {
588  __SUP_SS__ << "Unrecognized FE Communication type: " << type << __E__;
589  __SUP_SS_THROW__;
590  }
591 }
592 catch(const std::runtime_error& e)
593 {
594  __SUP_SS__ << "Error encountered processing FE communication request: " << e.what()
595  << __E__;
596  __SUP_COUT_ERR__ << ss.str();
597 
598  SOAPParameters parameters;
599  parameters.addParameter("Error", ss.str());
600  return SOAPUtilities::makeSOAPMessageReference(
601  supervisorClassNoNamespace_ + "FailFECommunicationRequest", parameters);
602 }
603 catch(...)
604 {
605  __SUP_SS__ << "Unknown error encountered processing FE communication request."
606  << __E__;
607  try
608  {
609  throw;
610  } //one more try to printout extra info
611  catch(const std::exception& e)
612  {
613  ss << "Exception message: " << e.what();
614  }
615  catch(...)
616  {
617  }
618  __SUP_COUT_ERR__ << ss.str();
619 
620  SOAPParameters parameters;
621  parameters.addParameter("Error", ss.str());
622  return SOAPUtilities::makeSOAPMessageReference(
623  supervisorClassNoNamespace_ + "FailFECommunicationRequest", parameters);
624 } // end frontEndCommunicationRequest()
625 
626 //==============================================================================
634  xoap::MessageReference message)
635 {
636  __SUP_COUT__ << "$$$$$$$$$$$$$$$$$" << __E__;
637 
638  // receive request parameters
639  SOAPParameters parameters;
640  parameters.addParameter("Request");
641 
642  __SUP_COUT__ << "Received Macro Maker message: " << SOAPUtilities::translate(message)
643  << __E__;
644 
645  SOAPUtilities::receive(message, parameters);
646  std::string request = parameters.getValue("Request");
647 
648  __SUP_COUT__ << "request: " << request << __E__;
649 
650  // request types:
651  // GetInterfaces
652  // UniversalWrite
653  // UniversalRead
654  // GetInterfaceMacros
655  // RunInterfaceMacro
656  // RunMacroMakerMacro
657 
658  SOAPParameters retParameters;
659 
660  try
661  {
662  if(request == "GetInterfaces")
663  {
664  if(theFEInterfacesManager_)
665  retParameters.addParameter(
666  "FEList",
667  theFEInterfacesManager_->getFEListString(
668  std::to_string(getApplicationDescriptor()->getLocalId())));
669  else // if no FE interfaces, return empty string
670  retParameters.addParameter("FEList", "");
671 
672  // if errors in state machine, send also
673  if(theStateMachine_.getErrorMessage() != "")
674  retParameters.addParameter("frontEndError",
675  theStateMachine_.getErrorMessage());
676 
677  return SOAPUtilities::makeSOAPMessageReference(
678  supervisorClassNoNamespace_ + "Response", retParameters);
679  }
680  else if(request == "UniversalWrite")
681  {
682  if(!theFEInterfacesManager_)
683  {
684  __SUP_SS__ << "No FE Interface Manager! Are you configured?" << __E__;
685  __SUP_SS_THROW__;
686  }
687  // params for running macros
688  SOAPParameters requestParameters;
689  requestParameters.addParameter("InterfaceID");
690  requestParameters.addParameter("Address");
691  requestParameters.addParameter("Data");
692  SOAPUtilities::receive(message, requestParameters);
693  std::string interfaceID = requestParameters.getValue("InterfaceID");
694  std::string addressStr = requestParameters.getValue("Address");
695  std::string dataStr = requestParameters.getValue("Data");
696 
697  __SUP_COUT__ << "Address: " << addressStr << " Data: " << dataStr
698  << " InterfaceID: " << interfaceID << __E__;
699 
700  // parameters interface index!
701  // unsigned int index = stoi(indexStr); // As long as the supervisor has only
702  // one interface, this index will remain 0?
703 
704  __SUP_COUT__
705  << "theFEInterfacesManager_->getInterfaceUniversalAddressSize(index) "
706  << theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID)
707  << __E__;
708  __SUP_COUT__
709  << "theFEInterfacesManager_->getInterfaceUniversalDataSize(index) "
710  << theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID)
711  << __E__;
712 
713  // Converting std::string to char*
714  // char address
715 
716  char tmpHex[3]; // for use converting hex to binary
717  tmpHex[2] = '\0';
718 
719  __SUP_COUT__ << "Translating address: ";
720 
721  std::string addressTmp;
722  addressTmp.reserve(
723  theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID));
724  char* address = &addressTmp[0];
725 
726  if(addressStr.size() % 2) // if odd, make even
727  addressStr = "0" + addressStr;
728  unsigned int i = 0;
729  for(; i < addressStr.size() &&
730  i / 2 < theFEInterfacesManager_->getInterfaceUniversalAddressSize(
731  interfaceID);
732  i += 2)
733  {
734  tmpHex[0] = addressStr[addressStr.size() - 1 - i - 1];
735  tmpHex[1] = addressStr[addressStr.size() - 1 - i];
736  sscanf(tmpHex, "%hhX", (unsigned char*)&address[i / 2]);
737  printf("%2.2X", (unsigned char)address[i / 2]);
738  }
739  // finish and fill with 0s
740  for(; i / 2 <
741  theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID);
742  i += 2)
743  {
744  address[i / 2] = 0;
745  printf("%2.2X", (unsigned char)address[i / 2]);
746  }
747 
748  std::cout << __E__;
749 
750  __SUP_COUT__ << "Translating data: ";
751 
752  std::string dataTmp;
753  dataTmp.reserve(
754  theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID));
755  char* data = &dataTmp[0];
756 
757  if(dataStr.size() % 2) // if odd, make even
758  dataStr = "0" + dataStr;
759 
760  i = 0;
761  for(; i < dataStr.size() &&
762  i / 2 <
763  theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID);
764  i += 2)
765  {
766  tmpHex[0] = dataStr[dataStr.size() - 1 - i - 1];
767  tmpHex[1] = dataStr[dataStr.size() - 1 - i];
768  sscanf(tmpHex, "%hhX", (unsigned char*)&data[i / 2]);
769  printf("%2.2X", (unsigned char)data[i / 2]);
770  }
771  // finish and fill with 0s
772  for(; i / 2 <
773  theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID);
774  i += 2)
775  {
776  data[i / 2] = 0;
777  printf("%2.2X", (unsigned char)data[i / 2]);
778  }
779 
780  std::cout << __E__;
781 
782  // char* address = new char[addressStr.size() + 1];
783  // std::copy(addressStr.begin(), addressStr.end(), address);
784  // address[addressStr.size()] = '\0';
785  // char* data = new char[dataStr.size() + 1];
786  // std::copy(dataStr.begin(), dataStr.end(), data);
787  // data[dataStr.size()] = '\0';
788 
789  theFEInterfacesManager_->universalWrite(interfaceID, address, data);
790 
791  // delete[] address;
792  // delete[] data;
793 
794  return SOAPUtilities::makeSOAPMessageReference(
795  supervisorClassNoNamespace_ + "DataWritten", retParameters);
796  }
797  else if(request == "UniversalRead")
798  {
799  if(!theFEInterfacesManager_)
800  {
801  __SUP_SS__ << "No FE Interface Manager! Are you configured?" << __E__;
802  __SUP_SS_THROW__;
803  }
804 
805  // params for running macros
806  SOAPParameters requestParameters;
807  requestParameters.addParameter("InterfaceID");
808  requestParameters.addParameter("Address");
809  SOAPUtilities::receive(message, requestParameters);
810  std::string interfaceID = requestParameters.getValue("InterfaceID");
811  std::string addressStr = requestParameters.getValue("Address");
812 
813  __SUP_COUT__ << "Address: " << addressStr << " InterfaceID: " << interfaceID
814  << __E__;
815 
816  // parameters interface index!
817  // parameter address and data
818  // unsigned int index = stoi(indexStr); // As long as the supervisor has only
819  // one interface, this index will remain 0?
820 
821  __SUP_COUT__
822  << "theFEInterfacesManager_->getInterfaceUniversalAddressSize(index) "
823  << theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID)
824  << __E__;
825  __SUP_COUT__
826  << "theFEInterfacesManager_->getInterfaceUniversalDataSize(index) "
827  << theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID)
828  << __E__;
829 
830  char tmpHex[3]; // for use converting hex to binary
831  tmpHex[2] = '\0';
832 
833  __SUP_COUT__ << "Translating address: ";
834 
835  std::string addressTmp;
836  addressTmp.reserve(
837  theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID));
838  char* address = &addressTmp[0];
839 
840  if(addressStr.size() % 2) // if odd, make even
841  addressStr = "0" + addressStr;
842 
843  unsigned int i = 0;
844  for(; i < addressStr.size() &&
845  i / 2 < theFEInterfacesManager_->getInterfaceUniversalAddressSize(
846  interfaceID);
847  i += 2)
848  {
849  tmpHex[0] = addressStr[addressStr.size() - 1 - i - 1];
850  tmpHex[1] = addressStr[addressStr.size() - 1 - i];
851  sscanf(tmpHex, "%hhX", (unsigned char*)&address[i / 2]);
852  printf("%2.2X", (unsigned char)address[i / 2]);
853  }
854  // finish and fill with 0s
855  for(; i / 2 <
856  theFEInterfacesManager_->getInterfaceUniversalAddressSize(interfaceID);
857  i += 2)
858  {
859  address[i / 2] = 0;
860  printf("%2.2X", (unsigned char)address[i / 2]);
861  }
862 
863  std::cout << __E__;
864 
865  unsigned int dataSz =
866  theFEInterfacesManager_->getInterfaceUniversalDataSize(interfaceID);
867  std::string dataStr;
868  dataStr.resize(dataSz);
869  char* data = &dataStr[0];
870 
871  // std::string result =
872  // theFEInterfacesManager_->universalRead(index,address,data);
873  // __SUP_COUT__<< result << __E__ << __E__;
874 
875  try
876  {
877  theFEInterfacesManager_->universalRead(interfaceID, address, data);
878  }
879  catch(const std::runtime_error& e)
880  {
881  // do not allow read exception to crash everything when a macromaker
882  // command
883  __SUP_COUT_ERR__ << "Exception caught during read: " << e.what() << __E__;
884  retParameters.addParameter("dataResult", "Time Out Error");
885  return SOAPUtilities::makeSOAPMessageReference(
886  supervisorClassNoNamespace_ + "aa", retParameters);
887  }
888  catch(...)
889  {
890  // do not allow read exception to crash everything when a macromaker
891  // command
892  __SUP_COUT_ERR__ << "Exception caught during read." << __E__;
893  retParameters.addParameter("dataResult", "Time Out Error");
894  return SOAPUtilities::makeSOAPMessageReference(
895  supervisorClassNoNamespace_ + "aa", retParameters);
896  }
897 
898  // if dataSz is less than 8 show what the unsigned number would be
899  if(dataSz <= 8)
900  {
901  std::string str8(data);
902  str8.resize(8);
903  __SUP_COUT__ << "decResult[" << dataSz
904  << " bytes]: " << *((unsigned long long*)(&str8[0]))
905  << __E__;
906  }
907 
908  std::string hexResultStr;
909  hexResultStr.reserve(dataSz * 2 + 1);
910  char* hexResult = &hexResultStr[0];
911  // go through each byte and convert it to hex value (i.e. 2 0-F chars)
912  // go backwards through source data since should be provided in host order
913  // (i.e. a cast to unsigned long long should acquire expected value)
914  for(unsigned int i = 0; i < dataSz; ++i)
915  {
916  sprintf(&hexResult[i * 2], "%2.2X", (unsigned char)data[dataSz - 1 - i]);
917  }
918 
919  __SUP_COUT__ << "hexResult[" << strlen(hexResult)
920  << " nibbles]: " << std::string(hexResult) << __E__;
921 
922  retParameters.addParameter("dataResult", hexResult);
923  return SOAPUtilities::makeSOAPMessageReference(
924  supervisorClassNoNamespace_ + "aa", retParameters);
925  }
926  else if(request == "GetInterfaceMacros")
927  {
928  if(theFEInterfacesManager_)
929  {
930  __SUP_COUT__ << "Getting FE Macros from FE Interface Manager..." << __E__;
931  retParameters.addParameter(
932  "FEMacros",
933  theFEInterfacesManager_->getFEMacrosString(
934  CorePropertySupervisorBase::getSupervisorUID(),
935  std::to_string(CoreSupervisorBase::getSupervisorLID())));
936  }
937  else
938  {
939  __SUP_COUT__ << "No FE Macros because there is no FE Interface Manager..."
940  << __E__;
941  retParameters.addParameter("FEMacros", "");
942  }
943 
944  return SOAPUtilities::makeSOAPMessageReference(
945  supervisorClassNoNamespace_ + "Response", retParameters);
946  }
947  else if(request == "RunInterfaceMacro")
948  {
949  if(!theFEInterfacesManager_)
950  {
951  __SUP_SS__ << "Missing FE Interface Manager! Are you configured?"
952  << __E__;
953  __SUP_SS_THROW__;
954  }
955 
956  // params for running macros
957  SOAPParameters requestParameters;
958  requestParameters.addParameter("feMacroName");
959  requestParameters.addParameter("inputArgs");
960  requestParameters.addParameter("outputArgs");
961  requestParameters.addParameter("InterfaceID");
962  requestParameters.addParameter("userPermissions");
963  SOAPUtilities::receive(message, requestParameters);
964  std::string interfaceID = requestParameters.getValue("InterfaceID");
965  std::string feMacroName = requestParameters.getValue("feMacroName");
966  std::string inputArgs = requestParameters.getValue("inputArgs");
967  std::string outputArgs = requestParameters.getValue("outputArgs");
968  std::string userPermissions = requestParameters.getValue("userPermissions");
969 
970  // check user permission
971  // userPermissions = "allUsers:1";
972  // userPermissions = "allUsers:1 & TDAQ:255";
973  __COUTV__(userPermissions);
974  std::map<std::string, WebUsers::permissionLevel_t> userPermissionLevelsMap;
976  userPermissions, userPermissionLevelsMap);
977  __COUTV__(StringMacros::mapToString(userPermissionLevelsMap));
978 
979  // outputArgs must be filled with the proper argument names
980  // and then the response output values will be returned in the string.
981  try
982  {
983  // check for interfaceID
984  FEVInterface* fe = theFEInterfacesManager_->getFEInterfaceP(interfaceID);
985 
986  // have pointer to virtual FEInterface, find Macro structure
987  auto FEMacroIt = fe->getMapOfFEMacroFunctions().find(feMacroName);
988  if(FEMacroIt == fe->getMapOfFEMacroFunctions().end())
989  {
990  __SUP_SS__ << "FE Macro '" << feMacroName << "' of interfaceID '"
991  << interfaceID << "' was not found!" << __E__;
992  __SUP_SS_THROW__;
993  }
994  const FEVInterface::frontEndMacroStruct_t& FEMacro = FEMacroIt->second;
995 
996  __COUTV__(FEMacro.requiredUserPermissions_);
997  std::map<std::string, WebUsers::permissionLevel_t>
998  FERequiredUserPermissionsMap;
1000  FEMacro.requiredUserPermissions_, FERequiredUserPermissionsMap);
1001  __COUTV__(StringMacros::mapToString(FERequiredUserPermissionsMap));
1002 
1004  userPermissionLevelsMap, FERequiredUserPermissionsMap))
1005  {
1006  __SUP_SS__ << "Invalid user permission for FE Macro '" << feMacroName
1007  << "' of interfaceID '" << interfaceID << "'!\n\n"
1008  << "Must have access level of at least '"
1009  << StringMacros::mapToString(FERequiredUserPermissionsMap)
1010  << ".' Users permissions level is only '"
1011  << userPermissions << ".'" << __E__;
1012  __SUP_SS_THROW__;
1013  }; // skip icon if no access
1014 
1015  theFEInterfacesManager_->runFEMacro(
1016  interfaceID, FEMacro, inputArgs, outputArgs);
1017 
1018  // theFEInterfacesManager_->runFEMacro(interfaceID, feMacroName, inputArgs, outputArgs);
1019  }
1020  catch(std::runtime_error& e)
1021  {
1022  __SUP_SS__ << "In Supervisor with LID="
1023  << getApplicationDescriptor()->getLocalId()
1024  << " the FE Macro named '" << feMacroName
1025  << "' with target FE '" << interfaceID
1026  << "' failed. Here is the error:\n\n"
1027  << e.what() << __E__;
1028  __SUP_SS_THROW__;
1029  }
1030  catch(std::exception& e)
1031  {
1032  __SUP_SS__ << "In Supervisor with LID="
1033  << getApplicationDescriptor()->getLocalId()
1034  << " the FE Macro named '" << feMacroName
1035  << "' with target FE '" << interfaceID
1036  << "' failed. Here is the error:\n\n"
1037  << e.what() << __E__;
1038  __SUP_SS_THROW__;
1039  }
1040  catch(...)
1041  {
1042  __SUP_SS__ << "In Supervisor with LID="
1043  << getApplicationDescriptor()->getLocalId()
1044  << " the FE Macro named '" << feMacroName
1045  << "' with target FE '" << interfaceID
1046  << "' failed due to an unknown error." << __E__;
1047  try
1048  {
1049  throw;
1050  } //one more try to printout extra info
1051  catch(const std::exception& e)
1052  {
1053  ss << "Exception message: " << e.what();
1054  }
1055  catch(...)
1056  {
1057  }
1058  __SUP_SS_THROW__;
1059  }
1060 
1061  // retParameters.addParameter("success", success ? "1" : "0");
1062  retParameters.addParameter("outputArgs", outputArgs);
1063 
1064  return SOAPUtilities::makeSOAPMessageReference(
1065  supervisorClassNoNamespace_ + "Response", retParameters);
1066  }
1067  else if(request == "RunMacroMakerMacro")
1068  {
1069  if(!theFEInterfacesManager_)
1070  {
1071  __SUP_SS__ << "Missing FE Interface Manager! Are you configured?"
1072  << __E__;
1073  __SUP_SS_THROW__;
1074  }
1075 
1076  // params for running macros
1077  SOAPParameters requestParameters;
1078  requestParameters.addParameter("macroName");
1079  requestParameters.addParameter("macroString");
1080  requestParameters.addParameter("inputArgs");
1081  requestParameters.addParameter("outputArgs");
1082  requestParameters.addParameter("InterfaceID");
1083  SOAPUtilities::receive(message, requestParameters);
1084  std::string interfaceID = requestParameters.getValue("InterfaceID");
1085  std::string macroName = requestParameters.getValue("macroName");
1086  std::string macroString = requestParameters.getValue("macroString");
1087  std::string inputArgs = requestParameters.getValue("inputArgs");
1088  std::string outputArgs = requestParameters.getValue("outputArgs");
1089 
1090  // outputArgs must be filled with the proper argument names
1091  // and then the response output values will be returned in the string.
1092  try
1093  {
1094  theFEInterfacesManager_->runMacro(
1095  interfaceID, macroString, inputArgs, outputArgs);
1096  }
1097  catch(std::runtime_error& e)
1098  {
1099  __SUP_SS__ << "In Supervisor with LID="
1100  << getApplicationDescriptor()->getLocalId()
1101  << " the MacroMaker Macro named '" << macroName
1102  << "' with target FE '" << interfaceID
1103  << "' failed. Here is the error:\n\n"
1104  << e.what() << __E__;
1105  __SUP_SS_THROW__;
1106  }
1107  catch(...)
1108  {
1109  __SUP_SS__ << "In Supervisor with LID="
1110  << getApplicationDescriptor()->getLocalId()
1111  << " the MacroMaker Macro named '" << macroName
1112  << "' with target FE '" << interfaceID
1113  << "' failed due to an unknown error." << __E__;
1114  try
1115  {
1116  throw;
1117  } //one more try to printout extra info
1118  catch(const std::exception& e)
1119  {
1120  ss << "Exception message: " << e.what();
1121  }
1122  catch(...)
1123  {
1124  }
1125  __SUP_SS_THROW__;
1126  }
1127 
1128  retParameters.addParameter("outputArgs", outputArgs);
1129 
1130  return SOAPUtilities::makeSOAPMessageReference(
1131  supervisorClassNoNamespace_ + "Response", retParameters);
1132  }
1133  else
1134  {
1135  __SUP_SS__ << "Unrecognized request received! '" << request << "'" << __E__;
1136  __SUP_SS_THROW__;
1137  }
1138  }
1139  catch(const std::runtime_error& e)
1140  {
1141  __SUP_SS__ << "Error occurred handling request: " << e.what() << __E__;
1142  __SUP_COUT_ERR__ << ss.str();
1143  retParameters.addParameter("Error", ss.str());
1144  }
1145  catch(...)
1146  {
1147  __SUP_SS__ << "Error occurred handling request." << __E__;
1148  try
1149  {
1150  throw;
1151  } //one more try to printout extra info
1152  catch(const std::exception& e)
1153  {
1154  ss << "Exception message: " << e.what();
1155  }
1156  catch(...)
1157  {
1158  }
1159  __SUP_COUT_ERR__ << ss.str();
1160  retParameters.addParameter("Error", ss.str());
1161  }
1162 
1163  return SOAPUtilities::makeSOAPMessageReference(
1164  supervisorClassNoNamespace_ + "FailRequest", retParameters);
1165 
1166 } // end macroMakerSupervisorRequest()
1167 
1168 //==============================================================================
1169 xoap::MessageReference FESupervisor::workLoopStatusRequest(
1170  xoap::MessageReference /*message*/)
1171 {
1172  if(!theFEInterfacesManager_)
1173  {
1174  __SUP_SS__ << "Invalid request for front-end workloop status from Supervisor "
1175  "without a FEVInterfacesManager."
1176  << __E__;
1177  __SUP_SS_THROW__;
1178  }
1179 
1180  return SOAPUtilities::makeSOAPMessageReference(
1181  (theFEInterfacesManager_->allFEWorkloopsAreDone()
1182  ? CoreSupervisorBase::WORK_LOOP_DONE
1183  : CoreSupervisorBase::WORK_LOOP_WORKING));
1184 } // end workLoopStatusRequest()
1185 
1186 //==============================================================================
1194 FEVInterfacesManager* FESupervisor::extractFEInterfacesManager()
1195 {
1196  theFEInterfacesManager_ = 0;
1197 
1198  for(unsigned int i = 0; i < theStateMachineImplementation_.size(); ++i)
1199  {
1200  try
1201  {
1202  theFEInterfacesManager_ =
1203  dynamic_cast<FEVInterfacesManager*>(theStateMachineImplementation_[i]);
1204  if(!theFEInterfacesManager_)
1205  {
1206  // dynamic_cast returns null pointer on failure
1207  __SUP_SS__ << "Dynamic cast failure!" << __E__;
1208  __SUP_SS_THROW__;
1209  }
1210  __SUP_COUT__ << "State Machine " << i << " WAS of type FEVInterfacesManager"
1211  << __E__;
1212 
1213  break;
1214  }
1215  catch(...)
1216  {
1217  __SUP_COUT__ << "State Machine " << i
1218  << " was NOT of type FEVInterfacesManager" << __E__;
1219  }
1220  }
1221 
1222  __SUP_COUT__ << "theFEInterfacesManager pointer = " << theFEInterfacesManager_
1223  << __E__;
1224 
1225  return theFEInterfacesManager_;
1226 } // end extractFEInterfaceManager()
1227 
1228 //==============================================================================
1229 void FESupervisor::transitionConfiguring(toolbox::Event::Reference /*event*/)
1230 {
1231  __SUP_COUT__ << "transitionConfiguring" << __E__;
1232 
1233  CoreSupervisorBase::configureInit();
1234 
1235  // get pset from Board Reader metric manager table
1236  try
1237  {
1238  __COUTV__(CorePropertySupervisorBase::getSupervisorConfigurationPath());
1239 
1240  ConfigurationTree feSupervisorNode =
1241  CorePropertySupervisorBase::getSupervisorTableNode();
1242 
1243  std::string metric_string = "";
1244  bool metricStringSetup = true;
1245  try
1246  {
1247  std::ostringstream oss;
1248  std::string tabString = "";
1249  std::string commentsString = "";
1251  oss, tabString, commentsString, "" /* parentPath*/, feSupervisorNode);
1252  metric_string = oss.str();
1253  }
1254  catch(...)
1255  {
1256  metricStringSetup = false;
1257  metric_string = "";
1258  } // ignore error
1259 
1260  if(!metricMan)
1261  {
1262  __SUP_COUT__ << "Metric manager is not instantiated! Attempting to fix."
1263  << __E__;
1264  metricMan = std::make_unique<artdaq::MetricManager>();
1265  }
1266  std::string metricNamePreamble =
1267  feSupervisorNode.getNode("/SlowControlsMetricManagerChannelNamePreamble")
1268  .getValue<std::string>();
1269  __SUP_COUTV__(metricNamePreamble);
1270  if(metricNamePreamble == TableViewColumnInfo::DATATYPE_STRING_DEFAULT)
1271  metricNamePreamble = "";
1272 
1273  // std::string metric_string = "epics: {metricPluginType:epics level:3 channel_name_prefix:Mu2e}";
1274  fhicl::ParameterSet metric_pset = fhicl::ParameterSet::make(metric_string);
1275 
1276  __SUP_COUTV__(metricNamePreamble);
1277  try
1278  {
1279  metricMan->initialize(metric_pset.get<fhicl::ParameterSet>("metrics"),
1280  metricNamePreamble);
1281  }
1282  catch(...)
1283  {
1284  if(metricStringSetup)
1285  throw;
1286  else
1287  __SUP_COUT__ << "Ignore metric manager initialize error because metric "
1288  "string is not setup."
1289  << __E__;
1290  }
1291  __SUP_COUT__ << "transitionConfiguring metric manager(" << metricMan
1292  << ") initialized = " << metricMan->Initialized() << __E__;
1293  }
1294  catch(const std::runtime_error& e)
1295  {
1296  __SS__ << "Error loading metrics in FESupervisor::transitionConfiguring(): "
1297  << e.what() << __E__;
1298  __SUP_COUT_ERR__ << ss.str();
1299  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
1300 
1301  //__SS_THROW_ONLY__;
1302  theStateMachine_.setErrorMessage(ss.str());
1303  throw toolbox::fsm::exception::Exception(
1304  "Transition Error" /*name*/,
1305  ss.str() /* message*/,
1306  "FESupervisor::transitionConfiguring" /*module*/,
1307  __LINE__ /*line*/,
1308  __FUNCTION__ /*function*/
1309  );
1310  }
1311  catch(...)
1312  {
1313  __SS__ << "Error loading metrics in FESupervisor::transitionConfiguring()"
1314  << __E__;
1315  try
1316  {
1317  throw;
1318  } //one more try to printout extra info
1319  catch(const std::exception& e)
1320  {
1321  ss << "Exception message: " << e.what();
1322  }
1323  catch(...)
1324  {
1325  }
1326  __SUP_COUT_ERR__ << ss.str();
1327  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
1328 
1329  //__SS_THROW_ONLY__;
1330  theStateMachine_.setErrorMessage(ss.str());
1331  throw toolbox::fsm::exception::Exception(
1332  "Transition Error" /*name*/,
1333  ss.str() /* message*/,
1334  "FESupervisor::transitionConfiguring" /*module*/,
1335  __LINE__ /*line*/,
1336  __FUNCTION__ /*function*/
1337  );
1338  }
1339 
1340  CoreSupervisorBase::transitionConfiguringFSMs();
1341 
1342  __SUP_COUT__ << "transitionConfiguring done." << __E__;
1343 } // end transitionConfiguring()
1344 
1345 //==============================================================================
1346 void FESupervisor::transitionHalting(toolbox::Event::Reference event)
1347 {
1348  __SUP_COUT__ << "transitionHalting" << __E__;
1349  TLOG_DEBUG(7) << "transitionHalting";
1350 
1351  // shutdown workloops first, then shutdown metric manager
1353 
1354  try
1355  {
1356  if(metricMan && metricMan->Initialized())
1357  {
1358  TLOG_DEBUG(7) << "Metric manager(" << metricMan << ") shutting down..."
1359  << __E__;
1360  metricMan
1361  ->shutdown(); // will set initilized_ to false with mutex, which should prevent races
1362  TLOG_DEBUG(7) << "Metric manager shutdown." << __E__;
1363  }
1364  else
1365  __SUP_COUT__ << "Metric manager(" << metricMan << ") already shutdown."
1366  << __E__;
1367 
1368  metricMan.reset(nullptr);
1369  }
1370  catch(...)
1371  {
1372  __SS__ << "Error shutting down metrics in FESupervisor::transitionHalting()"
1373  << __E__;
1374  try
1375  {
1376  throw;
1377  } //one more try to printout extra info
1378  catch(const std::exception& e)
1379  {
1380  ss << "Exception message: " << e.what();
1381  }
1382  catch(...)
1383  {
1384  }
1385  __SUP_COUT_ERR__ << ss.str();
1386  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
1387 
1388  //__SS_THROW_ONLY__;
1389  theStateMachine_.setErrorMessage(ss.str());
1390  throw toolbox::fsm::exception::Exception(
1391  "Transition Error" /*name*/,
1392  ss.str() /* message*/,
1393  "FESupervisor::transitionHalting" /*module*/,
1394  __LINE__ /*line*/,
1395  __FUNCTION__ /*function*/
1396  );
1397  }
1398 
1399  __SUP_COUT__ << "transitionHalting done." << __E__;
1400 } // end transitionHalting()
1401 
1402 //==============================================================================
1403 void FESupervisor::initDataPublishing(const std::string& endpoint,
1404  const std::string& topic)
1405 {
1406  if(dp_isInitialized_)
1407  {
1408  // silently re‑initialise – close old socket first.
1409  closeDataPublishing(false);
1410  }
1411 
1412  // Store for later use.
1413  dp_endpoint_ = endpoint;
1414  dp_topic_ = topic;
1415 
1416  // Bind the PUB socket.
1417  try
1418  {
1419  dp_socket_.bind(dp_endpoint_);
1420  }
1421  catch(const zmq::error_t& e)
1422  {
1423  __SUP_SS__ << "initDataPublishing() - bind to zmq '" + dp_endpoint_ +
1424  "' failed: " + e.what()
1425  << __E__;
1426  __SUP_SS_THROW__;
1427  }
1428 
1429  dp_isInitialized_ = true;
1430 } //end initDataPublishing()
1431 
1432 //==============================================================================
1433 void FESupervisor::closeDataPublishing(bool alsoCloseContext /* = true */)
1434 {
1435  if(dp_isInitialized_)
1436  {
1437  try
1438  {
1439  dp_socket_.set(zmq::sockopt::linger, 0); // discard unsent messages on close
1440  dp_socket_.close(); // close the PUB socket
1441  }
1442  catch(const zmq::error_t&)
1443  {
1444  // ignore – we are cleaning up.
1445  }
1446  try
1447  {
1448  if(alsoCloseContext)
1449  dp_context_.close(); // close the ZMQ context
1450  }
1451  catch(const zmq::error_t&)
1452  {
1453  // ignore.
1454  }
1455  dp_isInitialized_ = false;
1456  }
1457 } //end closeDataPublishing()
1458 
1459 //==============================================================================
1467 void FESupervisor::publishData(const char* dataPtr, size_t dataSize)
1468 {
1469  if(!dp_isInitialized_)
1470  {
1471  __SUP_SS__ << "publishData() called before zmq init()" << __E__;
1472  __SUP_SS_THROW__;
1473  }
1474 
1475  // ---- Topic frame (must be sent with sndmore) ----
1476  // Using zmq::buffer prevents an extra copy – it just points at the data.
1477  auto rc_topic = dp_socket_.send(zmq::buffer(dp_topic_), zmq::send_flags::sndmore);
1478  if(!rc_topic)
1479  {
1480  __SUP_SS__ << "publishData() - failed to send zmq topic" << __E__;
1481  __SUP_SS_THROW__;
1482  }
1483 
1484  // ---- Payload frame (final frame) ----
1485  // `dataPtr` may be nullptr only if `dataSize == 0` – ZeroMQ accepts an empty frame.
1486  if(dataPtr == nullptr && dataSize > 0)
1487  {
1488  __SUP_SS__ << "FESupervisor::publishData() - dataPtr is nullptr but dataSize is "
1489  << dataSize << __E__;
1490  __SUP_SS_THROW__;
1491  }
1492  auto rc_payload =
1493  dp_socket_.send(zmq::buffer(dataPtr, dataSize), zmq::send_flags::none);
1494  if(!rc_payload)
1495  {
1496  __SUP_SS__ << "publishData() - failed to send zmq payload" << __E__;
1497  __SUP_SS_THROW__;
1498  }
1499 } //end publishData()
static void insertMetricsBlock(std::ostream &out, std::string &tabStr, std::string &commentStr, const std::string &parentPath, ConfigurationTree daqNode)
insertMetricsBlock
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
void getValue(T &value) const
static void extractPermissionsMapFromString(const std::string &permissionsString, std::map< std::string, WebUsers::permissionLevel_t > &permissionsMap)
static bool doPermissionsGrantAccess(std::map< std::string, WebUsers::permissionLevel_t > &permissionLevelsMap, std::map< std::string, WebUsers::permissionLevel_t > &permissionThresholdsMap)
virtual void transitionHalting(toolbox::Event::Reference event)
virtual void request(const std::string &requestType, cgicc::Cgicc &cgiIn, HttpXmlDocument &xmlOut, const WebUsers::RequestUserInfo &userInfo)
void publishData(const char *dataPtr, size_t dataSize)
virtual void transitionHalting(toolbox::Event::Reference event) override
void initDataPublishing(const std::string &endpoint, const std::string &topic="test")
void closeDataPublishing(bool alsoCloseContext=true)
xoap::MessageReference macroMakerSupervisorRequest(xoap::MessageReference message)
const FEVInterface & getFEInterface(const std::string &interfaceID) const
getFEInterface
std::string getFEMacrosString(const std::string &supervisorName, const std::string &supervisorLid)
used by MacroMaker
FEVInterface * getFEInterfaceP(const std::string &interfaceID)
getFEInterfaceP
void runFEMacro(const std::string &interfaceID, const FEVInterface::frontEndMacroStruct_t &feMacro, const std::string &inputArgs, std::string &outputArgs)
used by MacroMaker and FE calling indirectly
unsigned int getInterfaceUniversalAddressSize(const std::string &interfaceID)
used by MacroMaker
void startFEMacroMultiDimensional(const std::string &requester, const std::string &interfaceID, const std::string &feMacroName, const bool enableSavingOutput, const std::string &outputFilePath, const std::string &outputFileRadix, const std::string &inputArgs)
used by iterator calling (i.e. FESupervisor)
void universalWrite(const std::string &interfaceID, char *address, char *writeValue)
used by MacroMaker
bool allFEWorkloopsAreDone(void)
used by Iterator, e.g.
void runFEMacroByFE(const std::string &callingInterfaceID, const std::string &interfaceID, const std::string &feMacroName, const std::string &inputArgs, std::string &outputArgs)
used by FE calling (i.e. FESupervisor)
unsigned int getInterfaceUniversalDataSize(const std::string &interfaceID)
used by MacroMaker
void universalRead(const std::string &interfaceID, char *address, char *returnValue)
used by MacroMaker
void startMacroMultiDimensional(const std::string &requester, const std::string &interfaceID, const std::string &macroName, const std::string &macroString, const bool enableSavingOutput, const std::string &outputFilePath, const std::string &outputFileRadix, const std::string &inputArgs)
used by iterator calling (i.e. FESupervisor)
bool checkMacroMultiDimensional(const std::string &interfaceID, const std::string &macroName)
used by iterator calling (i.e. FESupervisor)
std::mutex frontEndCommunicationReceiveMutex_
FE communication helpers.
void runMacro(const std::string &interfaceID, const std::string &macroObjectString, const std::string &inputArgs, std::string &outputArgs)
used by MacroMaker
std::string getFEListString(const std::string &supervisorLid)
used by MacroMaker
defines used also by OtsConfigurationWizardSupervisor
< members fully define a front-end macro function
Definition: FEVInterface.h:169
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")