00001 #include "otsdaq-core/ConfigurationPluginDataFormats/XDAQContextConfiguration.h"
00002 #include "otsdaq-core/Macros/ConfigurationPluginMacros.h"
00003 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
00004
00005 #include <iostream>
00006 #include <fstream>
00007 #include <stdio.h>
00008
00009 using namespace ots;
00010
00011
00012 #define XDAQ_RUN_FILE std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + std::string(getenv("XDAQ_CONFIGURATION_XML")) + ".xml"
00013 #define APP_PRIORITY_FILE std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + "xdaqAppStateMachinePriority"
00014
00015
00016
00017
00018 const std::string XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS = "ots::Supervisor";
00019 const std::string XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS = "ots::GatewaySupervisor";
00020 const std::string XDAQContextConfiguration::WIZARD_SUPERVISOR_CLASS = "ots::WizardSupervisor";
00021 const std::set<std::string> XDAQContextConfiguration::FETypeClassNames_ = {"ots::FESupervisor", "ots::FEDataManagerSupervisor", "ots::ARTDAQFEDataManagerSupervisor"};
00022 const std::set<std::string> XDAQContextConfiguration::DMTypeClassNames_ = {"ots::DataManagerSupervisor", "ots::FEDataManagerSupervisor", "ots::ARTDAQFEDataManagerSupervisor"};
00023 const std::set<std::string> XDAQContextConfiguration::LogbookTypeClassNames_ = {"ots::LogbookSupervisor"};
00024 const std::set<std::string> XDAQContextConfiguration::MacroMakerTypeClassNames_ = {"ots::MacroMakerSupervisor"};
00025 const std::set<std::string> XDAQContextConfiguration::ChatTypeClassNames_ = {"ots::ChatSupervisor"};
00026 const std::set<std::string> XDAQContextConfiguration::ConsoleTypeClassNames_ = {"ots::ConsoleSupervisor"};
00027 const std::set<std::string> XDAQContextConfiguration::ConfigurationGUITypeClassNames_ = {"ots::ConfigurationGUISupervisor"};
00028
00029 const std::string XDAQContextConfiguration::ARTDAQ_OFFSET_PORT = "OffsetPort";
00030
00031
00032 XDAQContextConfiguration::XDAQContextConfiguration(void)
00033 : ConfigurationBase("XDAQContextConfiguration")
00034 {
00036
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 }
00058
00059
00060 XDAQContextConfiguration::~XDAQContextConfiguration(void)
00061 {}
00062
00063
00064 void XDAQContextConfiguration::init(ConfigurationManager* configManager)
00065 {
00066 extractContexts(configManager);
00067
00068 {
00070
00071 std::fstream fs;
00072 fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc);
00073 if (fs.fail())
00074 {
00075 __SS__ << "Failed to open XDAQ run file: " << XDAQ_RUN_FILE << std::endl;
00076 throw std::runtime_error(ss.str());
00077 }
00078 outputXDAQXML((std::ostream &)fs);
00079 fs.close();
00080 }
00081 }
00082
00083
00084
00085 bool XDAQContextConfiguration::isARTDAQContext(const std::string &contextUID)
00086 {
00087 return (contextUID.find("ART") == 0 ||
00088 contextUID.find("ARTDAQ") == 0);
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 unsigned int XDAQContextConfiguration::getARTDAQAppRank(const std::string &contextUID) const
00099 {
00100
00101
00102
00103 if (artdaqBoardReaders_.size() == 0 &&
00104 artdaqEventBuilders_.size() == 0 &&
00105 artdaqAggregators_.size() == 0)
00106 {
00107 __COUT_WARN__ << "Assuming since there are 0 active ARTDAQ context UID(s), we can ignore rank failure." << std::endl;
00108 return -1;
00109 }
00110
00111
00112 auto localGetRank = [](const XDAQContext& context) -> unsigned int {
00113 if(context.applications_.size() != 1)
00114 {
00115 __SS__ << "Invalid number of ARTDAQ applications in context '" <<
00116 context.contextUID_ <<
00117 ".' Must be 1. Currently is " << context.applications_.size() << "." << __E__;
00118 __SS_THROW__;
00119 }
00120
00121 return context.applications_[0].id_;
00122 };
00123
00124
00125 for (auto &i : artdaqBoardReaders_)
00126 if (contexts_[i].contextUID_ == contextUID)
00127 return localGetRank(contexts_[i]);
00128
00129 for (auto &i : artdaqEventBuilders_)
00130 if (contexts_[i].contextUID_ == contextUID)
00131 return localGetRank(contexts_[i]);
00132
00133 for (auto &i : artdaqAggregators_)
00134 if (contexts_[i].contextUID_ == contextUID)
00135 return localGetRank(contexts_[i]);
00136
00137
00138
00139
00140
00141
00142 __SS__ << "ARTDAQ rank could not be found for context UID '" <<
00143 contextUID << ".'" << std::endl;
00144 __SS_THROW__;
00145 }
00146
00147
00148 std::string XDAQContextConfiguration::getContextAddress(const std::string &contextUID, bool wantHttp) const
00149 {
00150 if (contextUID == "X") return "";
00151 for (auto& context : contexts_)
00152 {
00153 if (context.contextUID_ == contextUID)
00154 {
00155 if (wantHttp) return context.address_;
00156 auto address = context.address_;
00157 if (address.find("http://") == 0) { address = address.replace(0,7, ""); }
00158 if (address.find("https://") == 0) { address = address.replace(0,8, ""); }
00159 return address;
00160 }
00161 }
00162 return "";
00163 }
00164
00165 unsigned int XDAQContextConfiguration::getARTDAQDataPort(const ConfigurationManager *configManager,
00166 const std::string &contextUID) const
00167 {
00168 if (contextUID == "X") return 0;
00169 for (auto& context : contexts_)
00170 {
00171 if (context.contextUID_ == contextUID)
00172 {
00173 if(context.applications_.size() != 1)
00174 {
00175 __SS__ << "Invalid number of ARTDAQ applications in context '" <<
00176 contextUID <<
00177 ".' Must be 1. Currently is " << context.applications_.size() << "." << __E__;
00178 __SS_THROW__;
00179 }
00180
00181 if(context.applications_[0].class_ == "ots::ARTDAQDataManagerSupervisor")
00182 {
00183 auto processors = getSupervisorConfigNode(configManager,
00184 context.contextUID_, context.applications_[0].applicationUID_).getNode(
00185 "LinkToDataManagerConfiguration").getChildren()[0].second.getNode(
00186 "LinkToDataBufferConfiguration").getChildren();
00187
00188 std::string processorType;
00189
00190
00191 for(auto& processor : processors)
00192 {
00193 processorType = processor.second.getNode(
00194 "ProcessorPluginName").getValue<std::string>();
00195 __COUTV__(processorType);
00196
00197 if(processorType == "ARTDAQConsumer" ||
00198 processorType == "ARTDAQProducer")
00199 return processor.second.getNode(
00200 "LinkToProcessorConfiguration").getNode(
00201 XDAQContextConfiguration::ARTDAQ_OFFSET_PORT).getValue<unsigned int>();
00202 }
00203
00204 __SS__ << "No ARTDAQ processor was found while looking for data port." << __E__;
00205 __SS_THROW__;
00206 }
00207
00208 return getSupervisorConfigNode(configManager,
00209 context.contextUID_, context.applications_[0].applicationUID_).getNode(
00210 XDAQContextConfiguration::ARTDAQ_OFFSET_PORT).getValue<unsigned int>();
00211 }
00212 }
00213 return 0;
00214 }
00215
00216
00217
00218 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getBoardReaderContexts() const
00219 {
00220 std::vector<const XDAQContext *> retVec;
00221 for (auto &i : artdaqBoardReaders_)
00222 retVec.push_back(&contexts_[i]);
00223 return retVec;
00224 }
00225
00226 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getEventBuilderContexts() const
00227 {
00228 std::vector<const XDAQContext *> retVec;
00229 for (auto &i : artdaqEventBuilders_)
00230 retVec.push_back(&contexts_[i]);
00231 return retVec;
00232
00233 }
00234
00235 std::vector<const XDAQContextConfiguration::XDAQContext *> XDAQContextConfiguration::getAggregatorContexts() const
00236 {
00237 std::vector<const XDAQContext *> retVec;
00238 for (auto &i : artdaqAggregators_)
00239 retVec.push_back(&contexts_[i]);
00240 return retVec;
00241 }
00242
00243
00244 ConfigurationTree XDAQContextConfiguration::getContextNode(const ConfigurationManager *configManager,
00245 const std::string &contextUID) const
00246 {
00247 return configManager->__SELF_NODE__.getNode(
00248 contextUID);
00249 }
00250
00251
00252 ConfigurationTree XDAQContextConfiguration::getApplicationNode(const ConfigurationManager *configManager,
00253 const std::string &contextUID, const std::string &appUID) const
00254 {
00255 return configManager->__SELF_NODE__.getNode(
00256 contextUID + "/" +
00257 colContext_.colLinkToApplicationConfiguration_ + "/" +
00258 appUID);
00259 }
00260
00261
00262 ConfigurationTree XDAQContextConfiguration::getSupervisorConfigNode(const ConfigurationManager *configManager,
00263 const std::string &contextUID, const std::string &appUID) const
00264 {
00265 return configManager->__SELF_NODE__.getNode(
00266 contextUID + "/" +
00267 colContext_.colLinkToApplicationConfiguration_ + "/" +
00268 appUID + "/" +
00269 colApplication_.colLinkToSupervisorConfiguration_);
00270 }
00271
00272
00273
00274
00275
00276
00277 void XDAQContextConfiguration::extractContexts(ConfigurationManager* configManager)
00278 {
00279
00280
00281
00282
00283
00284
00285 auto children = configManager->__SELF_NODE__.getChildren();
00286
00287 contexts_.clear();
00288
00289
00290 artdaqBoardReaders_.clear();
00291 artdaqEventBuilders_.clear();
00292 artdaqAggregators_.clear();
00293
00294
00295
00296 std::set<unsigned int > appIdSet;
00297
00298 for (auto &child : children)
00299 {
00300 contexts_.push_back(XDAQContext());
00301
00302
00303
00304 contexts_.back().contextUID_ = child.first;
00305
00306 contexts_.back().sourceConfig_ = child.second.getConfigurationName() + "_v" +
00307 child.second.getConfigurationVersion().toString() + " @ " +
00308 std::to_string(child.second.getConfigurationCreationTime());
00309 child.second.getNode(colContext_.colContextUID_).getValue(contexts_.back().contextUID_);
00310 child.second.getNode(colContext_.colStatus_).getValue(contexts_.back().status_);
00311 child.second.getNode(colContext_.colId_).getValue(contexts_.back().id_);
00312 child.second.getNode(colContext_.colAddress_).getValue(contexts_.back().address_);
00313 child.second.getNode(colContext_.colPort_).getValue(contexts_.back().port_);
00314
00315
00316
00317 auto appLink = child.second.getNode(colContext_.colLinkToApplicationConfiguration_);
00318 if (appLink.isDisconnected())
00319 {
00320 __SS__ << "Application link is disconnected!" << std::endl;
00321 throw std::runtime_error(ss.str());
00322 }
00323
00324
00325 auto appChildren = appLink.getChildren();
00326 for (auto appChild : appChildren)
00327 {
00328
00329
00330 contexts_.back().applications_.push_back(XDAQApplication());
00331
00332 contexts_.back().applications_.back().applicationGroupID_ = child.first;
00333 contexts_.back().applications_.back().sourceConfig_ = appChild.second.getConfigurationName() + "_v" +
00334 appChild.second.getConfigurationVersion().toString() + " @ " +
00335 std::to_string(appChild.second.getConfigurationCreationTime());
00336
00337 appChild.second.getNode(colApplication_.colApplicationUID_).getValue(contexts_.back().applications_.back().applicationUID_);
00338 appChild.second.getNode(colApplication_.colStatus_).getValue(contexts_.back().applications_.back().status_);
00339 appChild.second.getNode(colApplication_.colClass_).getValue(contexts_.back().applications_.back().class_);
00340 appChild.second.getNode(colApplication_.colId_).getValue(contexts_.back().applications_.back().id_);
00341
00342
00343 if(appIdSet.find(contexts_.back().applications_.back().id_) != appIdSet.end())
00344 {
00345 __SS__ << "XDAQ Application IDs are not unique. Specifically at id=" <<
00346 contexts_.back().applications_.back().id_ << " appName=" <<
00347 contexts_.back().applications_.back().applicationUID_ << std::endl;
00348 __COUT_ERR__ << "\n" << ss.str();
00349 throw std::runtime_error(ss.str());
00350 }
00351
00352
00353 if((contexts_.back().applications_.back().id_ == 200 &&
00354 contexts_.back().applications_.back().class_ != XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS &&
00355 contexts_.back().applications_.back().class_ != XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS) ||
00356 (contexts_.back().applications_.back().id_ != 200 &&
00357 (contexts_.back().applications_.back().class_ == XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS ||
00358 contexts_.back().applications_.back().class_ == XDAQContextConfiguration::DEPRECATED_SUPERVISOR_CLASS)))
00359 {
00360 __SS__ << "XDAQ Application ID of 200 is reserved for the Gateway Supervisor " <<
00361 XDAQContextConfiguration::GATEWAY_SUPERVISOR_CLASS << ". Conflict specifically at id=" <<
00362 contexts_.back().applications_.back().id_ << " appName=" <<
00363 contexts_.back().applications_.back().applicationUID_ << std::endl;
00364 __SS_THROW__;
00365 }
00366
00367 appIdSet.insert(contexts_.back().applications_.back().id_);
00368
00369
00370 if (appChild.second.getNode(colApplication_.colInstance_).isDefaultValue())
00371 contexts_.back().applications_.back().instance_ = 1;
00372 else
00373 appChild.second.getNode(colApplication_.colInstance_).getValue(contexts_.back().applications_.back().instance_);
00374
00375 if (appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue())
00376 contexts_.back().applications_.back().network_ = "local";
00377 else
00378 appChild.second.getNode(colApplication_.colNetwork_).getValue(contexts_.back().applications_.back().network_);
00379
00380 if (appChild.second.getNode(colApplication_.colGroup_).isDefaultValue())
00381 contexts_.back().applications_.back().group_ = "daq";
00382 else
00383 appChild.second.getNode(colApplication_.colGroup_).getValue(contexts_.back().applications_.back().group_);
00384
00385 appChild.second.getNode(colApplication_.colModule_).getValue(contexts_.back().applications_.back().module_);
00386
00387 try
00388 {
00389 appChild.second.getNode(colApplication_.colConfigurePriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_["Configure"]);
00390 appChild.second.getNode(colApplication_.colStartPriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_["Start"]);
00391 appChild.second.getNode(colApplication_.colStopPriority_).getValue(contexts_.back().applications_.back().stateMachineCommandPriority_["Stop"]);
00392 }
00393 catch(...)
00394 {
00395 __COUT__ << "Ignoring missing state machine priorities..." << __E__;
00396 }
00397
00398
00399 auto appPropertyLink = appChild.second.getNode(colApplication_.colLinkToPropertyConfiguration_);
00400 if (!appPropertyLink.isDisconnected())
00401 {
00402
00403
00404 auto appPropertyChildren = appPropertyLink.getChildren();
00405
00406
00407
00408 for (auto appPropertyChild : appPropertyChildren)
00409 {
00410 contexts_.back().applications_.back().properties_.push_back(XDAQApplicationProperty());
00411 contexts_.back().applications_.back().properties_.back().status_ =
00412 appPropertyChild.second.getNode(colAppProperty_.colStatus_).getValue<bool>();
00413 contexts_.back().applications_.back().properties_.back().name_ =
00414 appPropertyChild.second.getNode(colAppProperty_.colPropertyName_).getValue<std::string>();
00415 contexts_.back().applications_.back().properties_.back().type_ =
00416 appPropertyChild.second.getNode(colAppProperty_.colPropertyType_).getValue<std::string>();
00417 contexts_.back().applications_.back().properties_.back().value_ =
00418 appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_).getValue<std::string>();
00419
00420
00421 }
00422 }
00423
00424
00425 }
00426
00427
00428 if (isARTDAQContext(contexts_.back().contextUID_))
00429 {
00430
00431
00432 if (contexts_.back().applications_.size() != 1)
00433 {
00434 __SS__ << "ARTDAQ Context '" << contexts_.back().contextUID_ <<
00435 "' must have one Application! " <<
00436 contexts_.back().applications_.size() << " were found. " << std::endl;
00437 throw std::runtime_error(ss.str());
00438 }
00439
00440 if (!contexts_.back().status_) continue;
00441
00442 if (contexts_.back().applications_[0].class_ ==
00443 "ots::ARTDAQDataManagerSupervisor")
00444 artdaqBoardReaders_.push_back(contexts_.size() - 1);
00445 else if (contexts_.back().applications_[0].class_ ==
00446 "ots::EventBuilderApp")
00447 artdaqEventBuilders_.push_back(contexts_.size() - 1);
00448 else if (contexts_.back().applications_[0].class_ ==
00449 "ots::DataLoggerApp" ||
00450 contexts_.back().applications_[0].class_ ==
00451 "ots::DispatcherApp")
00452 artdaqAggregators_.push_back(contexts_.size() - 1);
00453 else
00454 {
00455 __SS__ << "ARTDAQ Context must be have Application of an allowed class type:\n " <<
00456 "\tots::ARTDAQDataManagerSupervisor\n" <<
00457 "\tots::EventBuilderApp\n" <<
00458 "\tots::DataLoggerApp\n" <<
00459 "\tots::DispatcherApp\n" <<
00460 "\nClass found was " <<
00461 contexts_.back().applications_[0].class_ << std::endl;
00462 throw std::runtime_error(ss.str());
00463 }
00464
00465 }
00466
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 void XDAQContextConfiguration::outputXDAQXML(std::ostream &out)
00693 {
00694
00695
00698
00699
00700
00701 out << "<?xml version='1.0'?>\n" <<
00702 "<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n" <<
00703 "\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n" <<
00704 "\t\txmlns:xc\t= \"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n";
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 char tmp[200];
00716 for (XDAQContext &context : contexts_)
00717 {
00718
00719
00720
00721 sprintf(tmp, "\t<!-- ContextUID='%s' sourceConfig='%s' -->",
00722 context.contextUID_.c_str(), context.sourceConfig_.c_str());
00723 out << tmp << "\n";
00724
00725 if (!context.status_)
00726 out << "\t<!--\n";
00727
00728 sprintf(tmp, "\t<xc:Context id=\"%u\" url=\"%s:%u\">", context.id_, context.address_.c_str(), context.port_);
00729 out << tmp << "\n\n";
00730
00731 for (XDAQApplication &app : context.applications_)
00732 {
00733
00734
00735
00736 if (context.status_)
00737 {
00738 sprintf(tmp, "\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->",
00739 app.applicationGroupID_.c_str(), app.applicationUID_.c_str(), app.sourceConfig_.c_str());
00740 out << tmp << "\n";
00741
00742 if (!app.status_)
00743 out << "\t\t<!--\n";
00744 }
00745
00746 sprintf(tmp, "\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" network=\"%s\" group=\"%s\">\n",
00747 app.class_.c_str(), app.id_, app.instance_, app.network_.c_str(), app.group_.c_str());
00748 out << tmp;
00749
00751 int foundColon = app.class_.rfind(':');
00752 if (foundColon >= 0) ++foundColon;
00753 else
00754 {
00755 __SS__ << "Illegal XDAQApplication class name value of '" << app.class_
00756 << "' - please check the entry for app ID = " << app.id_ << __E__;
00757 throw std::runtime_error(ss.str());
00758 }
00759 out << "\t\t\t<properties xmlns=\"urn:xdaq-application:" <<
00760 app.class_.substr(foundColon) <<
00761 "\" xsi:type=\"soapenc:Struct\">\n";
00762
00763
00764 for (XDAQApplicationProperty &appProperty : app.properties_)
00765 {
00766
00767 if (appProperty.type_ == "ots-only Property") continue;
00768
00769 if (!appProperty.status_)
00770 out << "\t\t\t\t<!--\n";
00771
00772 sprintf(tmp, "\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n",
00773 appProperty.name_.c_str(),
00774 appProperty.type_.c_str(),
00775 appProperty.value_.c_str(),
00776 appProperty.name_.c_str());
00777 out << tmp;
00778
00779 if (!appProperty.status_)
00780 out << "\t\t\t\t-->\n";
00781 }
00782 out << "\t\t\t</properties>\n";
00784
00785 out << "\t\t</xc:Application>\n";
00786
00787
00788 sprintf(tmp, "\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str());
00789 out << tmp;
00790
00791 if (context.status_ && !app.status_)
00792 out << "\t\t-->\n";
00793 out << "\n";
00794
00795
00796 }
00797
00798 out << "\t</xc:Context>\n";
00799 if (!context.status_)
00800 out << "\t-->\n";
00801 out << "\n";
00802 }
00803
00804
00805 out << "</xc:Partition>\n\n\n";
00806
00807 }
00808
00809
00810 std::string XDAQContextConfiguration::getContextUID(const std::string &url) const
00811 {
00812 for (auto context : contexts_)
00813 {
00814 if (!context.status_) continue;
00815
00816 if (url == context.address_ + ":" + std::to_string(context.port_))
00817 return context.contextUID_;
00818 }
00819 return "";
00820 }
00821
00822
00823 std::string XDAQContextConfiguration::getApplicationUID(const std::string &url, unsigned int id) const
00824 {
00825 for (auto context : contexts_)
00826 {
00827 if (!context.status_) continue;
00828
00829 if (url == context.address_ + ":" + std::to_string(context.port_))
00830 for (auto application : context.applications_)
00831 {
00832 if (!application.status_) continue;
00833
00834 if (application.id_ == id)
00835 {
00836 return application.applicationUID_;
00837 }
00838 }
00839 }
00840 return "";
00841 }
00842
00843 DEFINE_OTS_CONFIGURATION(XDAQContextConfiguration)