tdaq-develop-2025-02-12
MessageFacilityTable_table.cc
1 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
2 #include "otsdaq/Macros/TablePluginMacros.h"
3 #include "otsdaq/TablePlugins/MessageFacilityTable.h"
4 
5 #include <stdio.h>
6 #include <fstream> // std::fstream
7 #include <iostream>
8 using namespace ots;
9 
10 // clang-format off
11 #define MF_CFG_FILE std::string(__ENV__("USER_DATA")) + "/MessageFacilityConfigurations/MessageFacilityGen.fcl"
12 #define MF_ARTDAQ_INTERFACE_CFG_FILE std::string(__ENV__("USER_DATA")) + "/MessageFacilityConfigurations/ARTDAQInterfaceMessageFacilityGen.fcl"
13 #define QT_CFG_FILE std::string(__ENV__("USER_DATA")) + "/MessageFacilityConfigurations/QTMessageViewerGen.fcl"
14 #define QUIET_CFG_FILE std::string(__ENV__("USER_DATA")) + "/MessageFacilityConfigurations/QuietForwarderGen.cfg"
15 #define USE_WEB_BOOL_FILE std::string(__ENV__("USER_DATA")) + "/MessageFacilityConfigurations/UseWebConsole.bool"
16 #define USE_QT_BOOL_FILE std::string(__ENV__("USER_DATA")) + "/MessageFacilityConfigurations/UseQTViewer.bool"
17 
19 #define COL_NAME "UID"
20 #define COL_STATUS TableViewColumnInfo::COL_NAME_STATUS
21 #define COL_ENABLE_FWD "EnableUDPForwarding"
22 
23 #define COL_USE_WEB "ForwardToWebConsoleGUI"
24 #define COL_WEB_IP "WebConsoleForwardingIPAddress"
25 #define COL_WEB_PORT0 "WebConsoleForwardingPort0"
26 #define COL_WEB_PORT1 "WebConsoleForwardingPort1"
27 
28 #define COL_USE_QT "ForwardToQTViewerGUI"
29 #define COL_QT_IP "QTViewerForwardingIPAddress"
30 #define COL_QT_PORT "QTViewerForwardingPort"
31 
32 // clang-format on
33 
34 MessageFacilityTable::MessageFacilityTable(void) : TableBase("MessageFacilityTable")
35 {
37  // WARNING: the names used in C++ MUST match the Table INFO //
39 }
40 
41 MessageFacilityTable::~MessageFacilityTable(void) {}
42 
44 {
45  // use isFirstAppInContext to only run once per context, for example to avoid
46  // generating files on local disk multiple times.
47  bool isFirstAppInContext = configManager->isOwnerFirstAppInContext();
48 
49  //__COUTV__(isFirstAppInContext);
50  if(!isFirstAppInContext)
51  return;
52 
53  // __COUTT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << std::endl;
54  // __COUTT__ << configManager->__SELF_NODE__ << std::endl;
55 
56  bool enableFwd = true, useWeb = true,
57  useQT = false; // default to enabling web console
58  int fwdPort, destFwdPort;
59  std::string fwdIP;
60  std::string parseFilename = "/src";
61 
62  // attempt to setup forward IP:Port:FwdPort defaults
63  try
64  {
65  fwdPort = atoi(__ENV__("OTS_MAIN_PORT")) + 30000;
66  }
67  catch(...)
68  {
69  } // ignore errors (assume user will setup in table)
70  try
71  {
72  destFwdPort = atoi(__ENV__("OTS_MAIN_PORT")) + 30001;
73  }
74  catch(...)
75  {
76  } // ignore errors (assume user will setup in table)
77  try
78  {
79  fwdIP = __ENV__("HOSTNAME");
80  }
81  catch(...)
82  {
83  } // ignore errors (assume user will setup in table)
84  try
85  {
86  parseFilename =
87  std::string("/") + __ENV__("OTS_ENV") + "/"; //parse on spack environment
88  //override with env variable if present
89  parseFilename = __ENV__("OTS_FILE_PARSE_PATTERN"); //parse on spack environment
90  }
91  catch(...)
92  {
93  } // ignore errors (assume user will setup in table)
94 
95  __COUTTV__(parseFilename);
96  try
97  {
98  __COUTTV__(__ENV__("TRACE_TIME_FMT"));
99  }
100  catch(...)
101  {
102  } //ignore error
103 
104  auto childrenMap = configManager->__SELF_NODE__.getChildren();
105 
106  std::stringstream fclSs;
107 
108  // loop through all children just to be same as other tables
109  // exit loop after first active one
110  for(auto& child : childrenMap)
111  {
112  bool status;
113  child.second.getNode(COL_STATUS).getValue(status);
114 
115  if(!status)
116  continue; // skip inactive rows
117 
118  child.second.getNode(COL_ENABLE_FWD).getValue(enableFwd);
119 
120  child.second.getNode(COL_USE_WEB).getValue(useWeb);
121  child.second.getNode(COL_USE_QT).getValue(useQT);
122 
123  if(!child.second.getNode(COL_WEB_PORT0).isDefaultValue())
124  child.second.getNode(COL_WEB_PORT0).getValue(fwdPort);
125 
126  if(!child.second.getNode(COL_WEB_IP).isDefaultValue())
127  child.second.getNode(COL_WEB_IP).getValue(fwdIP);
128 
129  if(!child.second.getNode(COL_WEB_PORT1).isDefaultValue())
130  child.second.getNode(COL_WEB_PORT1).getValue(destFwdPort);
131 
132  if(useQT)
133  {
134  if(!child.second.getNode(COL_QT_IP).isDefaultValue())
135  child.second.getNode(COL_QT_IP).getValue(fwdIP);
136 
137  if(!child.second.getNode(COL_QT_PORT).isDefaultValue())
138  child.second.getNode(COL_QT_PORT).getValue(fwdPort);
139  }
140 
141  __COUTT__ << "Found FWD/WEB/QT " << (COL_ENABLE_FWD ? "true" : "false") << "/"
142  << (COL_USE_WEB ? "true" : "false") << "/"
143  << (COL_USE_QT ? "true" : "false") << " and IP:Port:FwdPort " << fwdIP
144  << ":" << fwdPort << ":" << destFwdPort << " in MesageFacility table."
145  << __E__;
146  break; // take first enable row only!
147  } // end record loop
148 
149  if(useWeb && useQT)
150  {
151  __SS__ << "Illegal Message Facility table: "
152  << "Can only enable Web Console or QT Viewer, not both." << std::endl;
153  __SS_THROW__;
154  }
155 
156  std::fstream bfs;
157  // output use web bool for StartOTS.sh
158  bfs.open(USE_WEB_BOOL_FILE, std::fstream::out | std::fstream::trunc);
159  if(bfs.fail())
160  {
161  __SS__ << "Failed to open boolean Use of Web Console table file: "
162  << USE_WEB_BOOL_FILE << std::endl;
163  __SS_THROW__;
164  }
165  bfs << (useWeb ? 1 : 0);
166  bfs.close();
167 
168  // output use web bool for StartOTS.sh
169  bfs.open(USE_QT_BOOL_FILE, std::fstream::out | std::fstream::trunc);
170  if(bfs.fail())
171  {
172  __SS__ << "Failed to open boolean Use of QT Viewer table file: "
173  << USE_QT_BOOL_FILE << std::endl;
174  __SS_THROW__;
175  }
176  bfs << (useQT ? 1 : 0);
177  bfs.close();
178 
179  if(enableFwd) // write udp forward config
180  {
181  // handle using web gui
182  if(useWeb)
183  {
184  __COUTT__ << "Forwarding to Web GUI at IP:Port:FwdPort " << fwdIP << ":"
185  << fwdPort << ":" << destFwdPort
186  << " with UDP forward MesageFacility." << __E__;
187 
188  fclSs << "otsConsole: {\n";
189  fclSs << "\t"
190  << "type: UDP\n";
191  fclSs << "\t"
192  << "threshold: DEBUG\n";
193  fclSs << "\t"
194  << "filename_delimit: \"" << parseFilename << "\"\n";
195  fclSs << "\t"
196  << "port: " << fwdPort << "\n";
197  fclSs << "\t"
198  << "host: \"" << fwdIP << "\"\n";
199  fclSs << "}\n";
200 
201  fclSs << "console: {\n";
202  fclSs << "\t"
203  << "type: \"OTS\"\n";
204  fclSs << "\t"
205  << "threshold: \"DEBUG\"\n";
206  fclSs << "\t"
207  << "filename_delimit: \"" << parseFilename << "\"\n";
208  fclSs << "\t"
209  << "format_string: \"|%T:%L:%N: %f:%u |\t%m\"\n";
210 
211  fclSs << "\n}\n";
212 
213  // output quiet forwarder config file
214  std::stringstream qtSs;
215  qtSs << "RECEIVE_PORT \t " << fwdPort << "\n";
216  qtSs << "DESTINATION_PORT \t " << destFwdPort << "\n";
217  qtSs << "DESTINATION_IP \t " << fwdIP << "\n";
218 
219  std::fstream qtfs;
220  qtfs.open(QUIET_CFG_FILE, std::fstream::out | std::fstream::trunc);
221  if(qtfs.fail())
222  {
223  __SS__ << "Failed to open Web Console's 'Quiet Forwarder' "
224  "table file: "
225  << QUIET_CFG_FILE << std::endl;
226  __SS_THROW__;
227  }
228  qtfs << qtSs.str();
229  qtfs.close();
230  __COUTT__ << "Wrote " << QUIET_CFG_FILE << ":" << __E__ << qtSs.str()
231  << __E__;
232  }
233 
234  // handle using qt viewer
235  if(useQT)
236  {
237  __COUTT__ << "Forwarding to QT GUI at IP:Port " << fwdIP << ":" << fwdPort
238  << " with UDP forward MesageFacility." << __E__;
239 
240  fclSs << "otsViewer: {\n";
241  fclSs << "\t"
242  << "type: UDP\n";
243  fclSs << "\t"
244  << "threshold: DEBUG\n";
245  fclSs << "\t"
246  << "filename_delimit: \"" << parseFilename << "\"\n";
247  fclSs << "\t"
248  << "port: " << fwdPort << "\n";
249  fclSs << "\t"
250  << "host: \"" << fwdIP << "\"\n";
251  fclSs << "}\n";
252 
253  // output QT Viewer config file
254  std::fstream qtfs;
255  qtfs.open(QT_CFG_FILE, std::fstream::out | std::fstream::trunc);
256  if(qtfs.fail())
257  {
258  __SS__ << "Failed to open QT Message Viewer table file: " << QT_CFG_FILE
259  << std::endl;
260  __SS_THROW__;
261  }
262  qtfs << "receivers: \n{\n";
263  qtfs << "\t"
264  << "syslog: \n{\n";
265  qtfs << "\t\t"
266  << "receiverType: "
267  << "\"UDP\""
268  << "\n";
269  qtfs << "\t\t"
270  << "port: " << fwdPort << "\n";
271  qtfs << "\t}\n"; // close syslog
272  qtfs << "}\n"; // close receivers
273  qtfs << "\n";
274  qtfs << "threshold: "
275  << "DEBUG"
276  << "\n";
277  qtfs.close();
278  }
279  }
280  else // write cout config (not forwarding to external process)
281  {
282  __COUTT__ << "Using cout-only MesageFacility table." << std::endl;
283  fclSs << "console: {\n";
284  fclSs << "\t"
285  << "type: \"OTS\"\n";
286  fclSs << "\t"
287  << "threshold: \"DEBUG\"\n";
288  fclSs << "\t"
289  << "filename_delimit: \"" << parseFilename << "\"\n";
290  fclSs << "\t"
291  << "format_string: \"|%T:%L:%N: %f:%u |\t%m\"\n";
292 
293  fclSs << "\n}\n";
294  }
295 
296  // generate MF_CFG_FILE file
297  std::fstream fs;
298  fs.open(MF_CFG_FILE, std::fstream::out | std::fstream::trunc);
299  if(fs.fail())
300  {
301  __SS__ << "Failed to open Message Facility table file: " << MF_CFG_FILE << __E__;
302  __SS_THROW__;
303  }
304  else
305  __COUTT__ << "Opened.. " << MF_CFG_FILE << __E__;
306 
307  // generate MF_CFG_MF_ARTDAQ_INTERFACE_CFG_FILE file
308  std::fstream artdaqfs;
309  artdaqfs.open(MF_ARTDAQ_INTERFACE_CFG_FILE, std::fstream::out | std::fstream::trunc);
310  if(artdaqfs.fail())
311  {
312  __SS__ << "Failed to open artdaq interface Message Facility table file: "
313  << MF_ARTDAQ_INTERFACE_CFG_FILE << __E__;
314  __SS_THROW__;
315  }
316  else
317  __COUTT__ << "Opened for artdaq.. " << MF_ARTDAQ_INTERFACE_CFG_FILE << __E__;
318 
319  // close MF config files
320  artdaqfs << fclSs.str();
321  // fs << fclSs.str() << "\nfile: {type:\"file\" filename:\"/dev/null\"}\n";
322  fs << fclSs.str() << "\nfile: \"\"\n";
323  fs.close();
324  artdaqfs.close();
325 
326  __COUTT__ << "Wrote " << __E__ << fclSs.str() << __E__;
327 
328 } // end init()
329 
330 DEFINE_OTS_TABLE(MessageFacilityTable)
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
void init(ConfigurationManager *configManager)
Methods.