otsdaq  3.03.00
ARTDAQDataLoggerTable_table.cc
1 #include "otsdaq/Macros/TablePluginMacros.h"
2 #include "otsdaq/TablePlugins/ARTDAQDataLoggerTable.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_artdaqDataLogger-ai.dbg"): \
12  (EPICS_CONFIG_PATH + "/_otsdaq_artdaqDataLogger-ai.dbg") )
13 
14 // clang-format on
15 
16 //==============================================================================
17 ARTDAQDataLoggerTable::ARTDAQDataLoggerTable(void)
18  : TableBase("ARTDAQDataLoggerTable")
19  , ARTDAQTableBase("ARTDAQDataLoggerTable")
20  , SlowControlsTableBase("ARTDAQDataLoggerTable")
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__ << "ARTDAQDataLoggerTable TRACE reinit and Constructed." << __E__;
37  }
38  else
39  __COUT__ << "ARTDAQDataLoggerTable Constructed." << __E__;
40 } // end constructor()
41 
42 //==============================================================================
43 ARTDAQDataLoggerTable::~ARTDAQDataLoggerTable(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__ << lastConfigManager_->__SELF_NODE__ << __E__;
71 
72  // handle fcl file generation, wherever the level of this table
73 
74  auto dataloggers = lastConfigManager_->__SELF_NODE__.getChildren(
75  /*default filterMap*/ std::map<std::string /*relative-path*/,
76  std::string /*value*/>(),
77  /*default byPriority*/ false,
78  /*TRUE! onlyStatusTrue*/ true);
79 
80  for(auto& datalogger : dataloggers)
81  {
83  datalogger.second, ARTDAQTableBase::ARTDAQAppType::DataLogger);
84 
85  ARTDAQTableBase::flattenFHICL(ARTDAQAppType::DataLogger,
86  datalogger.second.getValue());
87  }
88 } // end init()
89 
90 //==============================================================================
91 unsigned int ARTDAQDataLoggerTable::slowControlsHandlerConfig(
92  std::stringstream& out,
93  ConfigurationManager* configManager,
94  std::vector<std::pair<std::string /*channelName*/, std::vector<std::string>>>*
95  channelList /*= 0*/
96 ) const
97 {
99  // generate xdaq run parameter file
100 
101  std::string tabStr = "";
102  std::string commentStr = "";
103 
104  // loop through ARTDAQ DataLogger records starting at ARTDAQSupervisorTable
105  std::vector<std::pair<std::string, ConfigurationTree>> artdaqRecords =
106  configManager->getNode("ARTDAQSupervisorTable").getChildren();
107 
108  unsigned int numberOfDataLoggerMetricParameters = 0;
109 
110  for(auto& artdaqPair : artdaqRecords) // start main artdaq record loop
111  {
112  if(artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDataLoggers_)
113  .isDisconnected())
114  continue;
115 
116  std::vector<std::pair<std::string, ConfigurationTree>> dataLoggerRecords =
117  artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDataLoggers_)
118  .getChildren();
119 
120  for(auto& dataLoggerPair :
121  dataLoggerRecords) // start main dataLogger record loop
122  {
123  if(!dataLoggerPair.second.status())
124  continue;
125 
126  try
127  {
128  if(dataLoggerPair.second.getNode("daqLink").isDisconnected())
129  continue;
130 
131  auto daqLink = dataLoggerPair.second.getNode("daqLink");
132 
133  if(daqLink.getNode("daqMetricsLink").isDisconnected())
134  continue;
135 
136  auto daqMetricsLinks = daqLink.getNode("daqMetricsLink").getChildren();
137  for(auto& daqMetricsLink :
138  daqMetricsLinks) // start daqMetricsLinks record loop
139  {
140  if(!daqMetricsLink.second.status())
141  continue;
142 
143  if(daqMetricsLink.second.getNode("metricParametersLink")
144  .isDisconnected())
145  continue;
146 
147  // ConfigurationTree slowControlsLink = configManager->getNode("ARTDAQMetricAlarmThresholdsTable");
148  ConfigurationTree slowControlsLink =
149  dataLoggerPair.second.getNode("MetricAlarmThresholdsLink");
150 
151  auto metricParametersLinks =
152  daqMetricsLink.second.getNode("metricParametersLink")
153  .getChildren();
154  for(auto& metricParametersLink :
155  metricParametersLinks) // start daq MetricParametersLinks record loop
156  {
157  if(!metricParametersLink.second.status())
158  continue;
159 
160  std::string subsystem =
161  metricParametersLink.second.getNode("metricParameterValue")
162  .getValueWithDefault<std::string>(std::string("TDAQ_") +
163  __ENV__("MU2E_OWNER"));
164  if(subsystem.find("Mu2e:") != std::string::npos)
165  subsystem = subsystem.replace(subsystem.find("Mu2e:"), 5, "");
166  while(subsystem.find("\"") != std::string::npos)
167  subsystem = subsystem.replace(subsystem.find("\""), 1, "");
168 
169  numberOfDataLoggerMetricParameters =
170  slowControlsHandler(out,
171  tabStr,
172  commentStr,
173  subsystem,
174  dataLoggerPair.first,
175  slowControlsLink,
176  channelList);
177 
178  __COUT__ << "DataLogger '" << dataLoggerPair.first
179  << "' number of metrics for slow controls: "
180  << numberOfDataLoggerMetricParameters << __E__;
181  }
182  }
183  }
184  catch(const std::runtime_error& e)
185  {
186  __COUT_ERR__ << "Ignoring DataLogger error: " << e.what() << __E__;
187  }
188  }
189  }
190 
191  return numberOfDataLoggerMetricParameters;
192 } // end slowControlsHandlerConfig()
193 
194 //==============================================================================
197 {
198  return SLOWCONTROL_PV_FILE_PATH;
199 }
200 
201 DEFINE_OTS_TABLE(ARTDAQDataLoggerTable)
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 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, std::string *returnFcl=nullptr)
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