Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:07

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_rfioType("castor"),
0082           m_connected(false),
0083           m_cacheTempDir(),
0084           m_cacheTempDirPtr(nullptr),
0085           m_cacheMinFree(),
0086           m_cacheMinFreePtr(nullptr),
0087           m_cacheHint(),
0088           m_cacheHintPtr(nullptr),
0089           m_cloneCacheHint(),
0090           m_cloneCacheHintPtr(nullptr),
0091           m_readHint(),
0092           m_readHintPtr(nullptr),
0093           m_ttreeCacheSize(0U),
0094           m_ttreeCacheSizePtr(nullptr),
0095           m_timeout(0U),
0096           m_timeoutPtr(nullptr),
0097           m_debugLevel(0U),
0098           m_enablePrefetching(false),
0099           m_enablePrefetchingPtr(nullptr),
0100           m_nativeProtocols(),
0101           m_nativeProtocolsPtr(nullptr),
0102           m_statisticsDestination(),
0103           m_statisticsAddrInfo(nullptr),
0104           m_statisticsInfoAvail(false),
0105           m_siteName(),
0106           m_subSiteName() {
0107       this->parse(m_url);
0108 
0109       //apply overrides
0110       overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
0111       overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
0112       overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
0113       overrideFromPSet("overrideSourceCloneCacheHintDir", pset, m_cloneCacheHint, m_cloneCacheHintPtr);
0114       overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
0115       overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
0116       overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
0117       overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
0118       overrideFromPSet("overridePrefetching", pset, m_enablePrefetching, m_enablePrefetchingPtr);
0119       const std::string *tmpStringPtr = nullptr;
0120       overrideFromPSet("overrideStatisticsDestination", pset, m_statisticsDestination, tmpStringPtr);
0121       this->computeStatisticsDestination();
0122       std::vector<std::string> tmpStatisticsInfo;
0123       std::vector<std::string> const *tmpStatisticsInfoPtr = nullptr;
0124       overrideFromPSet("overrideStatisticsInfo", pset, tmpStatisticsInfo, tmpStatisticsInfoPtr);
0125       if (tmpStatisticsInfoPtr) {
0126         m_statisticsInfoAvail = true;
0127         m_statisticsInfo.clear();
0128         for (auto &entry : tmpStatisticsInfo) {
0129           m_statisticsInfo.insert(std::move(entry));
0130         }
0131       }
0132 
0133       if (pset.exists("debugLevel")) {
0134         m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel");
0135       }
0136       if (pset.exists("overrideUseLocalConnectString")) {
0137         m_useLocalConnectString = pset.getUntrackedParameter<bool>("overrideUseLocalConnectString");
0138       }
0139       if (pset.exists("overrideLocalConnectPrefix")) {
0140         m_localConnectPrefix = pset.getUntrackedParameter<std::string>("overrideLocalConnectPrefix");
0141       }
0142       if (pset.exists("overrideLocalConnectSuffix")) {
0143         m_localConnectSuffix = pset.getUntrackedParameter<std::string>("overrideLocalConnectSuffix");
0144       }
0145     }
0146 
0147     SiteLocalConfigService::~SiteLocalConfigService() {
0148       if (m_statisticsAddrInfo) {
0149         freeaddrinfo(m_statisticsAddrInfo);
0150         m_statisticsAddrInfo = nullptr;
0151       }
0152     }
0153 
0154     std::vector<std::string> const &SiteLocalConfigService::trivialDataCatalogs() const {
0155       if (!m_connected) {
0156         static std::vector<std::string> const tmp{"file:PoolFileCatalog.xml"};
0157         return tmp;
0158       }
0159 
0160       if (m_trivialDataCatalogs.empty()) {
0161         cms::Exception ex("SiteLocalConfigService");
0162         ex << "Did not find catalogs in event-data section in " << m_url;
0163         ex.addContext("edm::SiteLocalConfigService::trivialDataCatalogs()");
0164         throw ex;
0165       }
0166 
0167       return m_trivialDataCatalogs;
0168     }
0169 
0170     std::vector<edm::CatalogAttributes> const &SiteLocalConfigService::dataCatalogs() const {
0171       if (!m_connected) {
0172         cms::Exception ex("SiteLocalConfigService");
0173         ex << "Incomplete configuration. Valid site-local-config not found at " << m_url;
0174         ex.addContext("edm::SiteLocalConfigService::dataCatalogs()");
0175         throw ex;
0176       }
0177       if (m_dataCatalogs.empty()) {
0178         cms::Exception ex("SiteLocalConfigService");
0179         ex << "Did not find catalogs in data-access section in " << m_url;
0180         ex.addContext("edm::SiteLocalConfigService::dataCatalogs()");
0181         throw ex;
0182       }
0183       return m_dataCatalogs;
0184     }
0185 
0186     std::filesystem::path const SiteLocalConfigService::storageDescriptionPath(
0187         edm::CatalogAttributes const &aDataCatalog) const {
0188       std::string siteconfig_path = std::string(std::getenv("SITECONFIG_PATH"));
0189       std::filesystem::path filename_storage;
0190       //not a cross site use local path given in SITECONFIG_PATH
0191       if (aDataCatalog.site == aDataCatalog.storageSite) {
0192         //it is a site (no defined subSite), use local path given in SITECONFIG_PATH
0193         if (aDataCatalog.subSite.empty())
0194           filename_storage = siteconfig_path;
0195         //it is a subsite, move one level up
0196         else
0197           filename_storage = siteconfig_path + "/..";
0198       } else {  //cross site
0199         //it is a site (no defined subSite), move one level up
0200         if (aDataCatalog.subSite.empty())
0201           filename_storage = siteconfig_path + "/../" + aDataCatalog.storageSite;
0202         //it is a subsite, move two levels up
0203         else
0204           filename_storage = siteconfig_path + "/../../" + aDataCatalog.storageSite;
0205       }
0206       filename_storage /= "storage.json";
0207       try {
0208         filename_storage = std::filesystem::canonical(filename_storage);
0209       } catch (std::exception &e) {
0210         cms::Exception ex("SiteLocalConfigService");
0211         ex << "Fail to convert path to the storage description, " << filename_storage.string()
0212            << ", to the canonical absolute path"
0213            << ". Path exists?";
0214         ex.addContext("edm::SiteLocalConfigService::storageDescriptionPath()");
0215         throw ex;
0216       }
0217       return filename_storage;
0218     }
0219 
0220     std::string const SiteLocalConfigService::frontierConnect(std::string const &servlet) const {
0221       if (!m_connected) {
0222         throw cms::Exception("Incomplete configuration") << "Valid site-local-config not found at " << m_url;
0223       }
0224 
0225       if (m_frontierConnect.empty()) {
0226         throw cms::Exception("Incomplete configuration")
0227             << "Did not find frontier-connect in calib-data section in " << m_url;
0228       }
0229 
0230       if (servlet.empty()) {
0231         return m_frontierConnect;
0232       }
0233 
0234       // Replace the last component of every "serverurl=" piece (up to the
0235       //   next close-paren) with the servlet
0236       std::string::size_type nextparen = 0;
0237       std::string::size_type serverurl, lastslash;
0238       std::string complexstr = "";
0239       while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
0240         complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
0241         nextparen = m_frontierConnect.find(')', serverurl);
0242         lastslash = m_frontierConnect.rfind('/', nextparen);
0243         complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
0244         complexstr.append(servlet);
0245       }
0246       complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length() - nextparen);
0247 
0248       return complexstr;
0249     }
0250 
0251     std::string const SiteLocalConfigService::lookupCalibConnect(std::string const &input) const {
0252       static std::string const proto = "frontier://";
0253 
0254       if (input.substr(0, proto.length()) == proto) {
0255         // Replace the part after the frontier:// and before either an open-
0256         //  parentheses (which indicates user-supplied options) or the last
0257         //  slash (which indicates start of the schema) with the complex
0258         //  parenthesized string returned from frontierConnect() (which
0259         //  contains all the information needed to connect to frontier),
0260         //  if that part is a simple servlet name (non-empty and not
0261         //  containing special characters)
0262         // Example connect strings where servlet is replaced:
0263         //  frontier://cms_conditions_data/CMS_COND_ECAL
0264         //  frontier://FrontierInt/CMS_COND_ECAL
0265         //  frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL
0266         // Example connect strings left untouched:
0267         //  frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL
0268         //  frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL
0269         std::string::size_type startservlet = proto.length();
0270         // if user supplied extra parenthesized options, stop servlet there
0271         std::string::size_type endservlet = input.find('(', startservlet);
0272         if (endservlet == std::string::npos) {
0273           endservlet = input.rfind('/', input.length());
0274         }
0275         std::string servlet = input.substr(startservlet, endservlet - startservlet);
0276         if ((!servlet.empty()) && (servlet.find_first_of(":/)[]") == std::string::npos)) {
0277           if (servlet == "cms_conditions_data") {
0278             // use the default servlet from site-local-config.xml
0279             servlet = "";
0280           }
0281           return proto + frontierConnect(servlet) + input.substr(endservlet);
0282         }
0283       }
0284       return input;
0285     }
0286 
0287     std::string const SiteLocalConfigService::rfioType(void) const { return m_rfioType; }
0288 
0289     std::string const *SiteLocalConfigService::sourceCacheTempDir() const { return m_cacheTempDirPtr; }
0290 
0291     double const *SiteLocalConfigService::sourceCacheMinFree() const { return m_cacheMinFreePtr; }
0292 
0293     std::string const *SiteLocalConfigService::sourceCacheHint() const { return m_cacheHintPtr; }
0294 
0295     std::string const *SiteLocalConfigService::sourceCloneCacheHint() const { return m_cloneCacheHintPtr; }
0296 
0297     std::string const *SiteLocalConfigService::sourceReadHint() const { return m_readHintPtr; }
0298 
0299     unsigned int const *SiteLocalConfigService::sourceTTreeCacheSize() const { return m_ttreeCacheSizePtr; }
0300 
0301     unsigned int const *SiteLocalConfigService::sourceTimeout() const { return m_timeoutPtr; }
0302 
0303     bool SiteLocalConfigService::enablePrefetching() const {
0304       return m_enablePrefetchingPtr ? *m_enablePrefetchingPtr : false;
0305     }
0306 
0307     unsigned int SiteLocalConfigService::debugLevel() const { return m_debugLevel; }
0308 
0309     std::vector<std::string> const *SiteLocalConfigService::sourceNativeProtocols() const {
0310       return m_nativeProtocolsPtr;
0311     }
0312 
0313     struct addrinfo const *SiteLocalConfigService::statisticsDestination() const { return m_statisticsAddrInfo; }
0314 
0315     std::set<std::string> const *SiteLocalConfigService::statisticsInfo() const {
0316       return m_statisticsInfoAvail ? &m_statisticsInfo : nullptr;
0317     }
0318 
0319     std::string const &SiteLocalConfigService::siteName() const { return m_siteName; }
0320     std::string const &SiteLocalConfigService::subSiteName() const { return m_subSiteName; }
0321     bool SiteLocalConfigService::useLocalConnectString() const { return m_useLocalConnectString; }
0322     std::string const &SiteLocalConfigService::localConnectPrefix() const { return m_localConnectPrefix; }
0323     std::string const &SiteLocalConfigService::localConnectSuffix() const { return m_localConnectSuffix; }
0324 
0325     void SiteLocalConfigService::getCatalog(tinyxml2::XMLElement const &cat, std::string site, std::string subSite) {
0326       edm::CatalogAttributes aCatalog;
0327       aCatalog.site = site;
0328       aCatalog.subSite = subSite;
0329       auto tmp_site = std::string(safe(cat.Attribute("site")));
0330       //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
0331       if (tmp_site.empty())
0332         aCatalog.storageSite = site;
0333       //now storage site is explicitly defined in <data-access>
0334       else
0335         aCatalog.storageSite = tmp_site;
0336       aCatalog.volume = std::string(safe(cat.Attribute("volume")));
0337       aCatalog.protocol = std::string(safe(cat.Attribute("protocol")));
0338       m_dataCatalogs.push_back(aCatalog);
0339     }
0340 
0341     void SiteLocalConfigService::parse(std::string const &url) {
0342       tinyxml2::XMLDocument doc;
0343       auto loadErr = doc.LoadFile(url.c_str());
0344       if (loadErr != tinyxml2::XML_SUCCESS) {
0345         return;
0346       }
0347 
0348       // The Site Config has the following format
0349       // <site-local-config>
0350       // <site name="FNAL">
0351       //   <subsite name="FNAL_SUBSITE"/>
0352       //   <event-data>
0353       //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
0354       //     <rfiotype value="castor"/>
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           auto rfiotype = eventData->FirstChildElement("rfiotype");
0412           if (rfiotype) {
0413             m_rfioType = safe(rfiotype->Attribute("value"));
0414           }
0415         }
0416 
0417         //data-access
0418         //let store catalog entry as: SITE,SUBSITE,STORAGE_SITE,VOLUME,PROTOCOL
0419         //       SITE: from <site name= /> element
0420         //       SUBSITE: from <subsite name= /> element. SUBSITE=SITE for site
0421         //       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
0422         //Therefore
0423         //1. if STORAGE_SITE = SITE, use local storage.json since STORAGE_SITE is not a cross site
0424         //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.
0425         //get data-access
0426         auto dataAccess = site->FirstChildElement("data-access");
0427         if (dataAccess) {
0428           //get catalogs
0429           auto catalog = dataAccess->FirstChildElement("catalog");
0430           if (catalog) {
0431             //add all info for the first catlog here
0432             getCatalog(*catalog, m_siteName, m_subSiteName);
0433             //get next catlog
0434             catalog = catalog->NextSiblingElement("catalog");
0435             while (catalog) {
0436               //add all info for the current catlog here
0437               getCatalog(*catalog, m_siteName, m_subSiteName);
0438               //get next catlog
0439               catalog = catalog->NextSiblingElement("catalog");
0440             }
0441           }
0442         }
0443 
0444         // Parsing of the calib-data section
0445         auto calibData = site->FirstChildElement("calib-data");
0446 
0447         if (calibData) {
0448           auto frontierConnect = calibData->FirstChildElement("frontier-connect");
0449 
0450           if (frontierConnect) {
0451             m_frontierConnect = _toParenString(*frontierConnect);
0452           }
0453           auto localConnect = calibData->FirstChildElement("local-connect");
0454           if (localConnect) {
0455             if (frontierConnect) {
0456               throw cms::Exception("Illegal site local configuration")
0457                   << "It is illegal to include both frontier-connect and local-connect in the same XML file";
0458             }
0459             m_useLocalConnectString = true;
0460             auto connectString = localConnect->FirstChildElement("connectString");
0461             if (connectString) {
0462               m_localConnectPrefix = safe(connectString->Attribute("prefix"));
0463               m_localConnectSuffix = safe(connectString->Attribute("suffix"));
0464             }
0465           }
0466         }
0467 
0468         // Parsing of the source config section
0469         auto sourceConfig = site->FirstChildElement("source-config");
0470 
0471         if (sourceConfig) {
0472           auto cacheTempDir = sourceConfig->FirstChildElement("cache-temp-dir");
0473 
0474           if (cacheTempDir) {
0475             m_cacheTempDir = safe(cacheTempDir->Attribute("name"));
0476             m_cacheTempDirPtr = &m_cacheTempDir;
0477           }
0478 
0479           auto cacheMinFree = sourceConfig->FirstChildElement("cache-min-free");
0480 
0481           if (cacheMinFree) {
0482             //TODO what did xerces do if it couldn't convert?
0483             m_cacheMinFree = cacheMinFree->DoubleAttribute("value");
0484             m_cacheMinFreePtr = &m_cacheMinFree;
0485           }
0486 
0487           auto cacheHint = sourceConfig->FirstChildElement("cache-hint");
0488 
0489           if (cacheHint) {
0490             m_cacheHint = safe(cacheHint->Attribute("value"));
0491             m_cacheHintPtr = &m_cacheHint;
0492           }
0493 
0494           auto cloneCacheHint = sourceConfig->FirstChildElement("clone-cache-hint");
0495 
0496           if (cloneCacheHint) {
0497             m_cloneCacheHint = safe(cloneCacheHint->Attribute("value"));
0498             m_cloneCacheHintPtr = &m_cloneCacheHint;
0499           }
0500 
0501           auto readHint = sourceConfig->FirstChildElement("read-hint");
0502 
0503           if (readHint) {
0504             m_readHint = safe(readHint->Attribute("value"));
0505             m_readHintPtr = &m_readHint;
0506           }
0507 
0508           auto ttreeCacheSize = sourceConfig->FirstChildElement("ttree-cache-size");
0509 
0510           if (ttreeCacheSize) {
0511             m_ttreeCacheSize = ttreeCacheSize->UnsignedAttribute("value");
0512             m_ttreeCacheSizePtr = &m_ttreeCacheSize;
0513           }
0514 
0515           auto timeout = sourceConfig->FirstChildElement("timeout-in-seconds");
0516 
0517           if (timeout) {
0518             m_timeout = timeout->UnsignedAttribute("value");
0519             m_timeoutPtr = &m_timeout;
0520           }
0521 
0522           auto statsDest = sourceConfig->FirstChildElement("statistics-destination");
0523 
0524           if (statsDest) {
0525             m_statisticsDestination = safe(statsDest->Attribute("endpoint"));
0526             if (m_statisticsDestination.empty()) {
0527               m_statisticsDestination = safe(statsDest->Attribute("name"));
0528             }
0529             std::string tmpStatisticsInfo = safe(statsDest->Attribute("info"));
0530             boost::split(m_statisticsInfo, tmpStatisticsInfo, boost::is_any_of("\t ,"));
0531             m_statisticsInfoAvail = !tmpStatisticsInfo.empty();
0532           }
0533 
0534           auto prefetching = sourceConfig->FirstChildElement("prefetching");
0535 
0536           if (prefetching) {
0537             m_enablePrefetching = prefetching->BoolAttribute("value");
0538             m_enablePrefetchingPtr = &m_enablePrefetching;
0539           }
0540 
0541           auto nativeProtocol = sourceConfig->FirstChildElement("native-protocols");
0542 
0543           if (nativeProtocol) {
0544             for (auto child = nativeProtocol->FirstChildElement(); child != nullptr;
0545                  child = child->NextSiblingElement()) {
0546               m_nativeProtocols.push_back(safe(child->Attribute("prefix")));
0547             }
0548             m_nativeProtocolsPtr = &m_nativeProtocols;
0549           }
0550         }
0551       }
0552       m_connected = true;
0553     }
0554 
0555     void SiteLocalConfigService::computeStatisticsDestination() {
0556       std::vector<std::string> inputStrings;
0557       boost::split(inputStrings, m_statisticsDestination, boost::is_any_of(":"));
0558       const std::string &host = inputStrings[0];
0559       const std::string &port = (inputStrings.size() > 1) ? inputStrings[1] : m_statisticsDefaultPort;
0560       struct addrinfo *res;
0561       struct addrinfo hints;
0562       memset(&hints, '\0', sizeof(hints));
0563       hints.ai_socktype = SOCK_DGRAM;
0564       hints.ai_flags = AI_ADDRCONFIG;
0565       hints.ai_family = AF_UNSPEC;
0566       int e = getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
0567       if (e != 0) {
0568         // Silent failure - there's no way to report non-fatal failures from here.
0569         return;
0570       }
0571       m_statisticsAddrInfo = res;
0572     }
0573 
0574     void SiteLocalConfigService::fillDescriptions(ConfigurationDescriptions &descriptions) {
0575       ParameterSetDescription desc;
0576       desc.setComment("Service to translate logical file names to physical file names.");
0577 
0578       desc.addOptionalUntracked<std::string>("siteLocalConfigFileUrl", std::string())
0579           ->setComment(
0580               "Specify the file containing the site local config. Empty string will load from default directory.");
0581       desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
0582       desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
0583       desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
0584       desc.addOptionalUntracked<std::string>("overrideSourceCloneCacheHintDir")
0585           ->setComment("Provide an alternate cache hint for fast cloning.");
0586       desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
0587       desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
0588       desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
0589       desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
0590       desc.addOptionalUntracked<unsigned int>("debugLevel");
0591       desc.addOptionalUntracked<bool>("overridePrefetching")
0592           ->setComment("Request ROOT to asynchronously prefetch I/O during computation.");
0593       desc.addOptionalUntracked<std::string>("overrideStatisticsDestination")
0594           ->setComment(
0595               "Provide an alternate network destination for I/O statistics (must be in the form of host:port).");
0596       desc.addOptionalUntracked<std::vector<std::string> >("overrideStatisticsInfo")
0597           ->setComment(
0598               "Provide an alternate listing of statistics to send (comma separated list; current options are 'dn' or "
0599               "'nodn').  If left blank, all information is snet (including DNs).");
0600       desc.addOptionalUntracked<bool>("overrideUseLocalConnectString");
0601       desc.addOptionalUntracked<std::string>("overrideLocalConnectPrefix");
0602       desc.addOptionalUntracked<std::string>("overrideLocalConnectSuffix");
0603       descriptions.add("SiteLocalConfigService", desc);
0604     }
0605   }  // namespace service
0606 }  // namespace edm