otsdaq  v1_01_02
 All Classes Namespaces Functions
ARTDAQBoardReaderConfiguration_configuration.cc
1 #include "otsdaq-core/ConfigurationPluginDataFormats/ARTDAQBoardReaderConfiguration.h"
2 #include "otsdaq-core/Macros/ConfigurationPluginMacros.h"
3 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
4 #include "otsdaq-core/ConfigurationPluginDataFormats/XDAQContextConfiguration.h"
5 
6 #include <iostream>
7 #include <fstream> // std::fstream
8 #include <stdio.h>
9 #include <sys/stat.h> //for mkdir
10 
11 using namespace ots;
12 
13 
14 #define ARTDAQ_FCL_PATH std::string(getenv("USER_DATA")) + "/"+ "ARTDAQConfigurations/"
15 #define ARTDAQ_FILE_PREAMBLE "boardReader"
16 
17 //helpers
18 #define OUT out << tabStr << commentStr
19 #define PUSHTAB tabStr += "\t"
20 #define POPTAB tabStr.resize(tabStr.size()-1)
21 #define PUSHCOMMENT commentStr += "# "
22 #define POPCOMMENT commentStr.resize(commentStr.size()-2)
23 
24 
25 //========================================================================================================================
26 ARTDAQBoardReaderConfiguration::ARTDAQBoardReaderConfiguration(void)
27 : ConfigurationBase("ARTDAQBoardReaderConfiguration")
28 {
30  //WARNING: the names used in C++ MUST match the Configuration INFO //
32 
33 }
34 
35 //========================================================================================================================
36 ARTDAQBoardReaderConfiguration::~ARTDAQBoardReaderConfiguration(void)
37 {}
38 
39 //========================================================================================================================
40 void ARTDAQBoardReaderConfiguration::init(ConfigurationManager* configManager)
41 {
42  //make directory just in case
43  mkdir((ARTDAQ_FCL_PATH).c_str(), 0755);
44 
45  __MOUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << std::endl;
46  __MOUT__ << configManager->__SELF_NODE__ << std::endl;
47 
48  const XDAQContextConfiguration *contextConfig = configManager->__GET_CONFIG__(XDAQContextConfiguration);
49 
50  //ConfigurationTree contextNode = configManager->getNode(contextConfig->getConfigurationName());
51 
52  auto childrenMap = configManager->__SELF_NODE__.getChildren();
53 
54  std::string appUID, buffUID, consumerUID;
55  for(auto &child:childrenMap)
56  if(child.second.getNode("Status").getValue<bool>())
57  {
58 // getBoardReaderParents(child.second, contextConfig,
59 // contextNode, appUID, buffUID, consumerUID);
60  outputFHICL(child.second, contextConfig);
61  }
62 }
63 
65 //void ARTDAQBoardReaderConfiguration::getBoardReaderParents(const ConfigurationTree &readerNode,
66 // const ConfigurationTree &contextNode, std::string &applicationUID,
67 // std::string &bufferUID, std::string &consumerUID)
68 //{
69 // //search through all board reader contexts
70 // contextNode.getNode()
71 //}
72 
73 //========================================================================================================================
74 std::string ARTDAQBoardReaderConfiguration::getFHICLFilename(const ConfigurationTree &boardReaderNode)
75 {
76  __MOUT__ << "ARTDAQ BoardReader UID: " << boardReaderNode.getValue() << std::endl;
77  std::string filename = ARTDAQ_FCL_PATH + ARTDAQ_FILE_PREAMBLE + "-";
78  std::string uid = boardReaderNode.getValue();
79  for(unsigned int i=0;i<uid.size();++i)
80  if((uid[i] >= 'a' && uid[i] <= 'z') ||
81  (uid[i] >= 'A' && uid[i] <= 'Z') ||
82  (uid[i] >= '0' && uid[i] <= '9')) //only allow alpha numeric in file name
83  filename += uid[i];
84 
85  filename += ".fcl";
86 
87  __MOUT__ << "fcl: " << filename << std::endl;
88 
89  return filename;
90 }
91 
92 //========================================================================================================================
93 void ARTDAQBoardReaderConfiguration::outputFHICL(const ConfigurationTree &boardReaderNode,
94  const XDAQContextConfiguration *contextConfig)
95 {
96  /*
97  the file will look something like this:
98 
99  daq: {
100  fragment_receiver: {
101  mpi_sync_interval: 50
102 
103  # CommandableFragmentGenerator Configuration:
104  fragment_ids: []
105  fragment_id: -99 # Please define only one of these
106 
107  sleep_on_stop_us: 0
108 
109  requests_enabled: false # Whether to set up the socket for listening for trigger messages
110  request_mode: "Ignored" # Possible values are: Ignored, Single, Buffer, Window
111 
112  data_buffer_depth_fragments: 1000
113  data_buffer_depth_mb: 1000
114 
115  request_port: 3001
116  request_address: "227.128.12.26" # Multicast request address
117 
118  request_window_offset: 0 # Request message contains tzero. Window will be from tzero - offset to tzero + width
119  request_window_width: 0
120  stale_request_timeout: "0xFFFFFFFF" # How long to wait before discarding request messages that are outside the available data
121  request_windows_are_unique: true # If request windows are unique, avoids a copy operation, but the same data point cannot be used for two requests. If this is not anticipated, leave set to "true"
122 
123  separate_data_thread: false # MUST be true for triggers to be applied! If triggering is not desired, but a separate readout thread is, set this to true, triggers_enabled to false and trigger_mode to ignored.
124  separate_monitoring_thread: false # Whether a thread should be started which periodically calls checkHWStatus_, a user-defined function which should be used to check hardware status registers and report to MetricMan.
125  poll_hardware_status: false # Whether checkHWStatus_ will be called, either through the thread or at the start of getNext
126  hardware_poll_interval_us: 1000000 # If hardware monitoring thread is enabled, how often should it call checkHWStatus_
127 
128 
129  # Generated Parameters:
130  generator: ToySimulator
131  fragment_type: TOY1
132  fragment_id: 0
133  board_id: 0
134  starting_fragment_id: 0
135  random_seed: 5780
136  sleep_on_stop_us: 500000
137 
138  # Generator-Specific Configuration:
139 
140  nADCcounts: 40
141 
142  throttle_usecs: 100000
143 
144  distribution_type: 1
145 
146  timestamp_scale_factor: 1
147 
148 
149  destinations: {
150  d2: { transferPluginType: MPI destination_rank: 2 max_fragment_size_words: 2097152}
151  d3: { transferPluginType: MPI destination_rank: 3 max_fragment_size_words: 2097152}
152 
153  }
154  }
155 
156  metrics: {
157  brFile: {
158  metricPluginType: "file"
159  level: 3
160  fileName: "/tmp/boardreader/br_%UID%_metrics.log"
161  uniquify: true
162  }
163  # ganglia: {
164  # metricPluginType: "ganglia"
165  # level: %{ganglia_level}
166  # reporting_interval: 15.0
167  #
168  # configFile: "/etc/ganglia/gmond.conf"
169  # group: "ARTDAQ"
170  # }
171  # msgfac: {
172  # level: %{mf_level}
173  # metricPluginType: "msgFacility"
174  # output_message_application_name: "ARTDAQ Metric"
175  # output_message_severity: 0
176  # }
177  # graphite: {
178  # level: %{graphite_level}
179  # metricPluginType: "graphite"
180  # host: "localhost"
181  # port: 20030
182  # namespace: "artdaq."
183  # }
184  }
185  }
186 
187  */
188 
189  std::string filename = getFHICLFilename(boardReaderNode);
190 
192  //generate xdaq run parameter file
193  std::fstream out;
194 
195  std::string tabStr = "";
196  std::string commentStr = "";
197 
198  out.open(filename, std::fstream::out | std::fstream::trunc);
199  if(out.fail())
200  {
201  __SS__ << "Failed to open ARTDAQ Builder fcl file: " << filename << std::endl;
202  throw std::runtime_error(ss.str());
203  }
204 
205 
206  //--------------------------------------
207  //handle daq
208  OUT << "daq: {\n";
209 
210  //fragment_receiver
211  PUSHTAB;
212  OUT << "fragment_receiver: {\n";
213 
214  PUSHTAB;
215  { //shared parameters
216  auto parametersLink = boardReaderNode.getNode("daqSharedParametersLink");
217  if(!parametersLink.isDisconnected())
218  {
219 
220  auto parameters = parametersLink.getChildren();
221  for(auto &parameter:parameters)
222  {
223  if(!parameter.second.getNode("Enabled").getValue<bool>())
224  PUSHCOMMENT;
225 
226  auto comment = parameter.second.getNode("CommentDescription");
227  OUT << parameter.second.getNode("daqParameterKey").getValue() <<
228  ": " <<
229  parameter.second.getNode("daqParameterValue").getValue()
230  <<
231  (comment.isDefaultValue()?"":("\t # " + comment.getValue())) <<
232  "\n";
233 
234  if(!parameter.second.getNode("Enabled").getValue<bool>())
235  POPCOMMENT;
236  }
237  }
238  OUT << "\n"; //end shared daq board reader parameters
239  }
240  { //unique parameters
241  auto parametersLink = boardReaderNode.getNode("daqUniqueParametersLink");
242  if(!parametersLink.isDisconnected())
243  {
244 
245  auto parameters = parametersLink.getChildren();
246  for(auto &parameter:parameters)
247  {
248  if(!parameter.second.getNode("Enabled").getValue<bool>())
249  PUSHCOMMENT;
250 
251  auto comment = parameter.second.getNode("CommentDescription");
252  OUT << parameter.second.getNode("daqParameterKey").getValue() <<
253  ": " <<
254  parameter.second.getNode("daqParameterValue").getValue()
255  <<
256  (comment.isDefaultValue()?"":("\t # " + comment.getValue())) <<
257  "\n";
258 
259  if(!parameter.second.getNode("Enabled").getValue<bool>())
260  POPCOMMENT;
261  }
262  }
263  OUT << "\n"; //end shared daq board reader parameters
264  }
265 
266  OUT << "destinations: {\n";
267 
268  PUSHTAB;
269  auto destinationsGroup = boardReaderNode.getNode("daqDestinationsLink");
270  if(!destinationsGroup.isDisconnected())
271  {
272  auto destinations = destinationsGroup.getChildren();
273  for(auto &destination:destinations)
274  {
275  unsigned int destinationRank =
276  contextConfig->getARTDAQAppRank(
277  destination.second.getNode("destinationARTDAQContextLink").getValue());
278  OUT << destination.second.getNode("destinationKey").getValue() <<
279  ": {" <<
280  " transferPluginType: " <<
281  destination.second.getNode("transferPluginType").getValue() <<
282  " destination_rank: " <<
283  destinationRank <<
284  " max_fragment_size_words: " <<
285  destination.second.getNode("ARTDAQGlobalConfigurationLink/maxFragmentSizeWords").getValue<unsigned int>() <<
286  "}\n";
287  }
288  }
289  POPTAB;
290  OUT << "}\n\n"; //end destinations
291 
292  POPTAB;
293  OUT << "}\n\n"; //end fragment_receiver
294 
295 
296  OUT << "metrics: {\n";
297 
298  PUSHTAB;
299  auto metricsGroup = boardReaderNode.getNode("daqMetricsLink");
300  if(!metricsGroup.isDisconnected())
301  {
302  auto metrics = metricsGroup.getChildren();
303 
304  for(auto &metric:metrics)
305  {
306  if(!metric.second.getNode("Status").getValue<bool>())
307  PUSHCOMMENT;
308 
309  OUT << metric.second.getNode("metricKey").getValue() <<
310  ": {\n";
311  PUSHTAB;
312 
313  OUT << "metricPluginType: " <<
314  metric.second.getNode("metricPluginType").getValue()
315  << "\n";
316  OUT << "level: " <<
317  metric.second.getNode("metricLevel").getValue()
318  << "\n";
319 
320  auto metricParametersGroup = metric.second.getNode("metricParametersLink");
321  if(!metricParametersGroup.isDisconnected())
322  {
323  auto metricParameters = metricParametersGroup.getChildren();
324  for(auto &metricParameter:metricParameters)
325  {
326  if(!metricParameter.second.getNode("Enabled").getValue<bool>())
327  PUSHCOMMENT;
328 
329  OUT << metricParameter.second.getNode("metricParameterKey").getValue() <<
330  ": " <<
331  metricParameter.second.getNode("metricParameterValue").getValue()
332  << "\n";
333 
334  if(!metricParameter.second.getNode("Enabled").getValue<bool>())
335  POPCOMMENT;
336 
337  }
338  }
339  POPTAB;
340  OUT << "}\n\n"; //end metric
341 
342  if(!metric.second.getNode("Status").getValue<bool>())
343  POPCOMMENT;
344  }
345  }
346  POPTAB;
347  OUT << "}\n\n"; //end metrics
348 
349  POPTAB;
350  OUT << "}\n\n"; //end daq
351 
352 
353  out.close();
354 }
355 
356 DEFINE_OTS_CONFIGURATION(ARTDAQBoardReaderConfiguration)