otsdaq  v2_05_02_indev
ARTDAQDataLoggerTable_table.cc
1 #include "otsdaq/Macros/TablePluginMacros.h"
2 #include "otsdaq/TablePlugins/ARTDAQDataLoggerTable.h"
3 #include "otsdaq/TablePlugins/XDAQContextTable.h"
4 
5 using namespace ots;
6 
7 // clang-format off
8 
9 #define SLOWCONTROL_PV_FILE_PATH \
10  std::string( \
11  getenv("OTSDAQ_EPICS_DATA")? \
12  (std::string(getenv("OTSDAQ_EPICS_DATA")) + "/" + __ENV__("MU2E_OWNER") + "_otsdaq_artdaqDataLogger-ai.dbg"): \
13  (EPICS_CONFIG_PATH + "/_otsdaq_artdaqDataLogger-ai.dbg") )
14 
15 // clang-format on
16 
17 //==============================================================================
18 ARTDAQDataLoggerTable::ARTDAQDataLoggerTable(void)
19  : TableBase("ARTDAQDataLoggerTable")
20  , ARTDAQTableBase("ARTDAQDataLoggerTable")
21  , SlowControlsTableBase("ARTDAQDataLoggerTable")
22 {
24  // WARNING: the names used in C++ MUST match the Table INFO //
26  __COUT__ << "ARTDAQDataLoggerTable Constructed." << __E__;
27 } // end constructor()
28 
29 //==============================================================================
30 ARTDAQDataLoggerTable::~ARTDAQDataLoggerTable(void) {}
31 
32 //==============================================================================
33 void ARTDAQDataLoggerTable::init(ConfigurationManager* configManager)
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);
42  if(!isFirstAppInContext_)
43  return;
44 
45  // make directory just in case
46  mkdir((ARTDAQTableBase::ARTDAQ_FCL_PATH).c_str(), 0755);
47 
48  // __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
49  // __COUT__ << lastConfigManager_->__SELF_NODE__ << __E__;
50 
51  // handle fcl file generation, wherever the level of this table
52 
53  auto dataloggers = lastConfigManager_->__SELF_NODE__.getChildren(
54  /*default filterMap*/ std::map<std::string /*relative-path*/, std::string /*value*/>(),
55  /*default byPriority*/ false,
56  /*TRUE! onlyStatusTrue*/ true);
57 
58  for(auto& datalogger : dataloggers)
59  {
60  ARTDAQTableBase::outputDataReceiverFHICL(datalogger.second, ARTDAQTableBase::ARTDAQAppType::DataLogger);
61 
62  ARTDAQTableBase::flattenFHICL(ARTDAQAppType::DataLogger, datalogger.second.getValue());
63  }
64 }
65 
66 //==============================================================================
67 unsigned int ARTDAQDataLoggerTable::slowControlsHandlerConfig(
68  std::stringstream& out,
69  ConfigurationManager* configManager,
70  std::vector<std::pair<std::string /*channelName*/, std::vector<std::string>>>* channelList /*= 0*/
71 ) const
72 {
74  // generate xdaq run parameter file
75 
76  std::string tabStr = "";
77  std::string commentStr = "";
78 
79  // loop through ARTDAQ DataLogger records starting at ARTDAQSupervisorTable
80  std::vector<std::pair<std::string, ConfigurationTree>> artdaqRecords = configManager->getNode("ARTDAQSupervisorTable").getChildren();
81 
82  unsigned int numberOfDataLoggers = 0;
83  unsigned int numberOfDataLoggerMetricParameters = 0;
84 
85  for(auto& artdaqPair : artdaqRecords) // start main artdaq record loop
86  {
87  if(artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDataLoggers_).isDisconnected())
88  continue;
89 
90  std::vector<std::pair<std::string, ConfigurationTree>> dataLoggerRecords =
91  artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDataLoggers_).getChildren();
92 
93  for(auto& dataLoggerPair : dataLoggerRecords) // start main dataLogger record loop
94  {
95  if(!dataLoggerPair.second.status())
96  continue;
97 
98  numberOfDataLoggers++;
99 
100  try
101  {
102  if(dataLoggerPair.second.getNode("daqLink").isDisconnected())
103  continue;
104 
105  auto daqLink = dataLoggerPair.second.getNode("daqLink");
106 
107  if(daqLink.getNode("daqMetricsLink").isDisconnected())
108  continue;
109 
110  auto daqMetricsLinks = daqLink.getNode("daqMetricsLink").getChildren();
111  for(auto& daqMetricsLink : daqMetricsLinks) // start daqMetricsLinks record loop
112  {
113  if(!daqMetricsLink.second.status())
114  continue;
115 
116  if(daqMetricsLink.second.getNode("metricParametersLink").isDisconnected())
117  continue;
118 
119  // ConfigurationTree slowControlsLink = configManager->getNode("ARTDAQMetricAlarmThresholdsTable");
120  ConfigurationTree slowControlsLink = dataLoggerPair.second.getNode("MetricAlarmThresholdsLink");
121 
122  auto metricParametersLinks = daqMetricsLink.second.getNode("metricParametersLink").getChildren();
123  for(auto& metricParametersLink : metricParametersLinks) // start daq MetricParametersLinks record loop
124  {
125  if(!metricParametersLink.second.status())
126  continue;
127 
128  std::string subsystem = metricParametersLink.second.getNode("metricParameterValue")
129  .getValueWithDefault<std::string>(std::string("TDAQ_") + __ENV__("MU2E_OWNER"));
130  if(subsystem.find("Mu2e:") != std::string::npos)
131  subsystem = subsystem.replace(subsystem.find("Mu2e:"), 5, "");
132  while(subsystem.find("\"") != std::string::npos)
133  subsystem = subsystem.replace(subsystem.find("\""), 1, "");
134 
135  numberOfDataLoggerMetricParameters =
136  slowControlsHandler(out, tabStr, commentStr, subsystem, dataLoggerPair.first, slowControlsLink, channelList);
137 
138  __COUT__ << "DataLogger '" << dataLoggerPair.first << "' number of metrics for slow controls: " << numberOfDataLoggerMetricParameters
139  << __E__;
140  }
141  }
142  }
143  catch(const std::runtime_error& e)
144  {
145  __COUT_ERR__ << "Ignoring DataLogger error: " << e.what() << __E__;
146  }
147  }
148  }
149 
150  return numberOfDataLoggerMetricParameters;
151 } // end slowControlsHandlerConfig()
152 
153 //==============================================================================
154 // return out file path
155 std::string ARTDAQDataLoggerTable::setFilePath() const { return SLOWCONTROL_PV_FILE_PATH; }
156 
157 DEFINE_OTS_TABLE(ARTDAQDataLoggerTable)