otsdaq  v1_01_04
 All Classes Namespaces Functions
ARTDAQBuilderConfiguration_configuration.cc
1 #include "otsdaq-core/ConfigurationPluginDataFormats/ARTDAQBuilderConfiguration.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 "builder"
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 ARTDAQBuilderConfiguration::ARTDAQBuilderConfiguration(void)
27 : ConfigurationBase("ARTDAQBuilderConfiguration")
28 , configManager_(0)
29 {
31  //WARNING: the names used in C++ MUST match the Configuration INFO //
33 
34 }
35 
36 //========================================================================================================================
37 ARTDAQBuilderConfiguration::~ARTDAQBuilderConfiguration(void)
38 {}
39 
40 //========================================================================================================================
41 void ARTDAQBuilderConfiguration::init(ConfigurationManager* configManager)
42 {
43  configManager_ = configManager;
44  //make directory just in case
45  mkdir((ARTDAQ_FCL_PATH).c_str(), 0755);
46 
47  __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << std::endl;
48  __COUT__ << configManager->__SELF_NODE__ << std::endl;
49 
50  const XDAQContextConfiguration *contextConfig = configManager_->__GET_CONFIG__(XDAQContextConfiguration);
51 
52 // auto childrenMap = configManager->__SELF_NODE__.getChildren();
53 //
54 // for(auto &child:childrenMap)
55 // if(child.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
56 // outputFHICL(child.second, contextConfig);
57 
58  std::vector<const XDAQContextConfiguration::XDAQContext *> builderContexts =
59  contextConfig->getEventBuilderContexts();
60 
61  //for each aggregator context
62  // output associated fcl config file
63  for(auto &builderContext: builderContexts)
64  {
65  ConfigurationTree builderConfigNode = contextConfig->getSupervisorConfigNode(configManager,
66  builderContext->contextUID_, builderContext->applications_[0].applicationUID_);
67 
68  __COUT__ << "Path for this aggregator config is " <<
69  builderContext->contextUID_ << "/" <<
70  builderContext->applications_[0].applicationUID_ << "/" <<
71  builderConfigNode.getValueAsString() <<
72  std::endl;
73 
74  outputFHICL(builderConfigNode,
75  contextConfig);
76  }
77 }
78 
79 //========================================================================================================================
80 std::string ARTDAQBuilderConfiguration::getFHICLFilename(const ConfigurationTree &builderNode)
81 {
82  __COUT__ << "ARTDAQ Builder UID: " << builderNode.getValue() << std::endl;
83  std::string filename = ARTDAQ_FCL_PATH + ARTDAQ_FILE_PREAMBLE + "-";
84  std::string uid = builderNode.getValue();
85  for(unsigned int i=0;i<uid.size();++i)
86  if((uid[i] >= 'a' && uid[i] <= 'z') ||
87  (uid[i] >= 'A' && uid[i] <= 'Z') ||
88  (uid[i] >= '0' && uid[i] <= '9')) //only allow alpha numeric in file name
89  filename += uid[i];
90 
91  filename += ".fcl";
92 
93  __COUT__ << "fcl: " << filename << std::endl;
94 
95  return filename;
96 }
97 
98 //========================================================================================================================
99 void ARTDAQBuilderConfiguration::outputFHICL(const ConfigurationTree &builderNode,
100  const XDAQContextConfiguration *contextConfig)
101 {
102  /*
103  the file will look something like this:
104 
105  services: {
106  scheduler: {
107  fileMode: NOMERGE
108  errorOnFailureToPut: false
109  }
110  NetMonTransportServiceInterface: {
111  service_provider: NetMonTransportService
112  #broadcast_sends: true
113  destinations: {
114  d4: { transferPluginType: MPI destination_rank: 4 max_fragment_size_words: 2097152}
115 
116  }
117  }
118 
119  #SimpleMemoryCheck: { }
120  }
121 
122  daq: {
123  event_builder: {
124  expected_fragments_per_event: 2
125  use_art: true
126  print_event_store_stats: true
127  verbose: false
128  send_requests: true
129  request_port:
130  request_address:
131 
132  sources: {
133  s0: { transferPluginType: MPI source_rank: 0 max_fragment_size_words: 2097152}
134  s1: { transferPluginType: MPI source_rank: 1 max_fragment_size_words: 2097152}
135 
136  }
137  }
138  metrics: {
139  evbFile: {
140  metricPluginType: "file"
141  level: 3
142  fileName: "/tmp/eventbuilder/evb_%UID%_metrics.log"
143  uniquify: true
144  }
145  # ganglia: {
146  # metricPluginType: "ganglia"
147  # level: %{ganglia_level}
148  # reporting_interval: 15.0
149  #
150  # configFile: "/etc/ganglia/gmond.conf"
151  # group: "ARTDAQ"
152  # }
153  # msgfac: {
154  # level: %{mf_level}
155  # metricPluginType: "msgFacility"
156  # output_message_application_name: "ARTDAQ Metric"
157  # output_message_severity: 0
158  # }
159  # graphite: {
160  # level: %{graphite_level}
161  # metricPluginType: "graphite"
162  # host: "localhost"
163  # port: 20030
164  # namespace: "artdaq."
165  # }
166  }
167  }
168 
169  outputs: {
170  rootMPIOutput: {
171  module_type: RootMPIOutput
172  #SelectEvents: { SelectEvents: [ pmod2,pmod3 ] }
173  }
174  #normalOutput: {
175  # module_type: RootOutput
176  # fileName: "/tmp/artdaqdemo_eb00_r%06r_sr%02s_%to.root"
177  # #SelectEvents: { SelectEvents: [ pmod2,pmod3 ] }
178  #}
179  }
180 
181  physics: {
182  analyzers: {
183 
184  }
185 
186  producers: {
187  }
188 
189  filters: {
190 
191  prescaleMod2: {
192  module_type: NthEvent
193  nth: 2
194  }
195 
196  prescaleMod3: {
197  module_type: NthEvent
198  nth: 3
199  }
200  }
201 
202  pmod2: [ prescaleMod2 ]
203  pmod3: [ prescaleMod3 ]
204 
205 
206  #a1: [ app, wf ]
207 
208  my_output_modules: [ rootMPIOutput ]
209  #my_output_modules: [ normalOutput ]
210  }
211  source: {
212  module_type: DemoInput
213  waiting_time: 2500000
214  resume_after_timeout: true
215  }
216  process_name: DAQ
217 
218  */
219 
220 
221  std::string filename = getFHICLFilename(builderNode);
222 
224  //generate xdaq run parameter file
225  std::fstream out;
226 
227  std::string tabStr = "";
228  std::string commentStr = "";
229 
230  out.open(filename, std::fstream::out | std::fstream::trunc);
231  if(out.fail())
232  {
233  __SS__ << "Failed to open ARTDAQ Builder fcl file: " << filename << std::endl;
234  throw std::runtime_error(ss.str());
235  }
236 
237 
238  //no primary link to configuration tree for reader node!
239  if(builderNode.isDisconnected())
240  {
241  //create empty fcl
242  OUT << "{}\n\n";
243  out.close();
244  return;
245  }
246 
247 
248  //--------------------------------------
249  //handle services
250  auto services = builderNode.getNode("servicesLink");
251  if(!services.isDisconnected())
252  {
253  OUT << "services: {\n";
254 
255  //scheduler
256  PUSHTAB;
257  OUT << "scheduler: {\n";
258 
259  PUSHTAB;
260  OUT << "fileMode: " << services.getNode("schedulerFileMode").getValue() <<
261  "\n";
262  OUT << "errorOnFailureToPut: " <<
263  (services.getNode("schedulerErrorOnFailtureToPut").getValue<bool>()?"true":"false") <<
264  "\n";
265  POPTAB;
266 
267  OUT << "}\n\n";
268 
269 
270  //NetMonTransportServiceInterface
271  OUT << "NetMonTransportServiceInterface: {\n";
272 
273  PUSHTAB;
274  OUT << "service_provider: " <<
275  //services.getNode("NetMonTrasportServiceInterfaceServiceProvider").getEscapedValue()
276  services.getNode("NetMonTrasportServiceInterfaceServiceProvider").getValue()
277  << "\n";
278  OUT << "destinations: {\n";
279 
280  PUSHTAB;
281  auto destinationsGroup = services.getNode("NetMonTrasportServiceInterfaceDestinationsLink");
282  if(!destinationsGroup.isDisconnected())
283  {
284  try
285  {
286  auto destinations = destinationsGroup.getChildren();
287  for(auto &destination:destinations)
288  {
289  unsigned int destinationRank =
290  contextConfig->getARTDAQAppRank(
291  destination.second.getNode("destinationARTDAQContextLink").getValue());
292  OUT << destination.second.getNode("destinationKey").getValue() <<
293  ": {" <<
294  " transferPluginType: " <<
295  destination.second.getNode("transferPluginType").getValue() <<
296  " destination_rank: " <<
297  destinationRank <<
298  " max_fragment_size_words: " <<
299  destination.second.getNode("ARTDAQGlobalConfigurationLink/maxFragmentSizeWords").getValue<unsigned int>() <<
300  "}\n";
301  }
302  }
303  catch(const std::runtime_error& e)
304  {
305  __SS__ << "Are the Net Monitor Transport Service destinations valid? Error occurred looking for Event Builder transport service destinations for UID '" <<
306  builderNode.getValue() << "': " << e.what() << std::endl;
307  __COUT_ERR__ << ss.str() << std::endl;
308  throw std::runtime_error(ss.str());
309  }
310  }
311  POPTAB;
312  OUT << "}\n\n"; //end destinations
313 
314  POPTAB;
315  OUT << "}\n\n"; //end NetMonTransportServiceInterface
316 
317  POPTAB;
318  OUT << "}\n\n"; //end services
319 
320  }
321 
322  //--------------------------------------
323  //handle daq
324  auto daq = builderNode.getNode("daqLink");
325  if(!daq.isDisconnected())
326  {
328  OUT << "daq: {\n";
329 
330  //event_builder
331  PUSHTAB;
332  OUT << "event_builder: {\n";
333 
334  PUSHTAB;
335  auto parametersLink = daq.getNode("daqEventBuilderParametersLink");
336  if(!parametersLink.isDisconnected())
337  {
338 
339  auto parameters = parametersLink.getChildren();
340  for(auto &parameter:parameters)
341  {
342  if(!parameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
343  PUSHCOMMENT;
344 
345  OUT << parameter.second.getNode("daqParameterKey").getValue() <<
346  ": " <<
347  parameter.second.getNode("daqParameterValue").getValue()
348  << "\n";
349 
350  if(!parameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
351  POPCOMMENT;
352  }
353  }
354  OUT << "\n"; //end daq event builder parameters
355 
356 
357  OUT << "sources: {\n";
358 
359  PUSHTAB;
360  auto sourcesGroup = daq.getNode("daqEventBuilderSourcesLink");
361  if(!sourcesGroup.isDisconnected())
362  {
363  try
364  {
365  auto sources = sourcesGroup.getChildren();
366  for(auto &source:sources)
367  {
368  unsigned int sourceRank =
369  contextConfig->getARTDAQAppRank(
370  source.second.getNode("sourceARTDAQContextLink").getValue());
371 
372  OUT << source.second.getNode("sourceKey").getValue() <<
373  ": {" <<
374  " transferPluginType: " <<
375  source.second.getNode("transferPluginType").getValue() <<
376  " source_rank: " <<
377  sourceRank <<
378  " max_fragment_size_words: " <<
379  source.second.getNode("ARTDAQGlobalConfigurationLink/maxFragmentSizeWords").getValue<unsigned int>() <<
380  "}\n";
381  }
382  }
383  catch(const std::runtime_error& e)
384  {
385  __SS__ << "Are the DAQ sources valid? Error occurred looking for Event Builder DAQ sources for UID '" <<
386  builderNode.getValue() << "': " << e.what() << std::endl;
387  __COUT_ERR__ << ss.str() << std::endl;
388  throw std::runtime_error(ss.str());
389  }
390  }
391  POPTAB;
392  OUT << "}\n\n"; //end sources
393 
394  POPTAB;
395  OUT << "}\n\n"; //end event builder
396 
397 
398  OUT << "metrics: {\n";
399 
400  PUSHTAB;
401  auto metricsGroup = daq.getNode("daqMetricsLink");
402  if(!metricsGroup.isDisconnected())
403  {
404  auto metrics = metricsGroup.getChildren();
405 
406  for(auto &metric:metrics)
407  {
408  if(!metric.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
409  PUSHCOMMENT;
410 
411  OUT << metric.second.getNode("metricKey").getValue() <<
412  ": {\n";
413  PUSHTAB;
414 
415  OUT << "metricPluginType: " <<
416  metric.second.getNode("metricPluginType").getValue()
417  << "\n";
418  OUT << "level: " <<
419  metric.second.getNode("metricLevel").getValue()
420  << "\n";
421 
422  auto metricParametersGroup = metric.second.getNode("metricParametersLink");
423  if(!metricParametersGroup.isDisconnected())
424  {
425  auto metricParameters = metricParametersGroup.getChildren();
426  for(auto &metricParameter:metricParameters)
427  {
428  if(!metricParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
429  PUSHCOMMENT;
430 
431  OUT << metricParameter.second.getNode("metricParameterKey").getValue() <<
432  ": " <<
433  metricParameter.second.getNode("metricParameterValue").getValue()
434  << "\n";
435 
436  if(!metricParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
437  POPCOMMENT;
438 
439  }
440  }
441  POPTAB;
442  OUT << "}\n\n"; //end metric
443 
444  if(!metric.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
445  POPCOMMENT;
446  }
447  }
448  POPTAB;
449  OUT << "}\n\n"; //end metrics
450 
451  POPTAB;
452  OUT << "}\n\n"; //end daq
453  }
454 
455  //--------------------------------------
456  //handle outputs
457  auto outputs = builderNode.getNode("outputsLink");
458  if(!outputs.isDisconnected())
459  {
460  OUT << "outputs: {\n";
461 
462  PUSHTAB;
463 
464  auto outputPlugins = outputs.getChildren();
465  for(auto &outputPlugin:outputPlugins)
466  {
467  if(!outputPlugin.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
468  PUSHCOMMENT;
469 
470  OUT << outputPlugin.second.getNode("outputKey").getValue() <<
471  ": {\n";
472  PUSHTAB;
473  OUT << "module_type: " <<
474  outputPlugin.second.getNode("outputModuleType").getValue() <<
475  "\n";
476  auto pluginParameterLink = outputPlugin.second.getNode("outputModuleParameterLink");
477  if(!pluginParameterLink.isDisconnected())
478  {
479  auto pluginParameters = pluginParameterLink.getChildren();
480  for(auto &pluginParameter:pluginParameters)
481  {
482  if(!pluginParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
483  PUSHCOMMENT;
484 
485  OUT << pluginParameter.second.getNode("outputParameterKey").getValue() <<
486  ": " <<
487  pluginParameter.second.getNode("outputParameterValue").getValue()
488  << "\n";
489 
490  if(!pluginParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
491  POPCOMMENT;
492  }
493  }
494  POPTAB;
495  OUT << "}\n\n"; //end output module
496 
497  if(!outputPlugin.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
498  POPCOMMENT;
499  }
500 
501  POPTAB;
502  OUT << "}\n\n"; //end outputs
503  }
504 
505 
506  //--------------------------------------
507  //handle physics
508  auto physics = builderNode.getNode("physicsLink");
509  if(!physics.isDisconnected())
510  {
512  OUT << "physics: {\n";
513 
514  PUSHTAB;
515 
516  auto analyzers = physics.getNode("analyzersLink");
517  if(!analyzers.isDisconnected())
518  {
520  OUT << "analyzers: {\n";
521 
522  PUSHTAB;
523  auto modules = analyzers.getChildren();
524  for(auto &module:modules)
525  {
526  if(!module.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
527  PUSHCOMMENT;
528 
529  OUT << module.second.getNode("analyzerKey").getValue() <<
530  ": {\n";
531  PUSHTAB;
532  OUT << "module_type: " <<
533  module.second.getNode("analyzerModuleType").getValue() <<
534  "\n";
535  auto moduleParameterLink = module.second.getNode("analyzerModuleParameterLink");
536  if(!moduleParameterLink.isDisconnected())
537  {
538  auto moduleParameters = moduleParameterLink.getChildren();
539  for(auto &moduleParameter:moduleParameters)
540  {
541  if(!moduleParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
542  PUSHCOMMENT;
543 
544  OUT << moduleParameter.second.getNode("analyzerParameterKey").getValue() <<
545  ": " <<
546  moduleParameter.second.getNode("analyzerParameterValue").getValue()
547  << "\n";
548 
549  if(!moduleParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
550  POPCOMMENT;
551  }
552  }
553  POPTAB;
554  OUT << "}\n\n"; //end analyzer module
555 
556  if(!module.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
557  POPCOMMENT;
558  }
559  POPTAB;
560  OUT << "}\n\n"; //end analyzer
561  }
562 
563  auto producers = physics.getNode("producersLink");
564  if(!producers.isDisconnected())
565  {
567  OUT << "producers: {\n";
568 
569  PUSHTAB;
570  auto modules = producers.getChildren();
571  for(auto &module:modules)
572  {
573  if(!module.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
574  PUSHCOMMENT;
575 
576  OUT << module.second.getNode("producerKey").getValue() <<
577  ": {\n";
578  PUSHTAB;
579  OUT << "module_type: " <<
580  module.second.getNode("producerModuleType").getValue() <<
581  "\n";
582  auto moduleParameterLink = module.second.getNode("producerModuleParameterLink");
583  if(!moduleParameterLink.isDisconnected())
584  {
585  auto moduleParameters = moduleParameterLink.getChildren();
586  for(auto &moduleParameter:moduleParameters)
587  {
588  if(!moduleParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
589  PUSHCOMMENT;
590 
591  OUT << moduleParameter.second.getNode("producerParameterKey").getValue() <<
592  ":" <<
593  moduleParameter.second.getNode("producerParameterValue").getValue()
594  << "\n";
595 
596  if(!moduleParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
597  POPCOMMENT;
598  }
599  }
600  POPTAB;
601  OUT << "}\n\n"; //end producer module
602 
603  if(!module.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
604  POPCOMMENT;
605  }
606  POPTAB;
607  OUT << "}\n\n"; //end producer
608  }
609 
610 
611  auto filters = physics.getNode("filtersLink");
612  if(!filters.isDisconnected())
613  {
615  OUT << "filters: {\n";
616 
617  PUSHTAB;
618  auto modules = filters.getChildren();
619  for(auto &module:modules)
620  {
621  if(!module.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
622  PUSHCOMMENT;
623 
624  OUT << module.second.getNode("filterKey").getValue() <<
625  ": {\n";
626  PUSHTAB;
627  OUT << "module_type: " <<
628  module.second.getNode("filterModuleType").getValue() <<
629  "\n";
630  auto moduleParameterLink = module.second.getNode("filterModuleParameterLink");
631  if(!moduleParameterLink.isDisconnected())
632  {
633  auto moduleParameters = moduleParameterLink.getChildren();
634  for(auto &moduleParameter:moduleParameters)
635  {
636  if(!moduleParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
637  PUSHCOMMENT;
638 
639  OUT << moduleParameter.second.getNode("filterParameterKey").getValue()
640  << ": " <<
641  moduleParameter.second.getNode("filterParameterValue").getValue()
642  << "\n";
643 
644  if(!moduleParameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
645  POPCOMMENT;
646  }
647  }
648  POPTAB;
649  OUT << "}\n\n"; //end filter module
650 
651  if(!module.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
652  POPCOMMENT;
653  }
654  POPTAB;
655  OUT << "}\n\n"; //end filter
656  }
657 
658 
659  auto otherParameterLink = physics.getNode("physicsOtherParametersLink");
660  if(!otherParameterLink.isDisconnected())
661  {
663  auto physicsParameters = otherParameterLink.getChildren();
664  for(auto &parameter:physicsParameters)
665  {
666  if(!parameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
667  PUSHCOMMENT;
668 
669  OUT << parameter.second.getNode("physicsParameterKey").getValue() <<
670  ": " <<
671  parameter.second.getNode("physicsParameterValue").getValue()
672  << "\n";
673 
674  if(!parameter.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>())
675  POPCOMMENT;
676  }
677  }
678  POPTAB;
679  OUT << "}\n\n"; //end physics
680  }
681 
682 
683  //--------------------------------------
684  //handle source
685  auto source = builderNode.getNode("sourceLink");
686  if(!source.isDisconnected())
687  {
688  OUT << "source: {\n";
689 
690  PUSHTAB;
691  OUT << "module_type: " << source.getNode("sourceModuleType").getValue() <<
692  "\n";
693  OUT << "waiting_time: " << source.getNode("sourceWaitingTime").getValue() <<
694  "\n";
695  OUT << "resume_after_timeout: " <<
696  (source.getNode("sourceResumeAfterTimeout").getValue<bool>()?"true":"false") <<
697  "\n";
698  POPTAB;
699  OUT << "}\n\n"; //end source
700  }
701 
702  //--------------------------------------
703  //handle process_name
704  OUT << "process_name: " <<
705  builderNode.getNode("ARTDAQGlobalConfigurationForProcessNameLink/processNameForBuilders")
706  << "\n";
707 
708 
709 
710 
711  out.close();
712 }
713 
714 
715 DEFINE_OTS_CONFIGURATION(ARTDAQBuilderConfiguration)