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