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