otsdaq  3.11.00
ARTDAQSupervisor.hh
1 #ifndef _ots_ARTDAQSupervisor_h
2 #define _ots_ARTDAQSupervisor_h
3 
4 #if __cplusplus > 201402L
5 #pragma GCC diagnostic push
6 #pragma GCC diagnostic ignored "-Wregister"
7 #include <Python.h>
8 #pragma GCC diagnostic pop
9 #else
10 #include <Python.h>
11 #endif
12 
13 #include <atomic>
14 #include <chrono>
15 #include <memory>
16 #include <mutex>
17 #include <set>
18 #include <thread>
19 
20 #include "artdaq/ExternalComms/CommanderInterface.hh"
21 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
22 #include "otsdaq/TablePlugins/ARTDAQTableBase/ARTDAQTableBase.h"
23 
24 namespace ots
25 {
29 {
30  public:
31  XDAQ_INSTANTIATOR();
32 
34  {
35  std::string label;
36  std::string host;
37  int port;
38  int subsystem;
39  int rank;
40  std::string state;
41  };
42 
43  ARTDAQSupervisor(xdaq::ApplicationStub* s);
44  virtual ~ARTDAQSupervisor(void);
45 
46  void init(void);
47  void destroy(void);
48 
49  virtual void transitionConfiguring(toolbox::Event::Reference event) override;
50  virtual void transitionHalting(toolbox::Event::Reference event) override;
51  virtual void transitionInitializing(toolbox::Event::Reference event) override;
52  virtual void transitionPausing(toolbox::Event::Reference event) override;
53  virtual void transitionResuming(toolbox::Event::Reference event) override;
54  virtual void transitionStarting(toolbox::Event::Reference event) override;
55  virtual void transitionStopping(toolbox::Event::Reference event) override;
56  virtual void enteringError(toolbox::Event::Reference event) override;
57 
58  void request(const std::string& requestType,
59  cgicc::Cgicc& cgiIn,
60  HttpXmlDocument& xmlOut,
61  const WebUsers::RequestUserInfo& userInfo) override;
62 
63  virtual std::vector<SupervisorInfo::SubappInfo> getSubappInfo(void) override;
64  virtual std::string getStatusProgressDetail(void) override
65  {
66  if(!theStateMachine_.isInTransition() &&
67  (theStateMachine_.getCurrentStateName() ==
68  RunControlStateMachine::HALTED_STATE_NAME ||
69  theStateMachine_.getCurrentStateName() ==
70  RunControlStateMachine::INITIAL_STATE_NAME))
72 
73  std::lock_guard<std::mutex> lk(thread_mutex_);
74  __COUTVS__(20, thread_progress_message_);
75  return thread_progress_message_;
76  } //end getStatusProgressDetail()
77 
78  std::list<
79  std::pair<DAQInterfaceProcessInfo, std::unique_ptr<artdaq::CommanderInterface>>>
80  makeCommandersFromProcessInfo();
81 
82  // Hostnames of all enabled artdaq processes from the active configuration.
83  // Reflects the configuration's intended deployment (works even when
84  // DAQInterface is not running). Note: config does NOT carry the runtime
85  // xmlrpc commander ports -- this is for host discovery only.
86  std::set<std::string> getConfiguredArtdaqHosts(void);
87 
88  static std::list<std::string> tokenize_(std::string const& input);
89 
90  private:
91  void forceSupervisorPropertyValues(void) override;
92  void initArtdaqSystemVariables();
93  void saveArtdaqSystemVariables();
94  void loadArtdaqSystemVariables();
95  std::string getServiceDataFilePath() const;
96 
97  static const std::string ARTDAQ_SYSVAR_NAMESPACE;
98 
99  void configuringThread(void);
100  void startingThread(void);
101 
103  struct PyObjectGuard
104  {
105  PyObject* obj;
106  explicit PyObjectGuard(PyObject* o)
107  : obj(o) {}
108  ~PyObjectGuard()
109  {
110  if(obj)
111  Py_DECREF(obj);
112  }
113  PyObjectGuard(const PyObjectGuard&) = delete;
114  PyObjectGuard& operator=(const PyObjectGuard&) = delete;
115  PyObject* get() const { return obj; }
116  };
117 
118  PyObject *daqinterface_ptr_, *stringIO_out_,
119  *stringIO_err_; //stringIO_err_ not needed with new Tee Buffer solution
120  std::recursive_timed_mutex daqinterface_pythonMutex_;
121  std::mutex daqinterface_statusMutex_;
122  std::string daqinterface_status_;
123  int partition_;
124  std::string daqinterface_state_;
129  struct RunnerControl
130  {
131  std::atomic<bool> running{true};
132  std::atomic<bool> exited{false};
133  };
134  std::unique_ptr<std::thread> runner_thread_;
135  std::shared_ptr<RunnerControl> runner_control_;
136  std::atomic<bool> runner_abandoned_{false};
137 
138  std::mutex thread_mutex_;
139  ProgressBar thread_progress_bar_;
140  std::string thread_progress_message_;
141  std::string thread_error_message_;
142  int last_thread_progress_read_;
143  time_t last_thread_progress_update_;
144  std::map<std::string, std::string> label_to_proc_type_map_;
145 
146  unsigned int cachedMinReadyForEventGenerationStartIteration_ = 0;
147 
150  std::string capturePyErr(std::string label = "", std::string* summaryOut = nullptr);
151  bool checkPythonError(
152  PyObject* result); // Check if Python call failed (returns true on error)
153  std::string captureStderrAndStdout_(std::string label = "");
154  void getDAQState_(void);
155  std::string getProcessInfo_(void);
156  std::string artdaqStateToOtsState(std::string state);
157  std::string labelToProcType_(std::string label);
158  std::list<DAQInterfaceProcessInfo> getAndParseProcessInfo_(void);
159  void daqinterfaceRunner_(std::shared_ptr<RunnerControl> control);
160  bool stop_runner_(unsigned int timeoutSeconds = 5);
161  void start_runner_(void);
162  void set_thread_message_(std::string msg)
163  {
164  std::lock_guard<std::mutex> lk(thread_mutex_);
165  thread_progress_message_ = msg;
166  }
167 };
168 
169 } // namespace ots
170 
171 #endif
void request(const std::string &requestType, cgicc::Cgicc &cgiIn, HttpXmlDocument &xmlOut, const WebUsers::RequestUserInfo &userInfo) override
virtual void transitionHalting(toolbox::Event::Reference event) override
virtual void transitionInitializing(toolbox::Event::Reference event) override
virtual std::string getStatusProgressDetail(void) override
virtual std::string getStatusProgressDetail(void)
defines used also by OtsConfigurationWizardSupervisor