tdaq-develop-2025-02-12
GatewaySupervisor.h
1 #ifndef _ots_GatewaySupervisor_h
2 #define _ots_GatewaySupervisor_h
3 
4 #include "otsdaq/CoreSupervisors/ConfigurationSupervisorBase.h"
5 #include "otsdaq/CoreSupervisors/CorePropertySupervisorBase.h"
6 #include "otsdaq/FiniteStateMachine/RunControlStateMachine.h"
7 #include "otsdaq/GatewaySupervisor/Iterator.h"
8 #include "otsdaq/SOAPUtilities/SOAPMessenger.h"
9 #include "otsdaq/SupervisorInfo/AllSupervisorInfo.h"
10 #include "otsdaq/WebUsersUtilities/WebUsers.h"
11 #include "otsdaq/WorkLoopManager/WorkLoopManager.h"
12 
13 #include "otsdaq/CodeEditor/CodeEditor.h"
14 #include "otsdaq/TablePlugins/DesktopIconTable.h"
15 
16 #include "otsdaq/NetworkUtilities/TransceiverSocket.h" // for UDP state changer
17 
18 #pragma GCC diagnostic push
19 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
20 #include <xdaq/Application.h>
21 #pragma GCC diagnostic pop
22 #include "otsdaq/Macros/XDAQApplicationMacros.h"
23 
24 #include <toolbox/task/WorkLoop.h>
25 #include <xdata/String.h>
26 #include <xgi/Method.h>
27 #include "otsdaq/GatewaySupervisor/PixelHistoPicGen.h"
28 
29 #include <set>
30 #include <sstream>
31 #include <string>
32 
34 #define FSM_LAST_CONFIGURED_GROUP_ALIAS_FILE \
35  std::string("FSMLastConfiguredGroupAlias.hist")
36 #define FSM_LAST_STARTED_GROUP_ALIAS_FILE std::string("FSMLastStartedGroupAlias.hist")
37 
38 namespace ots
39 {
40 class ConfigurationManager;
41 class TableGroupKey;
42 class WorkLoopManager;
43 
44 // clang-format off
45 
50  class GatewaySupervisor : public xdaq::Application,
51  public SOAPMessenger,
55  {
56  friend class WizardSupervisor;
57  friend class Iterator;
58 
59  public:
60  XDAQ_INSTANTIATOR();
61 
62  GatewaySupervisor (xdaq::ApplicationStub* s);
63  virtual ~GatewaySupervisor (void);
64 
65  void init (void);
66 
67  void Default (xgi::Input* in, xgi::Output* out);
68 
69  void loginRequest (xgi::Input* in, xgi::Output* out);
70  void request (xgi::Input* in, xgi::Output* out);
71  void tooltipRequest (xgi::Input* in, xgi::Output* out);
72  void XGI_Turtle (xgi::Input* in, xgi::Output* out);
73 
74  void addStateMachineStatusToXML (HttpXmlDocument& xmlOut, const std::string& fsmName, bool getRunNumber = true);
75  void addFilteredConfigAliasesToXML (HttpXmlDocument& xmlOut, const std::string& fsmName);
76  void addRequiredFsmLogInputToXML (HttpXmlDocument& xmlOut, const std::string& fsmName);
77 
78  // State Machine requests handlers
79  void stateMachineXgiHandler(xgi::Input* in, xgi::Output* out);
80  void stateMachineIterationBreakpoint(xgi::Input* in, xgi::Output* out);
81 
82  static std::string getIconHeaderString(void);
83  static bool handleAddDesktopIconRequest(const std::string& author, cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut, std::vector<DesktopIconTable::DesktopIcon>* newIcons = nullptr);
84  static void handleGetApplicationIdRequest(AllSupervisorInfo* applicationInfo, cgicc::Cgicc& cgiIn, HttpXmlDocument& xmlOut);
85 
86  xoap::MessageReference stateMachineXoapHandler(xoap::MessageReference msg);
87 
88  bool stateMachineThread(toolbox::task::WorkLoop* workLoop);
89 
90  // Status requests handlers
91  void statusRequest(xgi::Input* in, xgi::Output* out);
92  void infoRequestResultHandler(xgi::Input* in, xgi::Output* out);
93  bool infoRequestThread(toolbox::task::WorkLoop* workLoop);
94 
95  // External GatewaySupervisor XOAP handlers
96  xoap::MessageReference supervisorCookieCheck(xoap::MessageReference msg);
97  xoap::MessageReference supervisorGetActiveUsers(xoap::MessageReference msg);
98  xoap::MessageReference supervisorSystemMessage(xoap::MessageReference msg);
99  xoap::MessageReference supervisorGetUserInfo(xoap::MessageReference msg);
100  xoap::MessageReference supervisorSystemLogbookEntry(xoap::MessageReference msg);
101  xoap::MessageReference supervisorLastTableGroupRequest(xoap::MessageReference msg);
102 
103  // Finite State Machine States
104  void stateInitial(toolbox::fsm::FiniteStateMachine& fsm) override;
105  void statePaused(toolbox::fsm::FiniteStateMachine& fsm) override;
106  void stateRunning(toolbox::fsm::FiniteStateMachine& fsm) override;
107  void stateHalted(toolbox::fsm::FiniteStateMachine& fsm) override;
108  void stateConfigured(toolbox::fsm::FiniteStateMachine& fsm) override;
109  void inError(toolbox::fsm::FiniteStateMachine& fsm) override;
110 
111  void transitionConfiguring(toolbox::Event::Reference e) override;
112  void transitionHalting(toolbox::Event::Reference e) override;
113  void transitionInitializing(toolbox::Event::Reference e) override;
114  void transitionPausing(toolbox::Event::Reference e) override;
115  void transitionResuming(toolbox::Event::Reference e) override;
116  void transitionStarting(toolbox::Event::Reference e) override;
117  void transitionStopping(toolbox::Event::Reference e) override;
118  void transitionShuttingDown(toolbox::Event::Reference e) override;
119  void transitionStartingUp(toolbox::Event::Reference e) override;
120  void enteringError(toolbox::Event::Reference e) override;
121 
122  void makeSystemLogEntry(const std::string& entryText, const std::string& subjectText = "");
123  static void addSystemMessage(std::string toUserCSV, std::string message);
124 
125  void checkForAsyncError(void);
126 
127  // CorePropertySupervisorBase override functions
128  virtual void setSupervisorPropertyDefaults (void) override;
129  virtual void forceSupervisorPropertyValues (void) override;
130 
131 
132  private:
133  unsigned int getNextRunNumber (const std::string& fsmName = "");
134  void setNextRunNumber (unsigned int runNumber, const std::string& fsmName = "");
135  std::string getLastLogEntry (const std::string& logType, const std::string& fsmName = "");
136  void setLastLogEntry (const std::string& logType, const std::string& logEntry, const std::string& fsmName = "");
137 
138 
139  static xoap::MessageReference lastTableGroupRequestHandler (const SOAPParameters& parameters);
140  static void launchStartOTSCommand (const std::string& command, ConfigurationManager* cfgMgr);
141  static void launchStartOneServerCommand (const std::string& command, ConfigurationManager* cfgMgr, const std::string& contextName);
142 
143  static void indicateOtsAlive (const CorePropertySupervisorBase* properties = 0);
144  xoap::MessageReference TRACESupervisorRequest (xoap::MessageReference message);
145 
146  static void StateChangerWorkLoop (GatewaySupervisor* supervisorPtr);
147  static void AppStatusWorkLoop (GatewaySupervisor* supervisorPtr);
148 
149  std::string attemptStateMachineTransition (HttpXmlDocument* xmldoc,
150  std::ostringstream* out,
151  const std::string& command,
152  const std::string& fsmName,
153  const std::string& fsmWindowName,
154  const std::string& username,
155  const std::vector<std::string>& parameters,
156  std::string logEntry = "");
157  void broadcastMessage (xoap::MessageReference msg);
158  void broadcastMessageToRemoteGateways (const xoap::MessageReference msg);
159  bool broadcastMessageToRemoteGatewaysComplete (const xoap::MessageReference msg);
160 
161  struct BroadcastMessageIterationsDoneStruct
162  {
163  // Creating std::vector<std::vector<bool>>
164  // because of problems with the standard library
165  // not allowing passing by reference of bool types.
166  // Broadcast thread implementation requires passing by reference.
167  ~BroadcastMessageIterationsDoneStruct()
168  {
169  for (auto& arr : iterationsDone_)
170  delete[] arr;
171  iterationsDone_.clear();
172  arraySizes_.clear();
173  } // end destructor
174 
175  void push(const unsigned int& size)
176  {
177  iterationsDone_.push_back(new bool[size]);
178  arraySizes_.push_back(size);
179 
180  // initialize to false
181  for (unsigned int i = 0; i < size; ++i)
182  iterationsDone_[iterationsDone_.size() - 1][i] = false;
183  } // end push()
184 
185  bool* operator[](unsigned int i) { return iterationsDone_[i]; }
186  const bool* operator[](unsigned int i) const { return iterationsDone_[i]; }
187  unsigned int size(unsigned int i = -1)
188  {
189  if (i == (unsigned int)-1)
190  return iterationsDone_.size();
191  return arraySizes_[i];
192  }
193 
194  private:
195  std::vector<bool*> iterationsDone_;
196  std::vector<unsigned int> arraySizes_;
197  }; // end BroadcastMessageIterationsDoneStruct definition
198 
199  struct BroadcastThreadStruct
200  {
201  //===================
202  BroadcastThreadStruct()
203  : threadIndex_(-1)
204  , exitThread_(false)
205  , working_(true)
206  , workToDo_(false)
207  , error_(false)
208  {
209  } // end BroadcastThreadStruct constructor()
210 
211  //===================
212  BroadcastThreadStruct(BroadcastThreadStruct &&b)
213  : threadIndex_(b.threadIndex_)
214  , exitThread_(b.exitThread_)
215  , working_(b.working_)
216  , workToDo_(b.workToDo_)
217  , error_(b.error_)
218  {
219  } // end BroadcastThreadStruct move constructor()
220 
221 
223  {
224  //===================
225  BroadcastMessageStruct(const SupervisorInfo& appInfo,
226  xoap::MessageReference message,
227  const std::string& command,
228  const unsigned int& iteration,
229  bool& iterationsDone)
230  : appInfo_(appInfo)
231  , message_(message)
232  , command_(command)
233  , iteration_(iteration)
234  , iterationsDone_(iterationsDone)
235  {
236  }
237 
238  const SupervisorInfo& appInfo_;
239  xoap::MessageReference message_;
240  const std::string command_;
241  const unsigned int iteration_;
242  bool& iterationsDone_;
243 
244  std::string reply_;
245  }; // end BroadcastMessageStruct definition
246 
247  //===================
248  void setMessage(const SupervisorInfo& appInfo,
249  xoap::MessageReference message,
250  const std::string& command,
251  const unsigned int& iteration,
252  bool& iterationsDone)
253  {
254  messages_.clear();
256  appInfo, message, command, iteration, iterationsDone));
257  workToDo_ = true;
258  } // end setMessage()
259 
260  const SupervisorInfo& getAppInfo() { return messages_[0].appInfo_; }
261  xoap::MessageReference getMessage() { return messages_[0].message_; }
262  const std::string& getCommand() { return messages_[0].command_; }
263  const unsigned int& getIteration() { return messages_[0].iteration_; }
264  std::string& getReply() { return messages_[0].reply_; }
265  bool& getIterationsDone() { return messages_[0].iterationsDone_; }
266 
267  // each thread accesses these members
268  std::mutex threadMutex_;
269  unsigned int threadIndex_;
270  volatile bool exitThread_, working_, workToDo_, error_;
271  // always just 1 message (for now)
272  std::vector<BroadcastThreadStruct::BroadcastMessageStruct> messages_;
273 
274  }; // end BroadcastThreadStruct declaration
275  static void broadcastMessageThread(
276  GatewaySupervisor* supervisorPtr,
277  std::shared_ptr<GatewaySupervisor::BroadcastThreadStruct> threadStruct);
278  bool handleBroadcastMessageTarget(const SupervisorInfo& appInfo,
279  xoap::MessageReference message,
280  const std::string& command,
281  const unsigned int& iteration,
282  std::string& reply,
283  unsigned int threadIndex = 0);
284 
285 
286  // Member Variables -----------------------
287 
288  bool supervisorGuiHasBeenLoaded_;
289  static WebUsers theWebUsers_;
290 
291  WorkLoopManager stateMachineWorkLoopManager_;
292  toolbox::BSem stateMachineSemaphore_;
293 
294  std::string activeStateMachineName_;
295  std::string activeStateMachineWindowName_;
296  std::string activeStateMachineConfigurationDumpOnRun_, activeStateMachineConfigurationDumpOnConfigure_;
297  bool activeStateMachineConfigurationDumpOnRunEnable_, activeStateMachineConfigurationDumpOnConfigureEnable_;
298  std::string activeStateMachineConfigurationDumpOnRunFilename_, activeStateMachineConfigurationDumpOnConfigureFilename_;
299  bool activeStateMachineRequireUserLogOnRun_, activeStateMachineRequireUserLogOnConfigure_;
300  std::string activeStateMachineRunInfoPluginType_;
301  std::map<std::string /* fsmName */, std::string /* logEntry */>
302  stateMachineConfigureLogEntry_, stateMachineStartLogEntry_, stateMachineStopLogEntry_;
303  std::string activeStateMachineRunNumber_, activeStateMachineRunAlias_, activeStateMachineConfigurationAlias_;
304  bool activeStateMachineRollOverLogOnConfigure_, activeStateMachineRollOverLogOnStart_;
305  std::chrono::steady_clock::time_point
306  activeStateMachineRunStartTime;
307  int activeStateMachineRunDuration_ms;
308 
309 
310  std::mutex systemStatusMutex_;
311  std::string lastLogbookEntry_;
312  time_t lastLogbookEntryTime_ = 0;
313 
314  std::string lastConsoleErr_, lastConsoleWarn_, lastConsoleInfo_, lastConsoleErrTime_, lastConsoleWarnTime_, lastConsoleInfoTime_;
315  std::string firstConsoleErr_, firstConsoleWarn_, firstConsoleInfo_, firstConsoleErrTime_, firstConsoleWarnTime_, firstConsoleInfoTime_;
316  size_t systemConsoleErrCount_ = 0, systemConsoleWarnCount_ = 0, systemConsoleInfoCount_ = 0;
317 
318  std::pair<std::string /*group name*/, TableGroupKey>
319  theConfigurationTableGroup_;
320 
321  Iterator theIterator_;
322  std::mutex stateMachineAccessMutex_;
324  std::string stateMachineLastCommandInput_;
325  std::string lastConfigurationAlias_;
326  enum
327  {
328  VERBOSE_MUTEX = 0
329  };
330 
331  CodeEditor codeEditor_;
332 
333  std::mutex broadcastCommandMessageIndexMutex_, broadcastIterationsDoneMutex_;
334  unsigned int broadcastCommandMessageIndex_;
335  bool broadcastIterationsDone_;
336  std::mutex broadcastIterationBreakpointMutex_;
337  unsigned int broadcastIterationBreakpoint_;
339  std::mutex broadcastCommandStatusUpdateMutex_;
340  std::string broadcastCommandStatus_;
341  static std::vector<std::shared_ptr<GatewaySupervisor::BroadcastThreadStruct>> broadcastThreadStructs_;
342 
343  std::string securityType_;
344  PixelHistoPicGen picGen_;
345 
346  //Variable used by the RunInfo plugin
347  unsigned int conditionID_;
348 
349 public: //used by remote subsystem control and status
350 
353 
354  std::string command, fsmName;
355  std::string error, config_dump;
356  size_t ignoreStatusCount = 0;
357 
358  size_t consoleErrCount = 0, consoleWarnCount = 0;
359 
360  std::string fullName;
361  std::string user_data_path_record;
362  std::string setupType, instancePath, instanceHost, instanceUser;
363 
364  std::string selected_config_alias;
365  std::set<std::string> config_aliases;
366  std::string iconString, parentIconFolderPath, landingPage, permissionThresholdString;
367 
368  std::string usernameWithLock;
369 
370  enum class FSM_ModeTypes
371  {
372  Follow_FSM,
373  DoNotHalt,
374  OnlyConfigure,
375  };
376  FSM_ModeTypes fsm_mode = FSM_ModeTypes::Follow_FSM;
377  bool fsm_included = true;
378 
379  std::string getFsmMode() const {
380  switch(fsm_mode)
381  {
382  case FSM_ModeTypes::Follow_FSM: return "Follow FSM";
383  case FSM_ModeTypes::DoNotHalt: return "Do Not Halt";
384  case FSM_ModeTypes::OnlyConfigure: return "Only Configure";
385  default: return "Impossible";
386  }
387  } //end getFsmMode()
388 
389  std::map<std::string, SupervisorInfo::SubappInfo> subapps;
390  }; //end GatewaySupervisor::RemoteGatewayInfo struct
391 
392  std::vector<GatewaySupervisor::RemoteGatewayInfo> remoteGatewayApps_;
393  std::mutex remoteGatewayAppsMutex_;
394 
395  static void CheckRemoteGatewayStatus (GatewaySupervisor::RemoteGatewayInfo& remoteGatewayApp, const std::unique_ptr<TransceiverSocket>& remoteGatewaySocket, const std::string& ipForReverseLoginOverUDP, int portForReverseLoginOverUDP);
396  static void SendRemoteGatewayCommand (GatewaySupervisor::RemoteGatewayInfo& remoteGatewayApp, const std::unique_ptr<TransceiverSocket>& remoteGatewaySocket);
397  static void GetRemoteGatewayIcons (GatewaySupervisor::RemoteGatewayInfo& remoteGatewayApp, const std::unique_ptr<TransceiverSocket>& remoteGatewaySocket);
398  void loadRemoteGatewaySettings (std::vector<GatewaySupervisor::RemoteGatewayInfo>& remoteGateways, bool onlyNotFound = false) const;
399  void saveRemoteGatewaySettings (void) const;
400 
401  };
402 // clang-format on
403 
404 } // namespace ots
405 
406 #endif
friend class GatewaySupervisor
for access to indicateOtsAlive()
virtual void setSupervisorPropertyDefaults(void) override
override to control supervisor specific defaults
void stateHalted(toolbox::fsm::FiniteStateMachine &fsm) override
virtual void forceSupervisorPropertyValues(void) override
override to force supervisor property values (and ignore user settings)
void statePaused(toolbox::fsm::FiniteStateMachine &fsm) override
void stateRunning(toolbox::fsm::FiniteStateMachine &fsm) override
void stateConfigured(toolbox::fsm::FiniteStateMachine &fsm) override
void stateInitial(toolbox::fsm::FiniteStateMachine &fsm) override
FSM_ModeTypes
<FSM Modes: 'Follow FSM,' 'Do not Halt' (artdaq), or 'Only Configure' (DCS/DQM)
std::string permissionThresholdString
used for desktop icons
std::set< std::string > config_aliases
used for remote gateway subapp control
std::string selected_config_alias
used for remote gateway subapp control
FSM_ModeTypes fsm_mode
used for remote gateway subapp control
std::string fsmName
when not "", need to send
std::map< std::string, SupervisorInfo::SubappInfo > subapps
remote gateways can have subapps
size_t ignoreStatusCount
if non-zero, do not ask for status
std::string instanceUser
used for remote ots instance ssh launch
std::string user_data_path_record
used for remote gateway subapp control