tdaq-develop-2025-02-12
ARTDAQDispatcherTable_table.cc
1 #include "otsdaq/Macros/TablePluginMacros.h"
2 #include "otsdaq/TablePlugins/ARTDAQDispatcherTable.h"
3 
4 using namespace ots;
5 
6 // clang-format off
7 
8 #define SLOWCONTROL_PV_FILE_PATH \
9  std::string( \
10  getenv("OTSDAQ_EPICS_DATA")? \
11  (std::string(getenv("OTSDAQ_EPICS_DATA")) + "/" + __ENV__("MU2E_OWNER") + "_otsdaq_artdaqDispatcher-ai.dbg"): \
12  (EPICS_CONFIG_PATH + "/_otsdaq_artdaqDispatcher-ai.dbg") )
13 
14 // clang-format on
15 
16 //==============================================================================
17 ARTDAQDispatcherTable::ARTDAQDispatcherTable(void)
18  : TableBase("ARTDAQDispatcherTable")
19  , ARTDAQTableBase("ARTDAQDispatcherTable")
20  , SlowControlsTableBase("ARTDAQDispatcherTable")
21 
22 {
24  // WARNING: the names used in C++ MUST match the Table INFO //
26  __COUT__ << "ARTDAQDispatcherTable Constructed." << __E__;
27 } // end constructor()
28 
29 //==============================================================================
30 ARTDAQDispatcherTable::~ARTDAQDispatcherTable(void) {}
31 
32 //==============================================================================
34 {
35  lastConfigManager_ = configManager;
36 
37  // use isFirstAppInContext to only run once per context, for example to avoid
38  // generating files on local disk multiple times.
39  isFirstAppInContext_ = configManager->isOwnerFirstAppInContext();
40 
41  //__COUTV__(isFirstAppInContext);
43  return;
44 
45  //if artdaq supervisor is disabled, skip fcl handling
46  if(!ARTDAQTableBase::isARTDAQEnabled(configManager))
47  {
48  __COUT_INFO__ << "ARTDAQ Supervisor is disabled, so skipping fcl handling."
49  << __E__;
50  return;
51  }
52 
53  // make directory just in case
54  mkdir((ARTDAQTableBase::ARTDAQ_FCL_PATH).c_str(), 0755);
55 
56  // __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
57  // __COUT__ << configManager->__SELF_NODE__ << __E__;
58 
59  // handle fcl file generation, wherever the level of this table
60 
61  auto dispatchers = lastConfigManager_->__SELF_NODE__.getChildren(
62  /*default filterMap*/ std::map<std::string /*relative-path*/,
63  std::string /*value*/>(),
64  /*default byPriority*/ false,
65  /*TRUE! onlyStatusTrue*/ true);
66 
67  for(auto& dispatcher : dispatchers)
68  {
70  dispatcher.second, ARTDAQTableBase::ARTDAQAppType::Dispatcher);
71  ARTDAQTableBase::flattenFHICL(ARTDAQAppType::Dispatcher,
72  dispatcher.second.getValue());
73  }
74 
75 } // end init()
76 
77 //==============================================================================
78 unsigned int ARTDAQDispatcherTable::slowControlsHandlerConfig(
79  std::stringstream& out,
80  ConfigurationManager* configManager,
81  std::vector<std::pair<std::string /*channelName*/, std::vector<std::string>>>*
82  channelList /*= 0*/
83 ) const
84 {
86  // generate xdaq run parameter file
87 
88  std::string tabStr = "";
89  std::string commentStr = "";
90 
91  // loop through ARTDAQ Dispatcher records starting at ARTDAQSupervisorTable
92  std::vector<std::pair<std::string, ConfigurationTree>> artdaqRecords =
93  configManager->getNode("ARTDAQSupervisorTable").getChildren();
94 
95  unsigned int numberOfDispatcherMetricParameters = 0;
96 
97  for(auto& artdaqPair : artdaqRecords) // start main artdaq record loop
98  {
99  if(artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDispatchers_)
100  .isDisconnected())
101  continue;
102 
103  std::vector<std::pair<std::string, ConfigurationTree>> dispatcherRecords =
104  artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDispatchers_)
105  .getChildren();
106 
107  for(auto& dispatcherPair :
108  dispatcherRecords) // start main dispatcher record loop
109  {
110  if(!dispatcherPair.second.status())
111  continue;
112 
113  try
114  {
115  if(dispatcherPair.second.getNode("daqLink").isDisconnected())
116  continue;
117 
118  auto daqLink = dispatcherPair.second.getNode("daqLink");
119 
120  if(daqLink.getNode("daqMetricsLink").isDisconnected())
121  continue;
122 
123  auto daqMetricsLinks = daqLink.getNode("daqMetricsLink").getChildren();
124  for(auto& daqMetricsLink :
125  daqMetricsLinks) // start daqMetricsLinks record loop
126  {
127  if(!daqMetricsLink.second.status())
128  continue;
129 
130  if(daqMetricsLink.second.getNode("metricParametersLink")
131  .isDisconnected())
132  continue;
133 
134  // ConfigurationTree slowControlsLink = configManager->getNode("ARTDAQMetricAlarmThresholdsTable");
135  ConfigurationTree slowControlsLink =
136  dispatcherPair.second.getNode("MetricAlarmThresholdsLink");
137 
138  auto metricParametersLinks =
139  daqMetricsLink.second.getNode("metricParametersLink")
140  .getChildren();
141  for(auto& metricParametersLink :
142  metricParametersLinks) // start daq MetricParametersLinks record loop
143  {
144  if(!metricParametersLink.second.status())
145  continue;
146 
147  std::string subsystem =
148  metricParametersLink.second.getNode("metricParameterValue")
149  .getValueWithDefault<std::string>(std::string("TDAQ_") +
150  __ENV__("MU2E_OWNER"));
151  if(subsystem.find("Mu2e:") != std::string::npos)
152  subsystem = subsystem.replace(subsystem.find("Mu2e:"), 5, "");
153  while(subsystem.find("\"") != std::string::npos)
154  subsystem = subsystem.replace(subsystem.find("\""), 1, "");
155 
156  numberOfDispatcherMetricParameters =
157  slowControlsHandler(out,
158  tabStr,
159  commentStr,
160  subsystem,
161  dispatcherPair.first,
162  slowControlsLink,
163  channelList);
164 
165  __COUT__ << "Dispatcher '" << dispatcherPair.first
166  << "' number of metrics for slow controls: "
167  << numberOfDispatcherMetricParameters << __E__;
168  }
169  }
170  }
171  catch(const std::runtime_error& e)
172  {
173  __COUT_ERR__ << "Ignoring Dispatcher error: " << e.what() << __E__;
174  }
175  }
176  }
177 
178  return numberOfDispatcherMetricParameters;
179 } // end slowControlsHandlerConfig()
180 
181 //==============================================================================
184 {
185  return SLOWCONTROL_PV_FILE_PATH;
186 }
187 
188 DEFINE_OTS_TABLE(ARTDAQDispatcherTable)
virtual std::string setFilePath() const override
return out file path
void init(ConfigurationManager *configManager) override
Methods.
<virtual so future plugins can inherit from multiple table base classes
static bool isARTDAQEnabled(const ConfigurationManager *cfgMgr)
isARTDAQEnabled
static void outputDataReceiverFHICL(const ConfigurationTree &receiverNode, ARTDAQAppType appType, size_t maxFragmentSizeBytes=DEFAULT_MAX_FRAGMENT_SIZE, size_t routingTimeoutMs=DEFAULT_ROUTING_TIMEOUT_MS, size_t routingRetryCount=DEFAULT_ROUTING_RETRY_COUNT)
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
<virtual so future plugins can inherit from multiple table base classes
bool isFirstAppInContext_
for managing if PV list has changed