otsdaq  v2_05_02_indev
ARTDAQDispatcherTable_table.cc
1 #include "otsdaq/Macros/TablePluginMacros.h"
2 #include "otsdaq/TablePlugins/ARTDAQDispatcherTable.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_artdaqDispatcher-ai.dbg"): \
13  (EPICS_CONFIG_PATH + "/_otsdaq_artdaqDispatcher-ai.dbg") )
14 
15 // clang-format on
16 
17 //==============================================================================
18 ARTDAQDispatcherTable::ARTDAQDispatcherTable(void)
19  : TableBase("ARTDAQDispatcherTable")
20  , ARTDAQTableBase("ARTDAQDispatcherTable")
21  , SlowControlsTableBase("ARTDAQDispatcherTable")
22 
23 {
25  // WARNING: the names used in C++ MUST match the Table INFO //
27  __COUT__ << "ARTDAQDispatcherTable Constructed." << __E__;
28 } // end constructor()
29 
30 //==============================================================================
31 ARTDAQDispatcherTable::~ARTDAQDispatcherTable(void) {}
32 
33 //==============================================================================
34 void ARTDAQDispatcherTable::init(ConfigurationManager* configManager)
35 {
36  lastConfigManager_ = configManager;
37 
38  // use isFirstAppInContext to only run once per context, for example to avoid
39  // generating files on local disk multiple times.
40  isFirstAppInContext_ = configManager->isOwnerFirstAppInContext();
41 
42  //__COUTV__(isFirstAppInContext);
43  if(!isFirstAppInContext_)
44  return;
45 
46  // make directory just in case
47  mkdir((ARTDAQTableBase::ARTDAQ_FCL_PATH).c_str(), 0755);
48 
49  // __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
50  // __COUT__ << configManager->__SELF_NODE__ << __E__;
51 
52  // handle fcl file generation, wherever the level of this table
53 
54  auto dispatchers = lastConfigManager_->__SELF_NODE__.getChildren(
55  /*default filterMap*/ std::map<std::string /*relative-path*/, std::string /*value*/>(),
56  /*default byPriority*/ false,
57  /*TRUE! onlyStatusTrue*/ true);
58 
59  for(auto& dispatcher : dispatchers)
60  {
61  ARTDAQTableBase::outputDataReceiverFHICL(dispatcher.second, ARTDAQTableBase::ARTDAQAppType::Dispatcher);
62  ARTDAQTableBase::flattenFHICL(ARTDAQAppType::Dispatcher, dispatcher.second.getValue());
63  }
64 
65 } // end init()
66 
67 //==============================================================================
68 unsigned int ARTDAQDispatcherTable::slowControlsHandlerConfig(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 Dispatcher records starting at ARTDAQSupervisorTable
80  std::vector<std::pair<std::string, ConfigurationTree>> artdaqRecords = configManager->getNode("ARTDAQSupervisorTable").getChildren();
81 
82  unsigned int numberOfDispatchers = 0;
83  unsigned int numberOfDispatcherMetricParameters = 0;
84 
85  for(auto& artdaqPair : artdaqRecords) // start main artdaq record loop
86  {
87  if(artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDispatchers_).isDisconnected())
88  continue;
89 
90  std::vector<std::pair<std::string, ConfigurationTree>> dispatcherRecords =
91  artdaqPair.second.getNode(colARTDAQSupervisor_.colLinkToDispatchers_).getChildren();
92 
93  for(auto& dispatcherPair : dispatcherRecords) // start main dispatcher record loop
94  {
95  if(!dispatcherPair.second.status())
96  continue;
97 
98  numberOfDispatchers++;
99 
100  try
101  {
102  if(dispatcherPair.second.getNode("daqLink").isDisconnected())
103  continue;
104 
105  auto daqLink = dispatcherPair.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 = dispatcherPair.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  numberOfDispatcherMetricParameters =
136  slowControlsHandler(out, tabStr, commentStr, subsystem, dispatcherPair.first, slowControlsLink, channelList);
137 
138  __COUT__ << "Dispatcher '" << dispatcherPair.first
139  << "' number of metrics for slow controls: " << numberOfDispatcherMetricParameters << __E__;
140  }
141  }
142  }
143  catch(const std::runtime_error& e)
144  {
145  __COUT_ERR__ << "Ignoring Dispatcher error: " << e.what() << __E__;
146  }
147  }
148  }
149 
150  return numberOfDispatcherMetricParameters;
151 } // end slowControlsHandlerConfig()
152 
153 //==============================================================================
154 // return out file path
155 std::string ARTDAQDispatcherTable::setFilePath() const { return SLOWCONTROL_PV_FILE_PATH; }
156 
157 DEFINE_OTS_TABLE(ARTDAQDispatcherTable)