tdaq-develop-2025-02-12
ARTDAQBoardReaderTable_table.cc
1 #include "otsdaq/Macros/TablePluginMacros.h"
2 #include "otsdaq/TablePlugins/ARTDAQBoardReaderTable.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_artdaqBoardReader-ai.dbg"): \
12  (EPICS_CONFIG_PATH + "/_otsdaq_artdaqBoardReader-ai.dbg") )
13 
14 // clang-format on
15 
16 //==============================================================================
17 ARTDAQBoardReaderTable::ARTDAQBoardReaderTable(void)
18  : TableBase("ARTDAQBoardReaderTable")
19  , ARTDAQTableBase("ARTDAQBoardReaderTable")
20  , SlowControlsTableBase("ARTDAQBoardReaderTable")
21 {
23  // WARNING: the names used in C++ MUST match the Table INFO //
25  // December 2021 started seeing an issue where traceTID is found to be cleared to 0
26  // which crashes TRACE if __COUT__ is used in a Table plugin constructor
27  // This check and re-initialization seems to cover up the issue for now.
28  // Why it is cleared to 0 after the constructor sets it to -1 is still unknown.
29  // Note: it seems to only happen on the first alphabetially ARTDAQ Configure Table plugin.
30  if(traceTID == 0)
31  {
32  std::cout << "ARTDAQBoardReaderTable Before traceTID=" << traceTID << __E__;
33  char buf[40];
34  traceInit(trace_name(TRACE_NAME, __TRACE_FILE__, buf, sizeof(buf)), 0);
35  std::cout << "ARTDAQBoardReaderTable After traceTID=" << traceTID << __E__;
36  __COUT__ << "ARTDAQBoardReaderTable TRACE reinit and Constructed." << __E__;
37  }
38  else
39  __COUT__ << "ARTDAQBoardReaderTable Constructed." << __E__;
40 } // end constructor()
41 
42 //==============================================================================
43 ARTDAQBoardReaderTable::~ARTDAQBoardReaderTable(void) {}
44 
45 //==============================================================================
47 {
48  lastConfigManager_ = configManager;
49 
50  // use isFirstAppInContext to only run once per context, for example to avoid
51  // generating files on local disk multiple times.
52  isFirstAppInContext_ = configManager->isOwnerFirstAppInContext();
53 
54  //__COUTV__(isFirstAppInContext_);
56  return;
57 
58  //if artdaq supervisor is disabled, skip fcl handling
59  if(!ARTDAQTableBase::isARTDAQEnabled(configManager))
60  {
61  __COUT_INFO__ << "ARTDAQ Supervisor is disabled, so skipping fcl handling."
62  << __E__;
63  return;
64  }
65 
66  // make directory just in case
67  mkdir((ARTDAQTableBase::ARTDAQ_FCL_PATH).c_str(), 0755);
68 
69  __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
70  __COUT__ << configManager->__SELF_NODE__ << __E__;
71 
72  // handle fcl file generation, wherever the level of this table
73 
74  // auto readers = lastConfigManager_->getNode(ARTDAQTableBase::getTableName()).getChildren(
75  auto readers = lastConfigManager_->__SELF_NODE__.getChildren(
76  /*default filterMap*/ std::map<std::string /*relative-path*/,
77  std::string /*value*/>(),
78  /*default byPriority*/ false,
79  /*TRUE! onlyStatusTrue*/ true);
80 
81  for(auto& reader : readers)
82  {
83  ARTDAQTableBase::outputBoardReaderFHICL(reader.second);
84  ARTDAQTableBase::flattenFHICL(ARTDAQAppType::BoardReader,
85  reader.second.getValue());
86  }
87 } // end init()
88 
89 //==============================================================================
90 unsigned int ARTDAQBoardReaderTable::slowControlsHandlerConfig(
91  std::stringstream& out,
92  ConfigurationManager* configManager,
93  std::vector<std::pair<std::string /*channelName*/, std::vector<std::string>>>*
94  channelList /*= 0*/
95 ) const
96 {
98  // generate xdaq run parameter file
99 
100  std::string tabStr = "";
101  std::string commentStr = "";
102 
103  // loop through ARTDAQ BoardReader records starting at ARTDAQSupervisorTable
104  std::vector<std::pair<std::string, ConfigurationTree>> artdaqRecords =
105  configManager->getNode("ARTDAQSupervisorTable").getChildren();
106 
107  unsigned int numberOfBoardReaderMetricParameters = 0;
108 
109  for(auto& artdaqPair : artdaqRecords) // start main artdaq record loop
110  {
111  if(artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToBoardReaders_)
112  .isDisconnected())
113  continue;
114 
115  std::vector<std::pair<std::string, ConfigurationTree>> boardReaderRecords =
116  artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToBoardReaders_)
117  .getChildren();
118 
119  for(auto& boardReaderPair :
120  boardReaderRecords) // start main boardReader record loop
121  {
122  if(!boardReaderPair.second.status())
123  continue;
124 
125  try
126  {
127  if(boardReaderPair.second.getNode("daqMetricsLink").isDisconnected())
128  continue;
129 
130  auto daqMetricsLinks =
131  boardReaderPair.second.getNode("daqMetricsLink").getChildren();
132  for(auto& daqMetricsLink :
133  daqMetricsLinks) // start daqMetricsLinks record loop
134  {
135  if(!daqMetricsLink.second.status())
136  continue;
137 
138  if(daqMetricsLink.second.getNode("metricParametersLink")
139  .isDisconnected())
140  continue;
141 
142  // ConfigurationTree slowControlsLink = configManager->getNode("ARTDAQMetricAlarmThresholdsTable");
143  ConfigurationTree slowControlsLink =
144  boardReaderPair.second.getNode("MetricAlarmThresholdsLink");
145 
146  auto metricParametersLinks =
147  daqMetricsLink.second.getNode("metricParametersLink")
148  .getChildren();
149  for(auto& metricParametersLink :
150  metricParametersLinks) // start daq MetricParametersLinks record loop
151  {
152  if(!metricParametersLink.second.status())
153  continue;
154 
155  std::string subsystem =
156  metricParametersLink.second.getNode("metricParameterValue")
157  .getValueWithDefault<std::string>(std::string("TDAQ_") +
158  __ENV__("MU2E_OWNER"));
159  if(subsystem.find("Mu2e:") != std::string::npos)
160  subsystem = subsystem.replace(subsystem.find("Mu2e:"), 5, "");
161  while(subsystem.find("\"") != std::string::npos)
162  subsystem = subsystem.replace(subsystem.find("\""), 1, "");
163 
164  numberOfBoardReaderMetricParameters =
165  slowControlsHandler(out,
166  tabStr,
167  commentStr,
168  subsystem,
169  boardReaderPair.first,
170  slowControlsLink,
171  channelList);
172 
173  __COUT__ << "BoardReader '" << boardReaderPair.first
174  << "' number of metrics for slow controls: "
175  << numberOfBoardReaderMetricParameters << __E__;
176  }
177  }
178  }
179  catch(const std::runtime_error& e)
180  {
181  __COUT_ERR__ << "Ignoring BoardReader error: " << e.what() << __E__;
182  }
183  }
184  }
185 
186  return numberOfBoardReaderMetricParameters;
187 } // end slowControlsHandlerConfig()
188 
189 //==============================================================================
192 {
193  return SLOWCONTROL_PV_FILE_PATH;
194 }
195 
196 DEFINE_OTS_TABLE(ARTDAQBoardReaderTable)
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
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