otsdaq  v1_01_04
 All Classes Namespaces Functions
XDAQContextConfiguration_configuration.cc
1 #include "otsdaq-core/ConfigurationPluginDataFormats/XDAQContextConfiguration.h"
2 #include "otsdaq-core/Macros/ConfigurationPluginMacros.h"
3 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
4 
5 #include <iostream>
6 #include <fstream> // std::fstream
7 #include <stdio.h>
8 
9 using namespace ots;
10 
11 
12 #define XDAQ_RUN_FILE std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/"+ std::string(getenv("XDAQ_CONFIGURATION_XML")) + ".xml"
13 //#define XDAQ_SCRIPT std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/"+ "StartXDAQ_gen.sh"
14 //#define ARTDAQ_MPI_SCRIPT std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/"+ "StartMPI_gen.sh"
15 
16 
17 //========================================================================================================================
18 XDAQContextConfiguration::XDAQContextConfiguration(void)
19 : ConfigurationBase("XDAQContextConfiguration")
20 {
22  //WARNING: the names used in C++ MUST match the Configuration INFO //
24 
25  // <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
26  // <ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ConfigurationInfo.xsd">
27  // <CONFIGURATION Name="XDAQContextConfiguration">
28  // <VIEW Name="XDAQ_CONTEXT_CONFIGURATION" Type="File,Database,DatabaseTest">
29  // <COLUMN Type="UID" Name="ContextUID" StorageName="CONTEXT_UID" DataType="VARCHAR2"/>
30  // <COLUMN Type="ChildLink-0" Name="LinkToApplicationConfiguration" StorageName="LINK_TO_APPLICATION_CONFIGURATION" DataType="VARCHAR2"/>
31  // <COLUMN Type="ChildLinkGroupID-0" Name="ApplicationGroupID" StorageName="APPLICATION_GROUP_ID" DataType="VARCHAR2"/>
32  // <COLUMN Type="OnOff" Name="Status" StorageName="STATUS" DataType="VARCHAR2"/>
33  // <COLUMN Type="Data" Name="Id" StorageName="ID" DataType="VARCHAR2"/>
34  // <COLUMN Type="Data" Name="Address" StorageName="ADDRESS" DataType="VARCHAR2"/>
35  // <COLUMN Type="Data" Name="Port" StorageName="PORT" DataType="VARCHAR2"/>
36  // <COLUMN Type="Comment" Name="CommentDescription" StorageName="COMMENT_DESCRIPTION" DataType="VARCHAR2"/>
37  // <COLUMN Type="Author" Name="Author" StorageName="AUTHOR" DataType="VARCHAR2"/>
38  // <COLUMN Type="Timestamp" Name="RecordInsertionTime" StorageName="RECORD_INSERTION_TIME" DataType="TIMESTAMP WITH TIMEZONE"/>
39  // </VIEW>
40  // </CONFIGURATION>
41  // </ROOT>
42 }
43 
44 //========================================================================================================================
45 XDAQContextConfiguration::~XDAQContextConfiguration(void)
46 {}
47 
48 //========================================================================================================================
49 void XDAQContextConfiguration::init(ConfigurationManager* configManager)
50 {
51  extractContexts(configManager);
52 
54  //generate xdaq run parameter file
55  std::fstream fs;
56  fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc);
57  if(fs.fail())
58  {
59  __SS__ << "Failed to open XDAQ run file: " << XDAQ_RUN_FILE << std::endl;
60  throw std::runtime_error(ss.str());
61  }
62  outputXDAQXML((std::ostream &)fs);
63  fs.close();
64 
65 // /////////////////////////
66 // //generate mpi script file
67 // fs.open(ARTDAQ_MPI_SCRIPT, std::fstream::out | std::fstream::trunc);
68 // if(fs.fail())
69 // {
70 // __SS__ << "Failed to open ARTDAQ script file: " << ARTDAQ_MPI_SCRIPT << std::endl;
71 // throw std::runtime_error(ss.str());
72 // }
73 // outputARTDAQScript((std::ostream &)fs);
74 // fs.close();
75 //
76 // /////////////////////////
77 // //generate xdaq script file
78 // fs.open(XDAQ_SCRIPT, std::fstream::out | std::fstream::trunc);
79 // if(fs.fail())
80 // {
81 // __SS__ << "Failed to open XDAQ script file: " << XDAQ_SCRIPT << std::endl;
82 // throw std::runtime_error(ss.str());
83 // }
84 // outputXDAQScript((std::ostream &)fs);
85 // fs.close();
86 }
87 
88 //========================================================================================================================
89 //isARTDAQContext
90 bool XDAQContextConfiguration::isARTDAQContext(const std::string &contextUID)
91 {
92  return (contextUID.find("ART") == 0 ||
93  contextUID.find("ARTDAQ") == 0);
94 }
95 
96 //========================================================================================================================
97 //isARTDAQContext
98 // looks through all active artdaq contexts for UID
99 // throws exception if not found
100 //
101 // if contextUID == "X" (which happens automatically for broken link)
102 // then highest possible rank plus 1 is returned
103 unsigned int XDAQContextConfiguration::getARTDAQAppRank(const std::string &contextUID) const
104 {
105  // __COUT__ << "artdaqContexts_.size() = " <<
106  // artdaqContexts_.size() << std::endl;
107 
108  unsigned int rank = 0;
109 
110  for(auto &i : artdaqBoardReaders_)
111  {
112  if(contexts_[i].contextUID_ == contextUID)
113  return rank;
114  ++rank;
115  }
116  for(auto &i : artdaqEventBuilders_)
117  {
118  if(contexts_[i].contextUID_ == contextUID)
119  return rank;
120  ++rank;
121  }
122  for(auto &i : artdaqAggregators_)
123  {
124  if(contexts_[i].contextUID_ == contextUID)
125  return rank;
126  ++rank;
127  }
128 
129  if(contextUID == "X")
130  return rank; //assume first undefined rank is desired
131 
132  if(!rank)
133  {
134  __COUT__ << "Assuming since there are 0 active ARTDAQ context UID(s), we can ignore rank failure." << std::endl;
135  return -1;
136  }
137  __SS__ << "ARTDAQ rank could not be found for context UID '" <<
138  contextUID << "' - there were " << rank
139  << " active ARTDAQ context UID(s) checked." << std::endl;
140  __COUT_ERR__ << "\n" << ss.str();
141  throw std::runtime_error(ss.str());
142  return -1; //should never happen!
143 }
144 
145 //========================================================================================================================
146 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getBoardReaderContexts() const
147 {
148  std::vector<const XDAQContext *> retVec;
149  for(auto &i : artdaqBoardReaders_)
150  retVec.push_back(&contexts_[i]);
151  return retVec;
152 }
153 //========================================================================================================================
154 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getEventBuilderContexts() const
155 {
156  std::vector<const XDAQContext *> retVec;
157  for(auto &i : artdaqEventBuilders_)
158  retVec.push_back(&contexts_[i]);
159  return retVec;
160 
161 }
162 //========================================================================================================================
163 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getAggregatorContexts() const
164 {
165  std::vector<const XDAQContext *> retVec;
166  for(auto &i : artdaqAggregators_)
167  retVec.push_back(&contexts_[i]);
168  return retVec;
169 }
170 
171 //========================================================================================================================
172 ConfigurationTree XDAQContextConfiguration::getSupervisorConfigNode(ConfigurationManager *configManager,
173  const std::string &contextUID, const std::string &appUID) const
174 {
175  return configManager->__SELF_NODE__.getNode(
176  contextUID + "/" +
177  colContext_.colLinkToApplicationConfiguration_ + "/" +
178  appUID + "/" +
179  colApplication_.colLinkToSupervisorConfiguration_);
180 
181 
182  // auto supervisorConfigLink =
183  // appChild.second.getNode(colApplication_.colLinkToSupervisorConfiguration_);
184  //
185  // contexts_.back().applications_.back().supervisorConfigUID_ =
186  // supervisorConfigLink.getValue();
187  // __COUT__ << "application supervisorConfigUID_ : " <<
188  // supervisorConfigLink.getValueAsString() << std::endl;
189  // if(!supervisorConfigLink.isDisconnected())
190  // {
191  // //add xdaq applications to this context
192  // auto supervisorConfigChildren = supervisorConfigLink.getChildren();
193  // for(auto supervisorConfigChild:supervisorConfigChildren)
194  // {
195  // __COUT__ << "Loop: " << appChild.first << "/" <<
196  // supervisorConfigChild.first << std::endl;
197  // }
198  // }
199  // __COUT__ << "application supervisorConfigUID_ : " <<
200  // contexts_.back().applic
201 }
202 
203 //========================================================================================================================
204 //extractContexts
205 // Could be called by other tables if they need to access the context.
206 // This doesn't re-write config files, it just re-makes constructs in software.
207 void XDAQContextConfiguration::extractContexts(ConfigurationManager* configManager)
208 {
209  //__COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << std::endl;
210  //__COUT__ << configManager->__SELF_NODE__ << std::endl;
211 
212  // __COUT__ << configManager->getNode(this->getConfigurationName()).getValueAsString()
213  // << std::endl;
214 
215  auto children = configManager->__SELF_NODE__.getChildren();
216 
217  contexts_.clear(); //reset
218  artdaqContexts_.clear();
219 
220  artdaqBoardReaders_.clear();
221  artdaqEventBuilders_.clear();
222  artdaqAggregators_.clear();
223 
224  for(auto &child:children)
225  {
226  contexts_.push_back(XDAQContext());
227  //__COUT__ << child.first << std::endl;
228  // __COUT__ << child.second.getNode(colContextUID_) << std::endl;
229 
230  contexts_.back().contextUID_ = child.first;
231 
232  contexts_.back().sourceConfig_ = child.second.getConfigurationName() + "_v" +
233  child.second.getConfigurationVersion().toString() + " @ " +
234  std::to_string(child.second.getConfigurationCreationTime());
235  child.second.getNode(colContext_.colContextUID_ ).getValue(contexts_.back().contextUID_);
236  child.second.getNode(colContext_.colStatus_ ).getValue(contexts_.back().status_);
237  child.second.getNode(colContext_.colId_ ).getValue(contexts_.back().id_);
238  child.second.getNode(colContext_.colAddress_ ).getValue(contexts_.back().address_);
239  child.second.getNode(colContext_.colPort_ ).getValue(contexts_.back().port_);
240 
241  //__COUT__ << contexts_.back().address_ << std::endl;
242  auto appLink = child.second.getNode(colContext_.colLinkToApplicationConfiguration_);
243  if(appLink.isDisconnected())
244  {
245  __SS__ << "Application link is disconnected!" << std::endl;
246  throw std::runtime_error(ss.str());
247  }
248 
249  //add xdaq applications to this context
250  auto appChildren = appLink.getChildren();
251  for(auto appChild:appChildren)
252  {
253  //__COUT__ << "Loop: " << child.first << "/" << appChild.first << std::endl;
254 
255  contexts_.back().applications_.push_back(XDAQApplication());
256 
257  contexts_.back().applications_.back().applicationGroupID_ = child.first;
258  contexts_.back().applications_.back().sourceConfig_ = appChild.second.getConfigurationName() + "_v" +
259  appChild.second.getConfigurationVersion().toString() + " @ " +
260  std::to_string(appChild.second.getConfigurationCreationTime());
261 
262  appChild.second.getNode(colApplication_.colApplicationUID_ ).getValue(contexts_.back().applications_.back().applicationUID_);
263  appChild.second.getNode(colApplication_.colStatus_ ).getValue(contexts_.back().applications_.back().status_);
264  appChild.second.getNode(colApplication_.colClass_ ).getValue(contexts_.back().applications_.back().class_);
265  appChild.second.getNode(colApplication_.colId_ ).getValue(contexts_.back().applications_.back().id_);
266 
267  //convert defaults to values
268  if(appChild.second.getNode(colApplication_.colInstance_ ).isDefaultValue())
269  contexts_.back().applications_.back().instance_ = 1;
270  else
271  appChild.second.getNode(colApplication_.colInstance_ ).getValue(contexts_.back().applications_.back().instance_);
272 
273  if(appChild.second.getNode(colApplication_.colNetwork_ ).isDefaultValue())
274  contexts_.back().applications_.back().network_ = "local";
275  else
276  appChild.second.getNode(colApplication_.colNetwork_ ).getValue(contexts_.back().applications_.back().network_);
277 
278  if(appChild.second.getNode(colApplication_.colGroup_ ).isDefaultValue())
279  contexts_.back().applications_.back().group_ = "daq";
280  else
281  appChild.second.getNode(colApplication_.colGroup_ ).getValue(contexts_.back().applications_.back().group_);
282 
283  appChild.second.getNode(colApplication_.colModule_ ).getValue(contexts_.back().applications_.back().module_);
284 
285 
286  auto appPropertyLink = appChild.second.getNode(colApplication_.colLinkToPropertyConfiguration_);
287  if(!appPropertyLink.isDisconnected())
288  {
289  //add xdaq application properties to this context
290 
291  auto appPropertyChildren = appPropertyLink.getChildren();
292 
293  //__COUT__ << "appPropertyChildren.size() " << appPropertyChildren.size() << std::endl;
294 
295  for(auto appPropertyChild:appPropertyChildren)
296  {
297  contexts_.back().applications_.back().properties_.push_back(XDAQApplicationProperty());
298  contexts_.back().applications_.back().properties_.back().status_ =
299  appPropertyChild.second.getNode(colAppProperty_.colStatus_).getValue<bool>();
300  contexts_.back().applications_.back().properties_.back().name_ =
301  appPropertyChild.second.getNode(colAppProperty_.colPropertyName_).getValue<std::string>();
302  contexts_.back().applications_.back().properties_.back().type_ =
303  appPropertyChild.second.getNode(colAppProperty_.colPropertyType_).getValue<std::string>();
304  contexts_.back().applications_.back().properties_.back().value_ =
305  appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_).getValue<std::string>();
306 
307  //__COUT__ << contexts_.back().applications_.back().properties_.back().name_ << std::endl;
308  }
309  }
310  //else
311  // __COUT__ << "Disconnected." << std::endl;
312  }
313 
314  //check artdaq type
315  if(isARTDAQContext(contexts_.back().contextUID_))
316  {
317  artdaqContexts_.push_back(contexts_.size()-1);
318 
319  if(contexts_.back().applications_.size() != 1)
320  {
321  __SS__ << "ARTDAQ Context '" << contexts_.back().contextUID_ <<
322  "' must have one Application! " <<
323  contexts_.back().applications_.size() << " were found. " << std::endl;
324  throw std::runtime_error(ss.str());
325  }
326 
327  if(!contexts_.back().status_) continue; //skip if disabled
328 
329  if(contexts_.back().applications_[0].class_ == //if board reader
330  "ots::ARTDAQDataManagerSupervisor")
331  artdaqBoardReaders_.push_back(contexts_.size()-1);
332  else if(contexts_.back().applications_[0].class_ == //if event builder
333  "ots::EventBuilderApp")
334  artdaqEventBuilders_.push_back(contexts_.size()-1);
335  else if(contexts_.back().applications_[0].class_ == //if aggregator
336  "ots::AggregatorApp")
337  artdaqAggregators_.push_back(contexts_.size()-1);
338  else
339  {
340  __SS__ << "ARTDAQ Context must be have Application of an allowed class type:\n " <<
341  "\tots::ARTDAQDataManagerSupervisor\n" <<
342  "\tots::EventBuilderApp\n" <<
343  "\tots::AggregatorApp\n" << "\nClass found was " <<
344  contexts_.back().applications_[0].class_ << std::endl;
345  throw std::runtime_error(ss.str());
346  }
347 
348  }
349 
350  }
351 }
352 
353 //========================================================================================================================
354 //void XDAQContextConfiguration::outputXDAQScript(std::ostream &out)
355 //{
356  /*
357  the file will look something like this:
358  #!/bin/sh
359 
360  echo
361  echo
362 
363  echo "Launching XDAQ contexts..."
364 
365  #for each XDAQ context
366  xdaq.exe -p ${CONTEXT_PORT} -e ${XDAQ_ARGS} &
367 
368  */
369 
370 // out << "#!/bin/sh\n\n";
371 //
372 // out << "echo\necho\n\n";
373 //
374 // out << "echo \"Launching XDAQ contexts...\"\n\n";
375 // out << "#for each XDAQ context\n";
376 //
377 //
378 // std::stringstream ss;
379 // int count = 0;
380 // //for each non-"ART" or "ARTDAQ" context make a xdaq entry
381 // for(XDAQContext &context:contexts_)
382 // {
383 // if(isARTDAQContext(context.contextUID_))
384 // continue; //skip if UID does identify as artdaq
385 //
386 // if(!context.status_)
387 // continue; //skip if disabled
388 //
389 // //at this point we have a xdaq context.. so make an xdaq entry
390 //
391 // ++count;
392 // ss << "echo \"xdaq.exe -p " <<
393 // context.port_ << " -e ${XDAQ_ARGS} &\"\n";
394 // ss << "xdaq.exe -p " <<
395 // context.port_ << " -e ${XDAQ_ARGS} & " <<
396 // "#" << context.contextUID_ << "\n";
397 // }
398 //
399 //
400 // if(count == 0) //if no artdaq contexts at all
401 // {
402 // out << "echo \"No XDAQ (non-artdaq) contexts found.\"\n\n";
403 // out << "echo\necho\n";
404 // return;
405 // }
406 //
407 // out << ss.str();
408 //
409 // out << "\n\n";
410 //}
411 
413 //void XDAQContextConfiguration::outputARTDAQScript(std::ostream &out)
414 //{
415  /*
416  the file will look something like this:
417  #!/bin/sh
418 
419 
420  echo
421  echo
422  while [ 1 ]; do
423 
424  echo "Cleaning up old MPI instance..."
425  killall mpirun
426 
427 
428  echo "Starting mpi run..."
429  echo "$1"
430  echo
431  echo
432 
433  echo mpirun $1 \
434  -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT1} -e ${XDAQ_ARGS} : \
435  -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT2} -e ${XDAQ_ARGS} : \
436  -np 1 xdaq.exe -p ${ARTDAQ_BUILDER_PORT} -e ${XDAQ_ARGS} : \
437  -np 1 xdaq.exe -p ${ARTDAQ_AGGREGATOR_PORT} -e ${XDAQ_ARGS} &
438 
439  echo
440  echo
441 
442  ret=mpirun $1 \
443  -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT1} -e ${XDAQ_ARGS} : \
444  -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT2} -e ${XDAQ_ARGS} : \
445  -np 1 xdaq.exe -p ${ARTDAQ_BUILDER_PORT} -e ${XDAQ_ARGS} : \
446  -np 1 xdaq.exe -p ${ARTDAQ_AGGREGATOR_PORT} -e ${XDAQ_ARGS}
447 
448  if [ $ret -eq 0 ]; then
449  exit
450  fi
451 
452  done
453  */
454 
455 // __COUT__ << artdaqContexts_.size() << " total artdaq context(s)." << std::endl;
456 // __COUT__ << artdaqBoardReaders_.size() << " active artdaq board reader(s)." << std::endl;
457 // __COUT__ << artdaqEventBuilders_.size() << " active artdaq event builder(s)." << std::endl;
458 // __COUT__ << artdaqAggregators_.size() << " active artdaq aggregator(s)." << std::endl;
459 //
460 // out << "#!/bin/sh\n\n";
461 //
462 // out << "\techo\n\techo\n\n";
463 // //out << "while [ 1 ]; do\n\n";
464 //
465 // //out << "\techo \"Cleaning up old MPI instance...\"\n";
466 //
467 // out << "\techo \"" <<
468 // artdaqContexts_.size() << " artdaq Contexts." <<
469 // "\"\n";
470 // out << "\techo \"\t" <<
471 // artdaqBoardReaders_.size() << " artdaq board readers." <<
472 // "\"\n";
473 // out << "\techo \"\t" <<
474 // artdaqEventBuilders_.size() << " artdaq event builders." <<
475 // "\"\n";
476 // out << "\techo \"\t" <<
477 // artdaqAggregators_.size() << " artdaq aggregators_." <<
478 // "\"\n";
479 //
480 // //out << "\tkillall mpirun\n";
481 // out << "\techo\n\techo\n\n";
482 //
483 // out << "\techo \"Starting mpi run...\"\n";
484 // out << "\techo \"$1\"\n\techo\n\techo\n\n";
485 //
486 //
487 //
488 // std::stringstream ss,ssUID;
489 // int count = 0;
490 //
491 // //ss << "\tret=`mpirun $1 \\\n"; `
492 //
493 // ss << "\tmpirun $1 \\\n";
494 //
495 // //for each "ART" or "ARTDAQ" context make an mpi entry
496 // //make an mpi entry for board readers, then event builders, then aggregators
497 //
498 // for(auto &i:artdaqBoardReaders_)
499 // {
500 // if(count++) //add line breaks if not first context
501 // ss << ": \\\n";
502 //
503 // ss << " -np 1 xdaq.exe -p " <<
504 // contexts_[i].port_ << " -e ${XDAQ_ARGS} ";
505 //
506 // ssUID << "\n\t#board reader \t context.port_ \t " << contexts_[i].port_ <<
507 // ": \t" << contexts_[i].contextUID_;
508 // }
509 //
510 // for(auto &i:artdaqEventBuilders_)
511 // {
512 // if(count++) //add line breaks if not first context
513 // ss << ": \\\n";
514 //
515 // ss << " -np 1 xdaq.exe -p " <<
516 // contexts_[i].port_ << " -e ${XDAQ_ARGS} ";
517 //
518 // ssUID << "\n\t#event builder \t context.port_ \t " << contexts_[i].port_ <<
519 // ": \t" << contexts_[i].contextUID_;
520 // }
521 //
522 // for(auto &i:artdaqAggregators_)
523 // {
524 // if(count++) //add line breaks if not first context
525 // ss << ": \\\n";
526 //
527 // ss << " -np 1 xdaq.exe -p " <<
528 // contexts_[i].port_ << " -e ${XDAQ_ARGS} ";
529 //
530 // ssUID << "\n\t#aggregator \t context.port_ \t " << contexts_[i].port_ <<
531 // ": \t" << contexts_[i].contextUID_;
532 // }
533 //
534 //
535 // if(count == 0) //if no artdaq contexts at all
536 // {
537 // out << "\techo \"No ARTDAQ contexts found. So no mpirun necessary.\"\n\n";
538 // out << "\techo\necho\n";
539 // return;
540 // }
541 //
542 // out << "\techo \"" << ss.str() << "\""; //print mpirun
543 // out << "\t\n\techo\n\techo\n\n";
544 // out << ssUID.str() << "\n\n";
545 // out << ss.str(); //run mpirun
546 //
547 // out << "\n\n";
548 // //out << ""\tif [ ${ret:-1} -eq 0 ]; then\n\t\texit\n\tfi\n";
549 // //out << "\ndone\n";
550 //}
551 //
552 //========================================================================================================================
553 void XDAQContextConfiguration::outputXDAQXML(std::ostream &out)
554 {
555  //each generated context will look something like this:
556  //<xc:Context id="0" url="http://${SUPERVISOR_SERVER}:${PORT}">
559  //</xc:Context>
560 
561  //print xml header information and declare xc partition
562  out << "<?xml version='1.0'?>\n" <<
563  "<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n" <<
564  "\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n" <<
565  "\t\txmlns:xc\t= \"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
566 
567  //print partition open
568  //for each context
569  // open context
570  // for each app in context
571  // print application
572  // print module
573  // close context
574  //close partition
575 
576  char tmp[200];
577  for(XDAQContext &context:contexts_)
578  {
579 
580  //__COUT__ << context.contextUID_ << std::endl;
581 
582  sprintf(tmp,"\t<!-- ContextUID='%s' sourceConfig='%s' -->",
583  context.contextUID_.c_str(), context.sourceConfig_.c_str());
584  out << tmp << "\n";
585 
586  if(!context.status_) //comment out if disabled
587  out << "\t<!--\n";
588 
589  sprintf(tmp,"\t<xc:Context id=\"%u\" url=\"%s:%u\">", context.id_, context.address_.c_str(), context.port_);
590  out << tmp << "\n\n";
591 
592  for(XDAQApplication &app:context.applications_)
593  {
594  //__COUT__ << app.id_ << std::endl;
595 
596 
597  if(context.status_)
598  {
599  sprintf(tmp,"\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
600  app.applicationGroupID_.c_str(), app.applicationUID_.c_str(), app.sourceConfig_.c_str());
601  out << tmp << "\n";
602 
603  if(!app.status_) //comment out if disabled
604  out << "\t\t<!--\n";
605  }
606 
607  sprintf(tmp,"\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" network=\"%s\" group=\"%s\">\n",
608  app.class_.c_str(), app.id_, app.instance_, app.network_.c_str(), app.group_.c_str());
609  out << tmp;
610 
612  int foundColon = app.class_.rfind(':');
613  if(foundColon >= 0) ++foundColon;
614  out << "\t\t\t<properties xmlns=\"urn:xdaq-application:" <<
615  app.class_.substr(foundColon) <<
616  "\" xsi:type=\"soapenc:Struct\">\n";
617 
618  //__COUT__ << "app.properties_ " << app.properties_.size() << std::endl;
619  for(XDAQApplicationProperty &appProperty:app.properties_)
620  {
621 
622  if(!appProperty.status_)
623  out << "\t\t\t\t<!--\n";
624 
625  sprintf(tmp,"\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
626  appProperty.name_.c_str(),
627  appProperty.type_.c_str(),
628  appProperty.value_.c_str(),
629  appProperty.name_.c_str());
630  out << tmp;
631 
632  if(!appProperty.status_)
633  out << "\t\t\t\t-->\n";
634  }
635  out << "\t\t\t</properties>\n";
637 
638  out << "\t\t</xc:Application>\n";
639 
640 
641  sprintf(tmp,"\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
642  out << tmp;
643 
644  if(context.status_ && !app.status_)
645  out << "\t\t-->\n";
646  out << "\n";
647  }
648 
649  out << "\t</xc:Context>\n";
650  if(!context.status_)
651  out << "\t-->\n";
652  out << "\n";
653  }
654 
655  out << "</xc:Partition>\n\n\n";
656 
657 }
658 
659 //========================================================================================================================
660 std::string XDAQContextConfiguration::getContextUID(const std::string &url) const
661 {
662  for(auto context: contexts_)
663  {
664  if(!context.status_) continue;
665 
666  if(url == context.address_ + ":" + std::to_string(context.port_))
667  return context.contextUID_;
668  }
669  return "";
670 }
671 
672 //========================================================================================================================
673 std::string XDAQContextConfiguration::getApplicationUID(const std::string &url, unsigned int id) const
674 {
675  for(auto context: contexts_)
676  {
677  if(!context.status_) continue;
678 
679  if(url == context.address_ + ":" + std::to_string(context.port_))
680  for(auto application: context.applications_)
681  {
682  if(!application.status_) continue;
683 
684  if(application.id_ == id)
685  {
686  return application.applicationUID_;
687  }
688  }
689  }
690  return "";
691 }
692 
693 DEFINE_OTS_CONFIGURATION(XDAQContextConfiguration)