otsdaq  v2_03_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(getenv("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  std::string host = contextConfig->getContextAddress(sourceContextUID);
362  unsigned int sourceRank =
363  contextConfig->getARTDAQAppRank(sourceContextUID);
364  unsigned int port =
365  contextConfig->getARTDAQDataPort(configManager, sourceContextUID);
366 
367  // open source object
368  OUT << source.second.getNode("sourceKey").getValue() << ": {\n";
369  PUSHTAB;
370 
371  OUT << "transferPluginType: "
372  << source.second.getNode("transferPluginType").getValue()
373  << __E__;
374 
375  OUT << "source_rank: " << sourceRank << __E__;
376 
377  try
378  {
379  OUT << "max_fragment_size_bytes: "
380  << source.second
381  .getNode("ARTDAQGlobalTableLink/maxFragmentSizeBytes")
382  .getValue<unsigned long long>()
383  << __E__;
384  }
385  catch(...)
386  {
387  __SS__ << "The field ARTDAQGlobalTableLink/maxFragmentSizeBytes "
388  "could not be accessed. Make sure the link is valid."
389  << __E__;
390  __SS_THROW__;
391  }
392 
393  OUT << "host_map: [\n";
394  PUSHTAB;
395  OUT << "{\n";
396  PUSHTAB;
397  OUT << "rank: " << sourceRank << __E__;
398  OUT << "host: \"" << host << "\"" << __E__;
399  OUT << "portOffset: " << std::to_string(port) << __E__;
400  POPTAB;
401  OUT << "},\n";
402  OUT << "{\n";
403  PUSHTAB;
404  OUT << "rank: " << selfRank << __E__;
405  OUT << "host: \"" << selfHost << "\"" << __E__;
406  OUT << "portOffset: " << std::to_string(selfPort) << __E__;
407  POPTAB;
408  OUT << "}" << __E__;
409  POPTAB;
410  OUT << "]" << __E__; // close host_map
411 
412  POPTAB;
413  OUT << "}" << __E__; // close source object
414  }
415  }
416  catch(const std::runtime_error& e)
417  {
418  __SS__ << "Are the DAQ sources valid? Error occurred looking for "
419  "Aggregator DAQ sources for UID '"
420  << aggregatorNode.getValue() << "': " << e.what() << std::endl;
421  __COUT_ERR__ << ss.str() << std::endl;
422  __SS_THROW__;
423  }
424  }
425  POPTAB;
426  OUT << "}\n\n"; // end sources
427 
428  POPTAB;
429  OUT << "}\n\n"; // end aggregator
430 
431  OUT << "metrics: {\n";
432 
433  PUSHTAB;
434  auto metricsGroup = daq.getNode("daqMetricsLink");
435  if(!metricsGroup.isDisconnected())
436  {
437  auto metrics = metricsGroup.getChildren();
438 
439  for(auto& metric : metrics)
440  {
441  if(!metric.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
442  .getValue<bool>())
443  PUSHCOMMENT;
444 
445  OUT << metric.second.getNode("metricKey").getValue() << ": {\n";
446  PUSHTAB;
447 
448  OUT << "metricPluginType: "
449  << metric.second.getNode("metricPluginType").getValue() << "\n";
450  OUT << "level: " << metric.second.getNode("metricLevel").getValue()
451  << "\n";
452 
453  auto metricParametersGroup =
454  metric.second.getNode("metricParametersLink");
455  if(!metricParametersGroup.isDisconnected())
456  {
457  auto metricParameters = metricParametersGroup.getChildren();
458  for(auto& metricParameter : metricParameters)
459  {
460  if(!metricParameter.second
461  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
462  .getValue<bool>())
463  PUSHCOMMENT;
464 
465  auto comment =
466  metricParameter.second.getNode("CommentDescription");
467  OUT << metricParameter.second.getNode("metricParameterKey")
468  .getValue()
469  << ": "
470  << metricParameter.second.getNode("metricParameterValue")
471  .getValue()
472  << (comment.isDefaultValue() ? ""
473  : ("\t # " + comment.getValue()))
474  << "\n";
475 
476  if(!metricParameter.second
477  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
478  .getValue<bool>())
479  POPCOMMENT;
480  }
481  }
482  POPTAB;
483  OUT << "}\n\n"; // end metric
484 
485  if(!metric.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
486  .getValue<bool>())
487  POPCOMMENT;
488  }
489  }
490  POPTAB;
491  OUT << "}\n\n"; // end metrics
492 
493  OUT << "destinations: {\n";
494 
495  PUSHTAB;
496  // other destinations
497  auto destinationsGroup = daq.getNode("daqAggregatorDestinationsLink");
498  if(!destinationsGroup.isDisconnected())
499  {
500  try
501  {
502  auto destinations = destinationsGroup.getChildren();
503  for(auto& destination : destinations)
504  {
505  auto destinationContextUID =
506  destination.second.getNode("destinationARTDAQContextLink")
507  .getValueAsString();
508 
509  unsigned int destinationRank =
510  contextConfig->getARTDAQAppRank(destinationContextUID);
511  std::string host =
512  contextConfig->getContextAddress(destinationContextUID);
513  unsigned int port = contextConfig->getARTDAQDataPort(
514  configManager, destinationContextUID);
515 
516  // open destination object
517  OUT << destination.second.getNode("destinationKey").getValue()
518  << ": {\n";
519  PUSHTAB;
520 
521  OUT << "transferPluginType: "
522  << destination.second.getNode("transferPluginType").getValue()
523  << __E__;
524 
525  OUT << "source_rank: " << destinationRank << __E__;
526 
527  try
528  {
529  OUT << "max_fragment_size_bytes: "
530  << destination.second
531  .getNode("ARTDAQGlobalTableLink/maxFragmentSizeBytes")
532  .getValue<unsigned long long>()
533  << __E__;
534  }
535  catch(...)
536  {
537  __SS__ << "The field ARTDAQGlobalTableLink/maxFragmentSizeBytes "
538  "could not be accessed. Make sure the link is valid."
539  << __E__;
540  __SS_THROW__;
541  }
542 
543  OUT << "host_map: [\n";
544  PUSHTAB;
545  OUT << "{\n";
546  PUSHTAB;
547  OUT << "rank: " << destinationRank << __E__;
548  OUT << "host: \"" << host << "\"" << __E__;
549  OUT << "portOffset: " << std::to_string(port) << __E__;
550  POPTAB;
551  OUT << "},\n";
552  OUT << "{\n";
553  PUSHTAB;
554  OUT << "rank: " << selfRank << __E__;
555  OUT << "host: \"" << selfHost << "\"" << __E__;
556  OUT << "portOffset: " << std::to_string(selfPort) << __E__;
557  POPTAB;
558  OUT << "}" << __E__;
559  POPTAB;
560  OUT << "]" << __E__; // close host_map
561 
562  POPTAB;
563  OUT << "}" << __E__; // close source object
564  }
565  }
566  catch(const std::runtime_error& e)
567  {
568  __SS__ << "Are the DAQ destinations valid? Error occurred looking for "
569  "Aggregator DAQ destinations for UID '"
570  << aggregatorNode.getValue() << "': " << e.what() << std::endl;
571  __COUT_ERR__ << ss.str() << std::endl;
572  __SS_THROW__;
573  }
574  }
575  POPTAB;
576  OUT << "}\n\n"; // end destinations
577 
578  POPTAB;
579  OUT << "}\n\n"; // end daq
580  }
581 
582  //--------------------------------------
583  // handle source
584  auto source = aggregatorNode.getNode("sourceLink");
585  if(!source.isDisconnected())
586  {
587  OUT << "source: {\n";
588 
589  PUSHTAB;
590  OUT << "module_type: " << source.getNode("sourceModuleType").getValue() << "\n";
591  POPTAB;
592  OUT << "}\n\n"; // end source
593  }
594 
595  //--------------------------------------
596  // handle outputs
597  auto outputs = aggregatorNode.getNode("outputsLink");
598  if(!outputs.isDisconnected())
599  {
600  OUT << "outputs: {\n";
601 
602  PUSHTAB;
603 
604  auto outputPlugins = outputs.getChildren();
605  for(auto& outputPlugin : outputPlugins)
606  {
607  if(!outputPlugin.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
608  .getValue<bool>())
609  PUSHCOMMENT;
610 
611  OUT << outputPlugin.second.getNode("outputKey").getValue() << ": {\n";
612  PUSHTAB;
613  OUT << "module_type: "
614  << outputPlugin.second.getNode("outputModuleType").getValue() << "\n";
615  auto pluginParameterLink =
616  outputPlugin.second.getNode("outputModuleParameterLink");
617  if(!pluginParameterLink.isDisconnected())
618  {
619  auto pluginParameters = pluginParameterLink.getChildren();
620  for(auto& pluginParameter : pluginParameters)
621  {
622  if(!pluginParameter.second
623  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
624  .getValue<bool>())
625  PUSHCOMMENT;
626 
627  auto comment = pluginParameter.second.getNode("CommentDescription");
628  OUT << pluginParameter.second.getNode("outputParameterKey").getValue()
629  << ": "
630  << pluginParameter.second.getNode("outputParameterValue")
631  .getValue()
632  << (comment.isDefaultValue() ? ""
633  : ("\t # " + comment.getValue()))
634  << "\n";
635 
636  if(!pluginParameter.second
637  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
638  .getValue<bool>())
639  POPCOMMENT;
640  }
641  }
642  POPTAB;
643  OUT << "}\n\n"; // end output module
644 
645  if(!outputPlugin.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
646  .getValue<bool>())
647  POPCOMMENT;
648  }
649 
650  POPTAB;
651  OUT << "}\n\n"; // end outputs
652  }
653 
654  //--------------------------------------
655  // handle physics
656  auto physics = aggregatorNode.getNode("physicsLink");
657  if(!physics.isDisconnected())
658  {
660  OUT << "physics: {\n";
661 
662  PUSHTAB;
663 
664  auto analyzers = physics.getNode("analyzersLink");
665  if(!analyzers.isDisconnected())
666  {
668  OUT << "analyzers: {\n";
669 
670  PUSHTAB;
671  auto modules = analyzers.getChildren();
672  for(auto& module : modules)
673  {
674  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
675  .getValue<bool>())
676  PUSHCOMMENT;
677 
678  OUT << module.second.getNode("analyzerKey").getValue() << ": {\n";
679  PUSHTAB;
680  OUT << "module_type: "
681  << module.second.getNode("analyzerModuleType").getValue() << "\n";
682  auto moduleParameterLink =
683  module.second.getNode("analyzerModuleParameterLink");
684  if(!moduleParameterLink.isDisconnected())
685  {
686  auto moduleParameters = moduleParameterLink.getChildren();
687  for(auto& moduleParameter : moduleParameters)
688  {
689  if(!moduleParameter.second
690  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
691  .getValue<bool>())
692  PUSHCOMMENT;
693 
694  auto comment =
695  moduleParameter.second.getNode("CommentDescription");
696  OUT << moduleParameter.second.getNode("analyzerParameterKey")
697  .getValue()
698  << ": "
699  << moduleParameter.second.getNode("analyzerParameterValue")
700  .getValue()
701  << (comment.isDefaultValue() ? ""
702  : ("\t # " + comment.getValue()))
703  << "\n";
704 
705  if(!moduleParameter.second
706  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
707  .getValue<bool>())
708  POPCOMMENT;
709  }
710  }
711  POPTAB;
712  OUT << "}\n\n"; // end analyzer module
713 
714  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
715  .getValue<bool>())
716  POPCOMMENT;
717  }
718  POPTAB;
719  OUT << "}\n\n"; // end analyzer
720  }
721 
722  auto producers = physics.getNode("producersLink");
723  if(!producers.isDisconnected())
724  {
726  OUT << "producers: {\n";
727 
728  PUSHTAB;
729  auto modules = producers.getChildren();
730  for(auto& module : modules)
731  {
732  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
733  .getValue<bool>())
734  PUSHCOMMENT;
735 
736  OUT << module.second.getNode("producerKey").getValue() << ": {\n";
737  PUSHTAB;
738  OUT << "module_type: "
739  << module.second.getNode("producerModuleType").getValue() << "\n";
740  auto moduleParameterLink =
741  module.second.getNode("producerModuleParameterLink");
742  if(!moduleParameterLink.isDisconnected())
743  {
744  auto moduleParameters = moduleParameterLink.getChildren();
745  for(auto& moduleParameter : moduleParameters)
746  {
747  if(!moduleParameter.second
748  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
749  .getValue<bool>())
750  PUSHCOMMENT;
751 
752  auto comment =
753  moduleParameter.second.getNode("CommentDescription");
754  OUT << moduleParameter.second.getNode("producerParameterKey")
755  .getValue()
756  << ":"
757  << moduleParameter.second.getNode("producerParameterValue")
758  .getValue()
759  << (comment.isDefaultValue() ? ""
760  : ("\t # " + comment.getValue()))
761  << "\n";
762 
763  if(!moduleParameter.second
764  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
765  .getValue<bool>())
766  POPCOMMENT;
767  }
768  }
769  POPTAB;
770  OUT << "}\n\n"; // end producer module
771 
772  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
773  .getValue<bool>())
774  POPCOMMENT;
775  }
776  POPTAB;
777  OUT << "}\n\n"; // end producer
778  }
779 
780  auto filters = physics.getNode("filtersLink");
781  if(!filters.isDisconnected())
782  {
784  OUT << "filters: {\n";
785 
786  PUSHTAB;
787  auto modules = filters.getChildren();
788  for(auto& module : modules)
789  {
790  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
791  .getValue<bool>())
792  PUSHCOMMENT;
793 
794  OUT << module.second.getNode("filterKey").getValue() << ": {\n";
795  PUSHTAB;
796  OUT << "module_type: "
797  << module.second.getNode("filterModuleType").getValue() << "\n";
798  auto moduleParameterLink =
799  module.second.getNode("filterModuleParameterLink");
800  if(!moduleParameterLink.isDisconnected())
801  {
802  auto moduleParameters = moduleParameterLink.getChildren();
803  for(auto& moduleParameter : moduleParameters)
804  {
805  if(!moduleParameter.second
806  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
807  .getValue<bool>())
808  PUSHCOMMENT;
809 
810  auto comment =
811  moduleParameter.second.getNode("CommentDescription");
812  OUT << moduleParameter.second.getNode("filterParameterKey")
813  .getValue()
814  << ": "
815  << moduleParameter.second.getNode("filterParameterValue")
816  .getValue()
817  << (comment.isDefaultValue() ? ""
818  : ("\t # " + comment.getValue()))
819  << "\n";
820 
821  if(!moduleParameter.second
822  .getNode(TableViewColumnInfo::COL_NAME_STATUS)
823  .getValue<bool>())
824  POPCOMMENT;
825  }
826  }
827  POPTAB;
828  OUT << "}\n\n"; // end filter module
829 
830  if(!module.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
831  .getValue<bool>())
832  POPCOMMENT;
833  }
834  POPTAB;
835  OUT << "}\n\n"; // end filter
836  }
837 
838  auto otherParameterLink = physics.getNode("physicsOtherParametersLink");
839  if(!otherParameterLink.isDisconnected())
840  {
842  auto physicsParameters = otherParameterLink.getChildren();
843  for(auto& parameter : physicsParameters)
844  {
845  if(!parameter.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
846  .getValue<bool>())
847  PUSHCOMMENT;
848 
849  auto comment = parameter.second.getNode("CommentDescription");
850  OUT << parameter.second.getNode("physicsParameterKey").getValue() << ": "
851  << parameter.second.getNode("physicsParameterValue").getValue()
852  << (comment.isDefaultValue() ? "" : ("\t # " + comment.getValue()))
853  << "\n";
854 
855  if(!parameter.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
856  .getValue<bool>())
857  POPCOMMENT;
858  }
859  }
860  POPTAB;
861  OUT << "}\n\n"; // end physics
862  }
863 
864  //--------------------------------------
865  // handle process_name
866  try
867  {
868  OUT << "process_name: "
869  << aggregatorNode.getNode(
870  "ARTDAQGlobalTableForProcessNameLink/processNameForAggregators")
871  << "\n";
872  }
873  catch(...)
874  {
875  __SS__ << "The field "
876  "ARTDAQGlobalTableForProcessNameLink/processNameForAggregators could "
877  "not be accessed. "
878  << "Make sure the link is valid from aggregator '"
879  << aggregatorNode.getValue() << ".'" << __E__;
880  __SS_THROW__;
881  }
882 
883  out.close();
884 }
885 
886 DEFINE_OTS_TABLE(ARTDAQAggregatorTable)