otsdaq  v2_03_00
ARTDAQBuilderTable_table.cc
1 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
2 #include "otsdaq-core/Macros/TablePluginMacros.h"
3 #include "otsdaq-core/TablePluginDataFormats/ARTDAQBuilderTable.h"
4 #include "otsdaq-core/TablePluginDataFormats/XDAQContextTable.h"
5 
6 #include <stdio.h>
7 #include <sys/stat.h> //for mkdir
8 #include <fstream> // std::fstream
9 #include <iostream>
10 
11 using namespace ots;
12 
13 #define ARTDAQ_FCL_PATH std::string(getenv("USER_DATA")) + "/" + "ARTDAQConfigurations/"
14 #define ARTDAQ_FILE_PREAMBLE "builder"
15 
16 // helpers
17 #define OUT out << tabStr << commentStr
18 #define PUSHTAB tabStr += "\t"
19 #define POPTAB tabStr.resize(tabStr.size() - 1)
20 #define PUSHCOMMENT commentStr += "# "
21 #define POPCOMMENT commentStr.resize(commentStr.size() - 2)
22 
23 //========================================================================================================================
24 ARTDAQBuilderTable::ARTDAQBuilderTable(void) : TableBase("ARTDAQBuilderTable")
25 {
27  // WARNING: the names used in C++ MUST match the Table INFO //
29 }
30 
31 //========================================================================================================================
32 ARTDAQBuilderTable::~ARTDAQBuilderTable(void) {}
33 
34 //========================================================================================================================
35 void ARTDAQBuilderTable::init(ConfigurationManager* configManager)
36 {
37  // make directory just in case
38  mkdir((ARTDAQ_FCL_PATH).c_str(), 0755);
39 
40  __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
41  __COUT__ << configManager->__SELF_NODE__ << __E__;
42 
43  const XDAQContextTable* contextConfig =
44  configManager->__GET_CONFIG__(XDAQContextTable);
45 
46  std::vector<const XDAQContextTable::XDAQContext*> builderContexts =
47  contextConfig->getEventBuilderContexts();
48 
49  // for each aggregator context
50  // output associated fcl config file
51  for(auto& builderContext : builderContexts)
52  {
53  ConfigurationTree builderAppNode = contextConfig->getApplicationNode(
54  configManager,
55  builderContext->contextUID_,
56  builderContext->applications_[0].applicationUID_);
57  ConfigurationTree builderConfigNode = contextConfig->getSupervisorConfigNode(
58  configManager,
59  builderContext->contextUID_,
60  builderContext->applications_[0].applicationUID_);
61 
62  __COUT__ << "Path for this aggregator config is " << builderContext->contextUID_
63  << "/" << builderContext->applications_[0].applicationUID_ << "/"
64  << builderConfigNode.getValueAsString() << __E__;
65 
66  outputFHICL(
67  configManager,
68  builderConfigNode,
69  contextConfig->getARTDAQAppRank(builderContext->contextUID_),
70  contextConfig->getContextAddress(builderContext->contextUID_),
71  contextConfig->getARTDAQDataPort(configManager, builderContext->contextUID_),
72  contextConfig);
73  }
74 }
75 
76 //========================================================================================================================
77 std::string ARTDAQBuilderTable::getFHICLFilename(const ConfigurationTree& builderNode)
78 {
79  __COUT__ << "ARTDAQ Builder UID: " << builderNode.getValue() << __E__;
80  std::string filename = ARTDAQ_FCL_PATH + ARTDAQ_FILE_PREAMBLE + "-";
81  std::string uid = builderNode.getValue();
82  for(unsigned int i = 0; i < uid.size(); ++i)
83  if((uid[i] >= 'a' && uid[i] <= 'z') || (uid[i] >= 'A' && uid[i] <= 'Z') ||
84  (uid[i] >= '0' && uid[i] <= '9')) // only allow alpha numeric in file name
85  filename += uid[i];
86 
87  filename += ".fcl";
88 
89  __COUT__ << "fcl: " << filename << __E__;
90 
91  return filename;
92 }
93 
94 //========================================================================================================================
95 void ARTDAQBuilderTable::outputFHICL(ConfigurationManager* configManager,
96  const ConfigurationTree& builderNode,
97  unsigned int selfRank,
98  std::string selfHost,
99  unsigned int selfPort,
100  const XDAQContextTable* 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_bytes:
115  2097152}
116 
117  }
118  }
119 
120  #SimpleMemoryCheck: { }
121  }
122 
123  daq: {
124  event_builder: {
125  expected_fragments_per_event: 2
126  use_art: true
127  print_event_store_stats: true
128  verbose: false
129  send_requests: true
130  request_port:
131  request_address:
132 
133  sources: {
134  s0: { transferPluginType: MPI source_rank: 0 max_fragment_size_bytes:
135  2097152} s1: { transferPluginType: MPI source_rank: 1 max_fragment_size_bytes:
136  2097152}
137 
138  }
139  }
140  metrics: {
141  evbFile: {
142  metricPluginType: "file"
143  level: 3
144  fileName: "/tmp/eventbuilder/evb_%UID%_metrics.log"
145  uniquify: true
146  }
147  # ganglia: {
148  # metricPluginType: "ganglia"
149  # level: %{ganglia_level}
150  # reporting_interval: 15.0
151  #
152  # configFile: "/etc/ganglia/gmond.conf"
153  # group: "ARTDAQ"
154  # }
155  # msgfac: {
156  # level: %{mf_level}
157  # metricPluginType: "msgFacility"
158  # output_message_application_name: "ARTDAQ Metric"
159  # output_message_severity: 0
160  # }
161  # graphite: {
162  # level: %{graphite_level}
163  # metricPluginType: "graphite"
164  # host: "localhost"
165  # port: 20030
166  # namespace: "artdaq."
167  # }
168  }
169  }
170 
171  outputs: {
172  rootMPIOutput: {
173  module_type: RootMPIOutput
174  #SelectEvents: { SelectEvents: [ pmod2,pmod3 ] }
175  }
176  #normalOutput: {
177  # module_type: RootOutput
178  # fileName: "/tmp/artdaqdemo_eb00_r%06r_sr%02s_%to.root"
179  # #SelectEvents: { SelectEvents: [ pmod2,pmod3 ] }
180  #}
181  }
182 
183  physics: {
184  analyzers: {
185 
186  }
187 
188  producers: {
189  }
190 
191  filters: {
192 
193  prescaleMod2: {
194  module_type: NthEvent
195  nth: 2
196  }
197 
198  prescaleMod3: {
199  module_type: NthEvent
200  nth: 3
201  }
202  }
203 
204  pmod2: [ prescaleMod2 ]
205  pmod3: [ prescaleMod3 ]
206 
207 
208  #a1: [ app, wf ]
209 
210  my_output_modules: [ rootMPIOutput ]
211  #my_output_modules: [ normalOutput ]
212  }
213  source: {
214  module_type: DemoInput
215  waiting_time: 2500000
216  resume_after_timeout: true
217  }
218  process_name: DAQ
219 
220  */
221 
222  std::string filename = getFHICLFilename(builderNode);
223 
225  // generate xdaq run parameter file
226  std::fstream out;
227 
228  std::string tabStr = "";
229  std::string commentStr = "";
230 
231  out.open(filename, std::fstream::out | std::fstream::trunc);
232  if(out.fail())
233  {
234  __SS__ << "Failed to open ARTDAQ Builder fcl file: " << filename << __E__;
235  __SS_THROW__;
236  }
237 
238  //--------------------------------------
239  // header
240  OUT << "###########################################################" << __E__;
241  OUT << "#" << __E__;
242  OUT << "# artdaq builder fcl configuration file produced by otsdaq." << __E__;
243  OUT << "# Creation timestamp: " << StringMacros::getTimestampString() << __E__;
244  OUT << "# Original filename: " << filename << __E__;
245  OUT << "# otsdaq-ARTDAQ Builder UID: " << builderNode.getValue() << __E__;
246  OUT << "#" << __E__;
247  OUT << "###########################################################" << __E__;
248  OUT << "\n\n";
249 
250  // no primary link to table tree for reader node!
251  if(builderNode.isDisconnected())
252  {
253  // create empty fcl
254  OUT << "{}\n\n";
255  out.close();
256  return;
257  }
258 
259  //--------------------------------------
260  // handle services
261  auto services = builderNode.getNode("servicesLink");
262  if(!services.isDisconnected())
263  {
264  OUT << "services: {\n";
265 
266  // scheduler
267  PUSHTAB;
268  OUT << "scheduler: {\n";
269 
270  PUSHTAB;
271  OUT << "fileMode: " << services.getNode("schedulerFileMode").getValue() << "\n";
272  OUT << "errorOnFailureToPut: "
273  << (services.getNode("schedulerErrorOnFailtureToPut").getValue<bool>()
274  ? "true"
275  : "false")
276  << "\n";
277  POPTAB;
278 
279  OUT << "}\n\n";
280 
281  // NetMonTransportServiceInterface
282  OUT << "NetMonTransportServiceInterface: {\n";
283 
284  PUSHTAB;
285  OUT << "service_provider: " <<
286  // services.getNode("NetMonTrasportServiceInterfaceServiceProvider").getEscapedValue()
287  services.getNode("NetMonTrasportServiceInterfaceServiceProvider").getValue()
288  << "\n";
289  OUT << "destinations: {\n";
290 
291  PUSHTAB;
292  auto destinationsGroup =
293  services.getNode("NetMonTrasportServiceInterfaceDestinationsLink");
294  if(!destinationsGroup.isDisconnected())
295  {
296  try
297  {
298  auto destinations = destinationsGroup.getChildren();
299  for(auto& destination : destinations)
300  {
301  auto destinationContextUID =
302  destination.second.getNode("destinationARTDAQContextLink")
303  .getValueAsString();
304 
305  unsigned int destinationRank =
306  contextConfig->getARTDAQAppRank(destinationContextUID);
307  std::string host =
308  contextConfig->getContextAddress(destinationContextUID);
309  unsigned int port = contextConfig->getARTDAQDataPort(
310  configManager, destinationContextUID);
311 
312  // open destination object
313  OUT << destination.second.getNode("destinationKey").getValue()
314  << ": {\n";
315  PUSHTAB;
316 
317  OUT << "transferPluginType: "
318  << destination.second.getNode("transferPluginType").getValue()
319  << __E__;
320 
321  OUT << "destination_rank: " << destinationRank << __E__;
322 
323  try
324  {
325  OUT << "max_fragment_size_bytes: "
326  << destination.second
327  .getNode("ARTDAQGlobalTableLink/maxFragmentSizeBytes")
328  .getValue<unsigned long long>()
329  << __E__;
330  }
331  catch(...)
332  {
333  __SS__ << "The field ARTDAQGlobalTableLink/maxFragmentSizeBytes "
334  "could not be accessed. Make sure the link is valid."
335  << __E__;
336  __SS_THROW__;
337  }
338 
339  OUT << "host_map: [\n";
340  PUSHTAB;
341  OUT << "{\n";
342  PUSHTAB;
343  OUT << "rank: " << destinationRank << __E__;
344  OUT << "host: \"" << host << "\"" << __E__;
345  OUT << "portOffset: " << std::to_string(port) << __E__;
346  POPTAB;
347  OUT << "},\n";
348  OUT << "{\n";
349  PUSHTAB;
350  OUT << "rank: " << selfRank << __E__;
351  OUT << "host: \"" << selfHost << "\"" << __E__;
352  OUT << "portOffset: " << std::to_string(selfPort) << __E__;
353  POPTAB;
354  OUT << "}" << __E__;
355  POPTAB;
356  OUT << "]" << __E__; // close host_map
357 
358  POPTAB;
359  OUT << "}" << __E__; // close destination object
360  }
361  }
362  catch(const std::runtime_error& e)
363  {
364  __SS__ << "Are the Net Monitor Transport Service destinations valid? "
365  "Error occurred looking for Event Builder transport service "
366  "destinations for UID '"
367  << builderNode.getValue() << "': " << e.what() << __E__;
368  __SS_THROW__;
369  }
370  }
371  POPTAB;
372  OUT << "}\n\n"; // end destinations
373 
374  POPTAB;
375  OUT << "}\n\n"; // end NetMonTransportServiceInterface
376 
377  POPTAB;
378  OUT << "}\n\n"; // end services
379  }
380 
381  //--------------------------------------
382  // handle daq
383  auto daq = builderNode.getNode("daqLink");
384  if(!daq.isDisconnected())
385  {
387  OUT << "daq: {\n";
388 
389  // event_builder
390  PUSHTAB;
391  OUT << "event_builder: {\n";
392 
393  PUSHTAB;
394 
395  OUT << "max_fragment_size_bytes: "
396  << daq.getNode("daqEventBuilderMaxFragmentSizeBytes")
397  .getValue<unsigned long long>()
398  << __E__;
399  OUT << "buffer_count: "
400  << daq.getNode("daqEventBuilderBufferCount").getValue<unsigned long long>()
401  << __E__;
402 
403  auto parametersLink = daq.getNode("daqEventBuilderParametersLink");
404  if(!parametersLink.isDisconnected())
405  {
406  auto parameters = parametersLink.getChildren();
407  for(auto& parameter : parameters)
408  {
409  if(!parameter.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
410  .getValue<bool>())
411  PUSHCOMMENT;
412 
413  OUT << parameter.second.getNode("daqParameterKey").getValue() << ": "
414  << parameter.second.getNode("daqParameterValue").getValue() << "\n";
415 
416  if(!parameter.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
417  .getValue<bool>())
418  POPCOMMENT;
419  }
420  }
421  OUT << "\n"; // end daq event builder parameters
422 
423  OUT << "sources: {\n";
424 
425  PUSHTAB;
426  auto sourcesGroup = daq.getNode("daqEventBuilderSourcesLink");
427  if(!sourcesGroup.isDisconnected())
428  {
429  try
430  {
431  auto sources = sourcesGroup.getChildren();
432  for(auto& source : sources)
433  {
434  auto sourceContextUID =
435  source.second.getNode("sourceARTDAQContextLink")
436  .getValueAsString();
437 
438  unsigned int sourceRank =
439  contextConfig->getARTDAQAppRank(sourceContextUID);
440  std::string host = contextConfig->getContextAddress(sourceContextUID);
441  unsigned int port =
442  contextConfig->getARTDAQDataPort(configManager, sourceContextUID);
443 
444  // open source object
445  OUT << source.second.getNode("sourceKey").getValue() << ": {\n";
446  PUSHTAB;
447 
448  OUT << "transferPluginType: "
449  << source.second.getNode("transferPluginType").getValue()
450  << __E__;
451 
452  OUT << "source_rank: " << sourceRank << __E__;
453 
454  try
455  {
456  OUT << "max_fragment_size_bytes: "
457  << source.second
458  .getNode("ARTDAQGlobalTableLink/maxFragmentSizeBytes")
459  .getValue<unsigned long long>()
460  << __E__;
461  }
462  catch(...)
463  {
464  __SS__ << "The field ARTDAQGlobalTableLink/maxFragmentSizeBytes "
465  "could not be accessed. Make sure the link is valid."
466  << __E__;
467  __SS_THROW__;
468  }
469 
470  OUT << "host_map: [\n";
471  PUSHTAB;
472  OUT << "{\n";
473  PUSHTAB;
474  OUT << "rank: " << sourceRank << __E__;
475  OUT << "host: \"" << host << "\"" << __E__;
476  OUT << "portOffset: " << std::to_string(port) << __E__;
477  POPTAB;
478  OUT << "},\n";
479  OUT << "{\n";
480  PUSHTAB;
481  OUT << "rank: " << selfRank << __E__;
482  OUT << "host: \"" << selfHost << "\"" << __E__;
483  OUT << "portOffset: " << std::to_string(selfPort) << __E__;
484  POPTAB;
485  OUT << "}" << __E__;
486  POPTAB;
487  OUT << "]" << __E__; // close host_map
488 
489  POPTAB;
490  OUT << "}" << __E__; // close source object
491  }
492  }
493  catch(const std::runtime_error& e)
494  {
495  __SS__ << "Are the DAQ sources valid? Error occurred looking for Event "
496  "Builder DAQ sources for UID '"
497  << builderNode.getValue() << "': " << e.what() << __E__;
498  __SS_THROW__;
499  }
500  }
501  POPTAB;
502  OUT << "}\n\n"; // end sources
503 
504  POPTAB;
505  OUT << "}\n\n"; // end event builder
506 
507  OUT << "metrics: {\n";
508 
509  PUSHTAB;
510  auto metricsGroup = daq.getNode("daqMetricsLink");
511  if(!metricsGroup.isDisconnected())
512  {
513  auto metrics = metricsGroup.getChildren();
514 
515  for(auto& metric : metrics)
516  {
517  if(!metric.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
518  .getValue<bool>())
519  PUSHCOMMENT;
520 
521  OUT << metric.second.getNode("metricKey").getValue() << ": {\n";
522  PUSHTAB;
523 
524  OUT << "metricPluginType: "
525  << metric.second.getNode("metricPluginType").getValue() << "\n";
526  OUT << "level: " << metric.second.getNode("metricLevel").getValue()
527  << "\n";
528 
529  auto metricParametersGroup =
530  metric.second.getNode("metricParametersLink");
531  if(!metricParametersGroup.isDisconnected())
532  {
533  auto metricParameters = metricParametersGroup.getChildren();
534  for(auto& metricParameter : metricParameters)
535  {
536  if(!metricParameter.second
537  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
538  .getValue<bool>())
539  PUSHCOMMENT;
540 
541  OUT << metricParameter.second.getNode("metricParameterKey")
542  .getValue()
543  << ": "
544  << metricParameter.second.getNode("metricParameterValue")
545  .getValue()
546  << "\n";
547 
548  if(!metricParameter.second
549  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
550  .getValue<bool>())
551  POPCOMMENT;
552  }
553  }
554  POPTAB;
555  OUT << "}\n\n"; // end metric
556 
557  if(!metric.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
558  .getValue<bool>())
559  POPCOMMENT;
560  }
561  }
562  POPTAB;
563  OUT << "}\n\n"; // end metrics
564 
565  POPTAB;
566  OUT << "}\n\n"; // end daq
567  }
568 
569  //--------------------------------------
570  // handle outputs
571  auto outputs = builderNode.getNode("outputsLink");
572  if(!outputs.isDisconnected())
573  {
574  OUT << "outputs: {\n";
575 
576  PUSHTAB;
577 
578  auto outputPlugins = outputs.getChildren();
579  for(auto& outputPlugin : outputPlugins)
580  {
581  if(!outputPlugin.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
582  .getValue<bool>())
583  PUSHCOMMENT;
584 
585  std::string moduleType =
586  outputPlugin.second.getNode("outputModuleType").getValue();
587 
588  OUT << outputPlugin.second.getNode("outputKey").getValue() << ": {\n";
589  PUSHTAB;
590 
591  OUT << "module_type: " << moduleType << "\n";
592 
593  auto pluginParameterLink =
594  outputPlugin.second.getNode("outputModuleParameterLink");
595  if(!pluginParameterLink.isDisconnected())
596  {
597  auto pluginParameters = pluginParameterLink.getChildren();
598  for(auto& pluginParameter : pluginParameters)
599  {
600  if(!pluginParameter.second
601  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
602  .getValue<bool>())
603  PUSHCOMMENT;
604 
605  OUT << pluginParameter.second.getNode("outputParameterKey").getValue()
606  << ": "
607  << pluginParameter.second.getNode("outputParameterValue")
608  .getValue()
609  << "\n";
610 
611  if(!pluginParameter.second
612  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
613  .getValue<bool>())
614  POPCOMMENT;
615  }
616  }
617 
618  // ONLY For output module type 'BinaryNetOuput,' allow destinations
619  auto destinationsGroup =
620  outputPlugin.second.getNode("outputModuleDestinationLink");
621  if(!destinationsGroup.isDisconnected())
622  {
623  try
624  {
625  if(moduleType.find("BinaryNetOuput") == std::string::npos)
626  {
627  __SS__ << "Illegal output module type '" << moduleType
628  << "' to include destinations. Only modules of type "
629  "'BinaryNetOuput' "
630  << "are allowed to have destinations." << __E__;
631  __SS_THROW__;
632  }
633 
634  OUT << "destinations: {\n";
635  PUSHTAB;
636 
637  auto destinations = destinationsGroup.getChildren();
638  for(auto& destination : destinations)
639  try
640  {
641  auto destinationContextUID =
642  destination.second.getNode("destinationARTDAQContextLink")
643  .getValueAsString();
644 
645  unsigned int destinationRank =
646  contextConfig->getARTDAQAppRank(destinationContextUID);
647  std::string host =
648  contextConfig->getContextAddress(destinationContextUID);
649  unsigned int port = contextConfig->getARTDAQDataPort(
650  configManager, destinationContextUID);
651 
652  // open destination object
653  OUT << destination.second.getNode("destinationKey").getValue()
654  << ": {\n";
655  PUSHTAB;
656 
657  OUT << "transferPluginType: "
658  << destination.second.getNode("transferPluginType")
659  .getValue()
660  << __E__;
661 
662  OUT << "destination_rank: " << destinationRank << __E__;
663 
664  try
665  {
666  OUT << "max_fragment_size_bytes: "
667  << destination.second
668  .getNode(
669  "ARTDAQGlobalTableLink/"
670  "maxFragmentSizeBytes")
671  .getValue<unsigned long long>()
672  << __E__;
673  }
674  catch(...)
675  {
676  __SS__
677  << "The field "
678  "ARTDAQGlobalTableLink/maxFragmentSizeBytes could "
679  "not be accessed. Make sure the link is valid."
680  << __E__;
681  __SS_THROW__;
682  }
683 
684  OUT << "host_map: [\n";
685  PUSHTAB;
686  OUT << "{\n";
687  PUSHTAB;
688  OUT << "rank: " << destinationRank << __E__;
689  OUT << "host: \"" << host << "\"" << __E__;
690  OUT << "portOffset: " << std::to_string(port) << __E__;
691  POPTAB;
692  OUT << "},\n";
693  OUT << "{\n";
694  PUSHTAB;
695  OUT << "rank: " << selfRank << __E__;
696  OUT << "host: \"" << selfHost << "\"" << __E__;
697  OUT << "portOffset: " << std::to_string(selfPort) << __E__;
698  POPTAB;
699  OUT << "}" << __E__;
700  POPTAB;
701  OUT << "]" << __E__; // close host_map
702 
703  POPTAB;
704  OUT << "}" << __E__; // close destination object
705  }
706  catch(const std::runtime_error& e)
707  {
708  __SS__ << "Error encountered populating parameters for "
709  "output module destination '"
710  << destination.first
711  << "'... Please verify fields. Here was the error: "
712  << e.what() << __E__;
713  __SS_ONLY_THROW__;
714  }
715 
716  POPTAB;
717  OUT << "}\n\n"; // end destinations
718  }
719  catch(const std::runtime_error& e)
720  {
721  __SS__ << "Are the Output module destinations valid? "
722  "Error occurred looking for Event Builder output module "
723  "destinations for UID '"
724  << outputPlugin.second.getValue() << "': " << e.what()
725  << __E__;
726  __SS_THROW__;
727  }
728  }
729 
730  POPTAB;
731  OUT << "}\n\n"; // end output module
732 
733  if(!outputPlugin.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
734  .getValue<bool>())
735  POPCOMMENT;
736  }
737 
738  POPTAB;
739  OUT << "}\n\n"; // end outputs
740  }
741 
742  //--------------------------------------
743  // handle physics
744  auto physics = builderNode.getNode("physicsLink");
745  if(!physics.isDisconnected())
746  {
748  OUT << "physics: {\n";
749 
750  PUSHTAB;
751 
752  auto analyzers = physics.getNode("analyzersLink");
753  if(!analyzers.isDisconnected())
754  {
756  OUT << "analyzers: {\n";
757 
758  PUSHTAB;
759  auto modules = analyzers.getChildren();
760  for(auto& module : modules)
761  {
762  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
763  .getValue<bool>())
764  PUSHCOMMENT;
765 
766  OUT << module.second.getNode("analyzerKey").getValue() << ": {\n";
767  PUSHTAB;
768  OUT << "module_type: "
769  << module.second.getNode("analyzerModuleType").getValue() << "\n";
770  auto moduleParameterLink =
771  module.second.getNode("analyzerModuleParameterLink");
772  if(!moduleParameterLink.isDisconnected())
773  {
774  auto moduleParameters = moduleParameterLink.getChildren();
775  for(auto& moduleParameter : moduleParameters)
776  {
777  if(!moduleParameter.second
778  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
779  .getValue<bool>())
780  PUSHCOMMENT;
781 
782  OUT << moduleParameter.second.getNode("analyzerParameterKey")
783  .getValue()
784  << ": "
785  << moduleParameter.second.getNode("analyzerParameterValue")
786  .getValue()
787  << "\n";
788 
789  if(!moduleParameter.second
790  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
791  .getValue<bool>())
792  POPCOMMENT;
793  }
794  }
795  POPTAB;
796  OUT << "}\n\n"; // end analyzer module
797 
798  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
799  .getValue<bool>())
800  POPCOMMENT;
801  }
802  POPTAB;
803  OUT << "}\n\n"; // end analyzer
804  }
805 
806  auto producers = physics.getNode("producersLink");
807  if(!producers.isDisconnected())
808  {
810  OUT << "producers: {\n";
811 
812  PUSHTAB;
813  auto modules = producers.getChildren();
814  for(auto& module : modules)
815  {
816  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
817  .getValue<bool>())
818  PUSHCOMMENT;
819 
820  OUT << module.second.getNode("producerKey").getValue() << ": {\n";
821  PUSHTAB;
822  OUT << "module_type: "
823  << module.second.getNode("producerModuleType").getValue() << "\n";
824  auto moduleParameterLink =
825  module.second.getNode("producerModuleParameterLink");
826  if(!moduleParameterLink.isDisconnected())
827  {
828  auto moduleParameters = moduleParameterLink.getChildren();
829  for(auto& moduleParameter : moduleParameters)
830  {
831  if(!moduleParameter.second
832  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
833  .getValue<bool>())
834  PUSHCOMMENT;
835 
836  OUT << moduleParameter.second.getNode("producerParameterKey")
837  .getValue()
838  << ":"
839  << moduleParameter.second.getNode("producerParameterValue")
840  .getValue()
841  << "\n";
842 
843  if(!moduleParameter.second
844  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
845  .getValue<bool>())
846  POPCOMMENT;
847  }
848  }
849  POPTAB;
850  OUT << "}\n\n"; // end producer module
851 
852  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
853  .getValue<bool>())
854  POPCOMMENT;
855  }
856  POPTAB;
857  OUT << "}\n\n"; // end producer
858  }
859 
860  auto filters = physics.getNode("filtersLink");
861  if(!filters.isDisconnected())
862  {
864  OUT << "filters: {\n";
865 
866  PUSHTAB;
867  auto modules = filters.getChildren();
868  for(auto& module : modules)
869  {
870  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
871  .getValue<bool>())
872  PUSHCOMMENT;
873 
874  OUT << module.second.getNode("filterKey").getValue() << ": {\n";
875  PUSHTAB;
876  OUT << "module_type: "
877  << module.second.getNode("filterModuleType").getValue() << "\n";
878  auto moduleParameterLink =
879  module.second.getNode("filterModuleParameterLink");
880  if(!moduleParameterLink.isDisconnected())
881  {
882  auto moduleParameters = moduleParameterLink.getChildren();
883  for(auto& moduleParameter : moduleParameters)
884  {
885  if(!moduleParameter.second
886  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
887  .getValue<bool>())
888  PUSHCOMMENT;
889 
890  OUT << moduleParameter.second.getNode("filterParameterKey")
891  .getValue()
892  << ": "
893  << moduleParameter.second.getNode("filterParameterValue")
894  .getValue()
895  << "\n";
896 
897  if(!moduleParameter.second
898  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
899  .getValue<bool>())
900  POPCOMMENT;
901  }
902  }
903  POPTAB;
904  OUT << "}\n\n"; // end filter module
905 
906  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
907  .getValue<bool>())
908  POPCOMMENT;
909  }
910  POPTAB;
911  OUT << "}\n\n"; // end filter
912  }
913 
914  auto otherParameterLink = physics.getNode("physicsOtherParametersLink");
915  if(!otherParameterLink.isDisconnected())
916  {
918  auto physicsParameters = otherParameterLink.getChildren();
919  for(auto& parameter : physicsParameters)
920  {
921  if(!parameter.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
922  .getValue<bool>())
923  PUSHCOMMENT;
924 
925  OUT << parameter.second.getNode("physicsParameterKey").getValue() << ": "
926  << parameter.second.getNode("physicsParameterValue").getValue()
927  << "\n";
928 
929  if(!parameter.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
930  .getValue<bool>())
931  POPCOMMENT;
932  }
933  }
934  POPTAB;
935  OUT << "}\n\n"; // end physics
936  }
937 
938  //--------------------------------------
939  // handle source
940  auto source = builderNode.getNode("sourceLink");
941  if(!source.isDisconnected())
942  {
943  OUT << "source: {\n";
944 
945  PUSHTAB;
946  OUT << "module_type: " << source.getNode("sourceModuleType").getValue() << "\n";
947  OUT << "waiting_time: " << source.getNode("sourceWaitingTime").getValue() << "\n";
948  OUT << "resume_after_timeout: "
949  << (source.getNode("sourceResumeAfterTimeout").getValue<bool>() ? "true"
950  : "false")
951  << "\n";
952  POPTAB;
953  OUT << "}\n\n"; // end source
954  }
955 
956  //--------------------------------------
957  // handle process_name
958  OUT << "process_name: "
959  << builderNode.getNode(
960  "ARTDAQGlobalTableForProcessNameLink/processNameForBuilders")
961  << "\n";
962 
963  out.close();
964 }
965 
966 DEFINE_OTS_TABLE(ARTDAQBuilderTable)