Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-24 01:28:01

0001 ///////////////////////////////////////
0002 //
0003 // data catalogs are filled in "parse"
0004 //
0005 ///////////////////////////////////////
0006 
0007 //<<<<<< INCLUDES                                                       >>>>>>
0008 
0009 #include "FWCore/Services/src/SiteLocalConfigService.h"
0010 #include "FWCore/Utilities/interface/Exception.h"
0011 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0013 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0014 #include "tinyxml2.h"
0015 #include <sstream>
0016 #include <memory>
0017 #include <boost/algorithm/string.hpp>
0018 //<<<<<< PRIVATE DEFINES                                                >>>>>>
0019 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
0020 //<<<<<< PRIVATE TYPES                                                  >>>>>>
0021 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
0022 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
0023 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
0024 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
0025 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
0026 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
0027 
0028 namespace {
0029 
0030   // concatenate all the XML node attribute/value pairs into a
0031   // paren-separated string (for use by CORAL and frontier_client)
0032   inline std::string _toParenString(tinyxml2::XMLElement const &nodeToConvert) {
0033     std::ostringstream oss;
0034 
0035     for (auto child = nodeToConvert.FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) {
0036       for (auto attribute = child->FirstAttribute(); attribute != nullptr; attribute = attribute->Next()) {
0037         oss << "(" << child->Name() << attribute->Name() << "=" << attribute->Value() << ")";
0038       }
0039     }
0040     return oss.str();
0041   }
0042 
0043   template <typename T>
0044   static void overrideFromPSet(char const *iName, edm::ParameterSet const &iPSet, T &iHolder, T const *&iPointer) {
0045     if (iPSet.exists(iName)) {
0046       iHolder = iPSet.getUntrackedParameter<T>(iName);
0047       iPointer = &iHolder;
0048     }
0049   }
0050 
0051   constexpr char const *const kEmptyString = "";
0052   const char *safe(const char *iCheck) {
0053     if (iCheck == nullptr) {
0054       return kEmptyString;
0055     }
0056     return iCheck;
0057   }
0058 
0059   std::string defaultURL() {
0060     std::string returnValue;
0061     const char *tmp = std::getenv("SITECONFIG_PATH");
0062     if (tmp) {
0063       returnValue = tmp;
0064     }
0065     returnValue += "/JobConfig/site-local-config.xml";
0066     return returnValue;
0067   }
0068 
0069 }  // namespace
0070 
0071 namespace edm {
0072   namespace service {
0073 
0074     const std::string SiteLocalConfigService::m_statisticsDefaultPort = "3334";
0075 
0076     SiteLocalConfigService::SiteLocalConfigService(ParameterSet const &pset)
0077         : m_url(pset.getUntrackedParameter<std::string>("siteLocalConfigFileUrl", defaultURL())),
0078           m_trivialDataCatalogs(),
0079           m_dataCatalogs(),
0080           m_frontierConnect(),
0081           m_connected(false),
0082           m_cacheTempDir(),
0083           m_cacheTempDirPtr(nullptr),
0084           m_cacheMinFree(),
0085           m_cacheMinFreePtr(nullptr),
0086           m_cacheHint(),
0087           m_cacheHintPtr(nullptr),
0088           m_cloneCacheHint(),
0089           m_cloneCacheHintPtr(nullptr),
0090           m_readHint(),
0091           m_readHintPtr(nullptr),
0092           m_ttreeCacheSize(0U),
0093           m_ttreeCacheSizePtr(nullptr),
0094           m_timeout(0U),
0095           m_timeoutPtr(nullptr),
0096           m_debugLevel(0U),
0097           m_enablePrefetching(false),
0098           m_enablePrefetchingPtr(nullptr),
0099           m_nativeProtocols(),
0100           m_nativeProtocolsPtr(nullptr),
0101           m_statisticsDestination(),
0102           m_statisticsAddrInfo(nullptr),
0103           m_statisticsInfoAvail(false),
0104           m_siteName(),
0105           m_subSiteName() {
0106       this->parse(m_url);
0107 
0108       //apply overrides
0109       overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
0110       overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
0111       overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
0112       overrideFromPSet("overrideSourceCloneCacheHintDir", pset, m_cloneCacheHint, m_cloneCacheHintPtr);
0113       overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
0114       overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
0115       overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
0116       overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
0117       overrideFromPSet("overridePrefetching", pset, m_enablePrefetching, m_enablePrefetchingPtr);
0118       const std::string *tmpStringPtr = nullptr;
0119       overrideFromPSet("overrideStatisticsDestination", pset, m_statisticsDestination, tmpStringPtr);
0120       this->computeStatisticsDestination();
0121       std::vector<std::string> tmpStatisticsInfo;
0122       std::vector<std::string> const *tmpStatisticsInfoPtr = nullptr;
0123       overrideFromPSet("overrideStatisticsInfo", pset, tmpStatisticsInfo, tmpStatisticsInfoPtr);
0124       if (tmpStatisticsInfoPtr) {
0125         m_statisticsInfoAvail = true;
0126         m_statisticsInfo.clear();
0127         for (auto &entry : tmpStatisticsInfo) {
0128           m_statisticsInfo.insert(std::move(entry));
0129         }
0130       }
0131 
0132       if (pset.exists("debugLevel")) {
0133         m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel");
0134       }
0135       if (pset.exists("overrideUseLocalConnectString")) {
0136         m_useLocalConnectString = pset.getUntrackedParameter<bool>("overrideUseLocalConnectString");
0137       }
0138       if (pset.exists("overrideLocalConnectPrefix")) {
0139         m_localConnectPrefix = pset.getUntrackedParameter<std::string>("overrideLocalConnectPrefix");
0140       }
0141       if (pset.exists("overrideLocalConnectSuffix")) {
0142         m_localConnectSuffix = pset.getUntrackedParameter<std::string>("overrideLocalConnectSuffix");
0143       }
0144     }
0145 
0146     SiteLocalConfigService::~SiteLocalConfigService() {
0147       if (m_statisticsAddrInfo) {
0148         freeaddrinfo(m_statisticsAddrInfo);
0149         m_statisticsAddrInfo = nullptr;
0150       }
0151     }
0152 
0153     std::vector<std::string> const &SiteLocalConfigService::trivialDataCatalogs() const {
0154       if (!m_connected) {
0155         static std::vector<std::string> const tmp{"file:PoolFileCatalog.xml"};
0156         return tmp;
0157       }
0158 
0159       if (m_trivialDataCatalogs.empty()) {
0160         cms::Exception ex("SiteLocalConfigService");
0161         ex << "Did not find catalogs in event-data section in " << m_url;
0162         ex.addContext("edm::SiteLocalConfigService::trivialDataCatalogs()");
0163         throw ex;
0164       }
0165 
0166       return m_trivialDataCatalogs;
0167     }
0168 
0169     std::vector<edm::CatalogAttributes> const &SiteLocalConfigService::dataCatalogs() const {
0170       if (!m_connected) {
0171         cms::Exception ex("SiteLocalConfigService");
0172         ex << "Incomplete configuration. Valid site-local-config not found at " << m_url;
0173         ex.addContext("edm::SiteLocalConfigService::dataCatalogs()");
0174         throw ex;
0175       }
0176       if (m_dataCatalogs.empty()) {
0177         cms::Exception ex("SiteLocalConfigService");
0178         ex << "Did not find catalogs in data-access section in " << m_url;
0179         ex.addContext("edm::SiteLocalConfigService::dataCatalogs()");
0180         throw ex;
0181       }
0182       return m_dataCatalogs;
0183     }
0184 
0185     std::filesystem::path const SiteLocalConfigService::storageDescriptionPath(
0186         edm::CatalogAttributes const &aDataCatalog) const {
0187       char *tmp = std::getenv("SITECONFIG_PATH");
0188       if (tmp == nullptr) {
0189         throw cms::Exception("SiteLocalConfigService") << "SITECONFIG_PATH is not set!";
0190       }
0191       std::string siteconfig_path = std::string(tmp);
0192       std::filesystem::path filename_storage;
0193       //not a cross site use local path given in SITECONFIG_PATH
0194       if (aDataCatalog.site == aDataCatalog.storageSite) {
0195         //it is a site (no defined subSite), use local path given in SITECONFIG_PATH
0196         if (aDataCatalog.subSite.empty())
0197           filename_storage = siteconfig_path;
0198         //it is a subsite, move one level up
0199         else
0200           filename_storage = siteconfig_path + "/..";
0201       } else {  //cross site
0202         //it is a site (no defined subSite), move one level up
0203         if (aDataCatalog.subSite.empty())
0204           filename_storage = siteconfig_path + "/../" + aDataCatalog.storageSite;
0205         //it is a subsite, move two levels up
0206         else
0207           filename_storage = siteconfig_path + "/../../" + aDataCatalog.storageSite;
0208       }
0209       filename_storage /= "storage.json";
0210       try {
0211         filename_storage = std::filesystem::canonical(filename_storage);
0212       } catch (std::exception &e) {
0213         cms::Exception ex("SiteLocalConfigService");
0214         ex << "Fail to convert path to the storage description, " << filename_storage.string()
0215            << ", to the canonical absolute path"
0216            << ". Path exists?";
0217         ex.addContext("edm::SiteLocalConfigService::storageDescriptionPath()");
0218         throw ex;
0219       }
0220       return filename_storage;
0221     }
0222 
0223     std::string const SiteLocalConfigService::frontierConnect(std::string const &servlet) const {
0224       if (!m_connected) {
0225         throw cms::Exception("Incomplete configuration") << "Valid site-local-config not found at " << m_url;
0226       }
0227 
0228       if (m_frontierConnect.empty()) {
0229         throw cms::Exception("Incomplete configuration")
0230             << "Did not find frontier-connect in calib-data section in " << m_url;
0231       }
0232 
0233       if (servlet.empty()) {
0234         return m_frontierConnect;
0235       }
0236 
0237       // Replace the last component of every "serverurl=" piece (up to the
0238       //   next close-paren) with the servlet
0239       std::string::size_type nextparen = 0;
0240       std::string::size_type serverurl, lastslash;
0241       std::string complexstr = "";
0242       while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
0243         complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
0244         nextparen = m_frontierConnect.find(')', serverurl);
0245         lastslash = m_frontierConnect.rfind('/', nextparen);
0246         complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
0247         complexstr.append(servlet);
0248       }
0249       complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length() - nextparen);
0250 
0251       return complexstr;
0252     }
0253 
0254     std::string const SiteLocalConfigService::lookupCalibConnect(std::string const &input) const {
0255       static std::string const proto = "frontier://";
0256 
0257       if (input.substr(0, proto.length()) == proto) {
0258         // Replace the part after the frontier:// and before either an open-
0259         //  parentheses (which indicates user-supplied options) or the last
0260         //  slash (which indicates start of the schema) with the complex
0261         //  parenthesized string returned from frontierConnect() (which
0262         //  contains all the information needed to connect to frontier),
0263         //  if that part is a simple servlet name (non-empty and not
0264         //  containing special characters)
0265         // Example connect strings where servlet is replaced:
0266         //  frontier://cms_conditions_data/CMS_COND_ECAL
0267         //  frontier://FrontierInt/CMS_COND_ECAL
0268         //  frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL
0269         // Example connect strings left untouched:
0270         //  frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL
0271         //  frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL
0272         std::string::size_type startservlet = proto.length();
0273         // if user supplied extra parenthesized options, stop servlet there
0274         std::string::size_type endservlet = input.find('(', startservlet);
0275         if (endservlet == std::string::npos) {
0276           endservlet = input.rfind('/', input.length());
0277         }
0278         std::string servlet = input.substr(startservlet, endservlet - startservlet);
0279         if ((!servlet.empty()) && (servlet.find_first_of(":/)[]") == std::string::npos)) {
0280           if (servlet == "cms_conditions_data") {
0281             // use the default servlet from site-local-config.xml
0282             servlet = "";
0283           }
0284           return proto + frontierConnect(servlet) + input.substr(endservlet);
0285         }
0286       }
0287       return input;
0288     }
0289 
0290     std::string const *SiteLocalConfigService::sourceCacheTempDir() const { return m_cacheTempDirPtr; }
0291 
0292     double const *SiteLocalConfigService::sourceCacheMinFree() const { return m_cacheMinFreePtr; }
0293 
0294     std::string const *SiteLocalConfigService::sourceCacheHint() const { return m_cacheHintPtr; }
0295 
0296     std::string const *SiteLocalConfigService::sourceCloneCacheHint() const { return m_cloneCacheHintPtr; }
0297 
0298     std::string const *SiteLocalConfigService::sourceReadHint() const { return m_readHintPtr; }
0299 
0300     unsigned int const *SiteLocalConfigService::sourceTTreeCacheSize() const { return m_ttreeCacheSizePtr; }
0301 
0302     unsigned int const *SiteLocalConfigService::sourceTimeout() const { return m_timeoutPtr; }
0303 
0304     bool SiteLocalConfigService::enablePrefetching() const {
0305       return m_enablePrefetchingPtr ? *m_enablePrefetchingPtr : false;
0306     }
0307 
0308     unsigned int SiteLocalConfigService::debugLevel() const { return m_debugLevel; }
0309 
0310     std::vector<std::string> const *SiteLocalConfigService::sourceNativeProtocols() const {
0311       return m_nativeProtocolsPtr;
0312     }
0313 
0314     struct addrinfo const *SiteLocalConfigService::statisticsDestination() const { return m_statisticsAddrInfo; }
0315 
0316     std::set<std::string> const *SiteLocalConfigService::statisticsInfo() const {
0317       return m_statisticsInfoAvail ? &m_statisticsInfo : nullptr;
0318     }
0319 
0320     std::string const &SiteLocalConfigService::siteName() const { return m_siteName; }
0321     std::string const &SiteLocalConfigService::subSiteName() const { return m_subSiteName; }
0322     bool SiteLocalConfigService::useLocalConnectString() const { return m_useLocalConnectString; }
0323     std::string const &SiteLocalConfigService::localConnectPrefix() const { return m_localConnectPrefix; }
0324     std::string const &SiteLocalConfigService::localConnectSuffix() const { return m_localConnectSuffix; }
0325 
0326     void SiteLocalConfigService::getCatalog(tinyxml2::XMLElement const &cat, std::string site, std::string subSite) {
0327       edm::CatalogAttributes aCatalog;
0328       aCatalog.site = site;
0329       aCatalog.subSite = subSite;
0330       auto tmp_site = std::string(safe(cat.Attribute("site")));
0331       //no site attribute in the data catalog defined in <data-access>, so storage site is from <site> block of site_local_config.xml, which is the input parameter "site" of this method
0332       if (tmp_site.empty())
0333         aCatalog.storageSite = site;
0334       //now storage site is explicitly defined in <data-access>
0335       else
0336         aCatalog.storageSite = tmp_site;
0337       aCatalog.volume = std::string(safe(cat.Attribute("volume")));
0338       aCatalog.protocol = std::string(safe(cat.Attribute("protocol")));
0339       m_dataCatalogs.push_back(aCatalog);
0340     }
0341 
0342     void SiteLocalConfigService::parse(std::string const &url) {
0343       tinyxml2::XMLDocument doc;
0344       auto loadErr = doc.LoadFile(url.c_str());
0345       if (loadErr != tinyxml2::XML_SUCCESS) {
0346         return;
0347       }
0348 
0349       // The Site Config has the following format
0350       // <site-local-config>
0351       // <site name="FNAL">
0352       //   <subsite name="FNAL_SUBSITE"/>
0353       //   <event-data>
0354       //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
0355       //   </event-data>
0356       //   <calib-data>
0357       //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
0358       //     <frontier-connect>
0359       //       ... frontier-interpreted server/proxy xml ...
0360       //     </frontier-connect>
0361       //     <local-connect>
0362       //       <connectString prefix="anything1" suffix="anything2"/>
0363       //     </local-connect>
0364       //   </calib-data>
0365       //   <source-config>
0366       //     <cache-temp-dir name="/a/b/c"/>
0367       //     <cache-hint value="..."/>
0368       //     <read-hint value="..."/>
0369       //     <ttree-cache-size value="0"/>
0370       //     <native-protocols>
0371       //        <protocol  prefix="dcache"/>
0372       //        <protocol prefix="file"/>
0373       //     </native-protocols>
0374       //   </source-config>
0375       // </site>
0376       // </site-local-config>
0377 
0378       auto rootElement = doc.RootElement();
0379 
0380       for (auto site = rootElement->FirstChildElement("site"); site != nullptr;
0381            site = site->NextSiblingElement("site")) {
0382         auto subSite = site->FirstChildElement("subsite");
0383 
0384         // Parse the site name
0385         m_siteName = safe(site->Attribute("name"));
0386         m_subSiteName = std::string();
0387         if (subSite) {
0388           //check to make sure subSite has no children
0389           auto subSite_first_child = subSite->FirstChild();
0390           if (subSite_first_child) {
0391             cms::Exception ex("SiteLocalConfigService");
0392             ex << "Invalid site-local-config.xml. Subsite node has children!";
0393             ex.addContext("edm::SiteLocalConfigService::parse()");
0394             throw ex;
0395           }
0396           m_subSiteName = safe(subSite->Attribute("name"));
0397         }
0398 
0399         // Parsing of the event data section
0400         auto eventData = site->FirstChildElement("event-data");
0401         if (eventData) {
0402           auto catalog = eventData->FirstChildElement("catalog");
0403           if (catalog) {
0404             m_trivialDataCatalogs.push_back(safe(catalog->Attribute("url")));
0405             catalog = catalog->NextSiblingElement("catalog");
0406             while (catalog) {
0407               m_trivialDataCatalogs.push_back(safe(catalog->Attribute("url")));
0408               catalog = catalog->NextSiblingElement("catalog");
0409             }
0410           }
0411         }
0412 
0413         //data-access
0414         //let store catalog entry as: SITE,SUBSITE,STORAGE_SITE,VOLUME,PROTOCOL
0415         //       SITE: from <site name= /> element
0416         //       SUBSITE: from <subsite name= /> element. SUBSITE=SITE for site
0417         //       STORAGE_SITE, VOLUME and PROTOCOL: from <catalog site= volume= protocol= /> in <data-access>. If "site" attribute is not defined inside <catalog />, STORAGE_SITE is SITE
0418         //Therefore
0419         //1. if STORAGE_SITE = SITE, use local storage.json since STORAGE_SITE is not a cross site
0420         //2. if SUBSITE is empty, this is a site. Otherwise, this is a subsite. These are used to define the path to locate the storage.json in FileLocator. This path is provided by storageDescriptionPath() method of this class.
0421         //get data-access
0422         auto dataAccess = site->FirstChildElement("data-access");
0423         if (dataAccess) {
0424           //get catalogs
0425           auto catalog = dataAccess->FirstChildElement("catalog");
0426           if (catalog) {
0427             //add all info for the first catlog here
0428             getCatalog(*catalog, m_siteName, m_subSiteName);
0429             //get next catlog
0430             catalog = catalog->NextSiblingElement("catalog");
0431             while (catalog) {
0432               //add all info for the current catlog here
0433               getCatalog(*catalog, m_siteName, m_subSiteName);
0434               //get next catlog
0435               catalog = catalog->NextSiblingElement("catalog");
0436             }
0437           }
0438         }
0439 
0440         // Parsing of the calib-data section
0441         auto calibData = site->FirstChildElement("calib-data");
0442 
0443         if (calibData) {
0444           auto frontierConnect = calibData->FirstChildElement("frontier-connect");
0445 
0446           if (frontierConnect) {
0447             m_frontierConnect = _toParenString(*frontierConnect);
0448           }
0449           auto localConnect = calibData->FirstChildElement("local-connect");
0450           if (localConnect) {
0451             if (frontierConnect) {
0452               throw cms::Exception("Illegal site local configuration")
0453                   << "It is illegal to include both frontier-connect and local-connect in the same XML file";
0454             }
0455             m_useLocalConnectString = true;
0456             auto connectString = localConnect->FirstChildElement("connectString");
0457             if (connectString) {
0458               m_localConnectPrefix = safe(connectString->Attribute("prefix"));
0459               m_localConnectSuffix = safe(connectString->Attribute("suffix"));
0460             }
0461           }
0462         }
0463 
0464         // Parsing of the source config section
0465         auto sourceConfig = site->FirstChildElement("source-config");
0466 
0467         if (sourceConfig) {
0468           auto cacheTempDir = sourceConfig->FirstChildElement("cache-temp-dir");
0469 
0470           if (cacheTempDir) {
0471             m_cacheTempDir = safe(cacheTempDir->Attribute("name"));
0472             m_cacheTempDirPtr = &m_cacheTempDir;
0473           }
0474 
0475           auto cacheMinFree = sourceConfig->FirstChildElement("cache-min-free");
0476 
0477           if (cacheMinFree) {
0478             //TODO what did xerces do if it couldn't convert?
0479             m_cacheMinFree = cacheMinFree->DoubleAttribute("value");
0480             m_cacheMinFreePtr = &m_cacheMinFree;
0481           }
0482 
0483           auto cacheHint = sourceConfig->FirstChildElement("cache-hint");
0484 
0485           if (cacheHint) {
0486             m_cacheHint = safe(cacheHint->Attribute("value"));
0487             m_cacheHintPtr = &m_cacheHint;
0488           }
0489 
0490           auto cloneCacheHint = sourceConfig->FirstChildElement("clone-cache-hint");
0491 
0492           if (cloneCacheHint) {
0493             m_cloneCacheHint = safe(cloneCacheHint->Attribute("value"));
0494             m_cloneCacheHintPtr = &m_cloneCacheHint;
0495           }
0496 
0497           auto readHint = sourceConfig->FirstChildElement("read-hint");
0498 
0499           if (readHint) {
0500             m_readHint = safe(readHint->Attribute("value"));
0501             m_readHintPtr = &m_readHint;
0502           }
0503 
0504           auto ttreeCacheSize = sourceConfig->FirstChildElement("ttree-cache-size");
0505 
0506           if (ttreeCacheSize) {
0507             m_ttreeCacheSize = ttreeCacheSize->UnsignedAttribute("value");
0508             m_ttreeCacheSizePtr = &m_ttreeCacheSize;
0509           }
0510 
0511           auto timeout = sourceConfig->FirstChildElement("timeout-in-seconds");
0512 
0513           if (timeout) {
0514             m_timeout = timeout->UnsignedAttribute("value");
0515             m_timeoutPtr = &m_timeout;
0516           }
0517 
0518           auto statsDest = sourceConfig->FirstChildElement("statistics-destination");
0519 
0520           if (statsDest) {
0521             m_statisticsDestination = safe(statsDest->Attribute("endpoint"));
0522             if (m_statisticsDestination.empty()) {
0523               m_statisticsDestination = safe(statsDest->Attribute("name"));
0524             }
0525             std::string tmpStatisticsInfo = safe(statsDest->Attribute("info"));
0526             boost::split(m_statisticsInfo, tmpStatisticsInfo, boost::is_any_of("\t ,"));
0527             m_statisticsInfoAvail = !tmpStatisticsInfo.empty();
0528           }
0529 
0530           auto prefetching = sourceConfig->FirstChildElement("prefetching");
0531 
0532           if (prefetching) {
0533             m_enablePrefetching = prefetching->BoolAttribute("value");
0534             m_enablePrefetchingPtr = &m_enablePrefetching;
0535           }
0536 
0537           auto nativeProtocol = sourceConfig->FirstChildElement("native-protocols");
0538 
0539           if (nativeProtocol) {
0540             for (auto child = nativeProtocol->FirstChildElement(); child != nullptr;
0541                  child = child->NextSiblingElement()) {
0542               m_nativeProtocols.push_back(safe(child->Attribute("prefix")));
0543             }
0544             m_nativeProtocolsPtr = &m_nativeProtocols;
0545           }
0546         }
0547       }
0548       m_connected = true;
0549     }
0550 
0551     void SiteLocalConfigService::computeStatisticsDestination() {
0552       std::vector<std::string> inputStrings;
0553       boost::split(inputStrings, m_statisticsDestination, boost::is_any_of(":"));
0554       const std::string &host = inputStrings[0];
0555       const std::string &port = (inputStrings.size() > 1) ? inputStrings[1] : m_statisticsDefaultPort;
0556       struct addrinfo *res;
0557       struct addrinfo hints;
0558       memset(&hints, '\0', sizeof(hints));
0559       hints.ai_socktype = SOCK_DGRAM;
0560       hints.ai_flags = AI_ADDRCONFIG;
0561       hints.ai_family = AF_UNSPEC;
0562       int e = getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
0563       if (e != 0) {
0564         // Silent failure - there's no way to report non-fatal failures from here.
0565         return;
0566       }
0567       m_statisticsAddrInfo = res;
0568     }
0569 
0570     void SiteLocalConfigService::fillDescriptions(ConfigurationDescriptions &descriptions) {
0571       ParameterSetDescription desc;
0572       desc.setComment("Service to translate logical file names to physical file names.");
0573 
0574       desc.addOptionalUntracked<std::string>("siteLocalConfigFileUrl", std::string())
0575           ->setComment(
0576               "Specify the file containing the site local config. Empty string will load from default directory.");
0577       desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
0578       desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
0579       desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
0580       desc.addOptionalUntracked<std::string>("overrideSourceCloneCacheHintDir")
0581           ->setComment("Provide an alternate cache hint for fast cloning.");
0582       desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
0583       desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
0584       desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
0585       desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
0586       desc.addOptionalUntracked<unsigned int>("debugLevel");
0587       desc.addOptionalUntracked<bool>("overridePrefetching")
0588           ->setComment("Request ROOT to asynchronously prefetch I/O during computation.");
0589       desc.addOptionalUntracked<std::string>("overrideStatisticsDestination")
0590           ->setComment(
0591               "Provide an alternate network destination for I/O statistics (must be in the form of host:port).");
0592       desc.addOptionalUntracked<std::vector<std::string> >("overrideStatisticsInfo")
0593           ->setComment(
0594               "Provide an alternate listing of statistics to send (comma separated list; current options are 'dn' or "
0595               "'nodn').  If left blank, all information is snet (including DNs).");
0596       desc.addOptionalUntracked<bool>("overrideUseLocalConnectString");
0597       desc.addOptionalUntracked<std::string>("overrideLocalConnectPrefix");
0598       desc.addOptionalUntracked<std::string>("overrideLocalConnectSuffix");
0599       descriptions.add("SiteLocalConfigService", desc);
0600     }
0601   }  // namespace service
0602 }  // namespace edm