/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FWStorage/Services/src/SiteLocalConfigService.cc
573 строки
25 KB
Christopher Jones
Renamed AdaptorConfig to TFileAdaptor
17 дек 2025, 22:45
17 дек 2025, 22:45
3690d77
Код
Авторство
О чём код?
/////////////////////////////////////// // // data catalogs are filled in "parse" // /////////////////////////////////////// //<<<<<< INCLUDES >>>>>> #include "FWStorage/Services/src/SiteLocalConfigService.h" #include "FWCore/Utilities/interface/Exception.h" #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" #include "tinyxml2.h" #include <sstream> #include <memory> #include <boost/algorithm/string.hpp> //<<<<<< PRIVATE DEFINES >>>>>> //<<<<<< PRIVATE CONSTANTS >>>>>> //<<<<<< PRIVATE TYPES >>>>>> //<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> //<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> //<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> //<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> //<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> //<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> namespace { // concatenate all the XML node attribute/value pairs into a // paren-separated string (for use by CORAL and frontier_client) inline std::string _toParenString(tinyxml2::XMLElement const &nodeToConvert) { std::ostringstream oss; for (auto child = nodeToConvert.FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) { for (auto attribute = child->FirstAttribute(); attribute != nullptr; attribute = attribute->Next()) { oss << "(" << child->Name() << attribute->Name() << "=" << attribute->Value() << ")"; } } return oss.str(); } template <typename T> void overrideFromPSet(char const *iName, edm::ParameterSet const &iPSet, T &iHolder, T const *&iPointer) { if (iPSet.exists(iName)) { iHolder = iPSet.getUntrackedParameter<T>(iName); iPointer = &iHolder; } } constexpr char const *const kEmptyString = ""; const char *safe(const char *iCheck) { if (iCheck == nullptr) { return kEmptyString; } return iCheck; } std::string defaultURL() { std::string returnValue; const char *tmp = std::getenv("SITECONFIG_PATH"); if (tmp) { returnValue = tmp; } returnValue += "/JobConfig/site-local-config.xml"; return returnValue; } } // namespace namespace edm { namespace service { const std::string SiteLocalConfigService::m_statisticsDefaultPort = "3334"; SiteLocalConfigService::SiteLocalConfigService(ParameterSet const &pset) : m_url(pset.getUntrackedParameter<std::string>("siteLocalConfigFileUrl", defaultURL())), m_dataCatalogs(), m_frontierConnect(), m_connected(false), m_cacheTempDir(), m_cacheTempDirPtr(nullptr), m_cacheMinFree(), m_cacheMinFreePtr(nullptr), m_cacheHint(), m_cacheHintPtr(nullptr), m_cloneCacheHint(), m_cloneCacheHintPtr(nullptr), m_readHint(), m_readHintPtr(nullptr), m_ttreeCacheSize(0U), m_ttreeCacheSizePtr(nullptr), m_timeout(0U), m_timeoutPtr(nullptr), m_debugLevel(0U), m_enablePrefetching(false), m_enablePrefetchingPtr(nullptr), m_nativeProtocols(), m_nativeProtocolsPtr(nullptr), m_statisticsDestination(), m_statisticsAddrInfo(nullptr), m_statisticsInfoAvail(false), m_siteName(), m_subSiteName() { this->parse(m_url); //apply overrides overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr); overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr); overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr); overrideFromPSet("overrideSourceCloneCacheHintDir", pset, m_cloneCacheHint, m_cloneCacheHintPtr); overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr); overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr); overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr); overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr); overrideFromPSet("overridePrefetching", pset, m_enablePrefetching, m_enablePrefetchingPtr); const std::string *tmpStringPtr = nullptr; overrideFromPSet("overrideStatisticsDestination", pset, m_statisticsDestination, tmpStringPtr); this->computeStatisticsDestination(); std::vector<std::string> tmpStatisticsInfo; std::vector<std::string> const *tmpStatisticsInfoPtr = nullptr; overrideFromPSet("overrideStatisticsInfo", pset, tmpStatisticsInfo, tmpStatisticsInfoPtr); if (tmpStatisticsInfoPtr) { m_statisticsInfoAvail = true; m_statisticsInfo.clear(); for (auto &entry : tmpStatisticsInfo) { m_statisticsInfo.insert(std::move(entry)); } } if (pset.exists("debugLevel")) { m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel"); } if (pset.exists("overrideUseLocalConnectString")) { m_useLocalConnectString = pset.getUntrackedParameter<bool>("overrideUseLocalConnectString"); } if (pset.exists("overrideLocalConnectPrefix")) { m_localConnectPrefix = pset.getUntrackedParameter<std::string>("overrideLocalConnectPrefix"); } if (pset.exists("overrideLocalConnectSuffix")) { m_localConnectSuffix = pset.getUntrackedParameter<std::string>("overrideLocalConnectSuffix"); } } SiteLocalConfigService::~SiteLocalConfigService() { if (m_statisticsAddrInfo) { freeaddrinfo(m_statisticsAddrInfo); m_statisticsAddrInfo = nullptr; } } std::vector<edm::CatalogAttributes> const &SiteLocalConfigService::dataCatalogs() const { if (!m_connected) { cms::Exception ex("SiteLocalConfigService"); ex << "Incomplete configuration. Valid site-local-config not found at " << m_url; ex.addContext("edm::SiteLocalConfigService::dataCatalogs()"); throw ex; } if (m_dataCatalogs.empty()) { cms::Exception ex("SiteLocalConfigService"); ex << "Did not find catalogs in data-access section in " << m_url; ex.addContext("edm::SiteLocalConfigService::dataCatalogs()"); throw ex; } return m_dataCatalogs; } std::filesystem::path const SiteLocalConfigService::storageDescriptionPath( edm::CatalogAttributes const &aDataCatalog) const { char *tmp = std::getenv("SITECONFIG_PATH"); if (tmp == nullptr) { throw cms::Exception("SiteLocalConfigService") << "SITECONFIG_PATH is not set!"; } std::string siteconfig_path = std::string(tmp); std::filesystem::path filename_storage; //not a cross site use local path given in SITECONFIG_PATH if (aDataCatalog.site == aDataCatalog.storageSite) { //it is a site (no defined subSite), use local path given in SITECONFIG_PATH if (aDataCatalog.subSite.empty()) filename_storage = siteconfig_path; //it is a subsite, move one level up else filename_storage = siteconfig_path + "/.."; } else { //cross site //it is a site (no defined subSite), move one level up if (aDataCatalog.subSite.empty()) filename_storage = siteconfig_path + "/../" + aDataCatalog.storageSite; //it is a subsite, move two levels up else filename_storage = siteconfig_path + "/../../" + aDataCatalog.storageSite; } filename_storage /= "storage.json"; try { filename_storage = std::filesystem::canonical(filename_storage); } catch (std::exception &e) { cms::Exception ex("SiteLocalConfigService"); ex << "Fail to convert path to the storage description, " << filename_storage.string() << ", to the canonical absolute path" << ". Path exists?"; ex.addContext("edm::SiteLocalConfigService::storageDescriptionPath()"); throw ex; } return filename_storage; } std::string const SiteLocalConfigService::frontierConnect(std::string const &servlet) const { if (!m_connected) { throw cms::Exception("Incomplete configuration") << "Valid site-local-config not found at " << m_url; } if (m_frontierConnect.empty()) { throw cms::Exception("Incomplete configuration") << "Did not find frontier-connect in calib-data section in " << m_url; } if (servlet.empty()) { return m_frontierConnect; } // Replace the last component of every "serverurl=" piece (up to the // next close-paren) with the servlet std::string::size_type nextparen = 0; std::string::size_type serverurl, lastslash; std::string complexstr = ""; while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) { complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen); nextparen = m_frontierConnect.find(')', serverurl); lastslash = m_frontierConnect.rfind('/', nextparen); complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1); complexstr.append(servlet); } complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length() - nextparen); return complexstr; } std::string const SiteLocalConfigService::lookupCalibConnect(std::string const &input) const { static std::string const proto = "frontier://"; if (input.substr(0, proto.length()) == proto) { // Replace the part after the frontier:// and before either an open- // parentheses (which indicates user-supplied options) or the last // slash (which indicates start of the schema) with the complex // parenthesized string returned from frontierConnect() (which // contains all the information needed to connect to frontier), // if that part is a simple servlet name (non-empty and not // containing special characters) // Example connect strings where servlet is replaced: // frontier://cms_conditions_data/CMS_COND_ECAL // frontier://FrontierInt/CMS_COND_ECAL // frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL // Example connect strings left untouched: // frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL // frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL std::string::size_type startservlet = proto.length(); // if user supplied extra parenthesized options, stop servlet there std::string::size_type endservlet = input.find('(', startservlet); if (endservlet == std::string::npos) { endservlet = input.rfind('/', input.length()); } std::string servlet = input.substr(startservlet, endservlet - startservlet); if ((!servlet.empty()) && (servlet.find_first_of(":/)[]") == std::string::npos)) { if (servlet == "cms_conditions_data") { // use the default servlet from site-local-config.xml servlet = ""; } return proto + frontierConnect(servlet) + input.substr(endservlet); } } return input; } std::string const *SiteLocalConfigService::sourceCacheTempDir() const { return m_cacheTempDirPtr; } double const *SiteLocalConfigService::sourceCacheMinFree() const { return m_cacheMinFreePtr; } std::string const *SiteLocalConfigService::sourceCacheHint() const { return m_cacheHintPtr; } std::string const *SiteLocalConfigService::sourceCloneCacheHint() const { return m_cloneCacheHintPtr; } std::string const *SiteLocalConfigService::sourceReadHint() const { return m_readHintPtr; } unsigned int const *SiteLocalConfigService::sourceTTreeCacheSize() const { return m_ttreeCacheSizePtr; } unsigned int const *SiteLocalConfigService::sourceTimeout() const { return m_timeoutPtr; } bool SiteLocalConfigService::enablePrefetching() const { return m_enablePrefetchingPtr ? *m_enablePrefetchingPtr : false; } unsigned int SiteLocalConfigService::debugLevel() const { return m_debugLevel; } std::vector<std::string> const *SiteLocalConfigService::sourceNativeProtocols() const { return m_nativeProtocolsPtr; } struct addrinfo const *SiteLocalConfigService::statisticsDestination() const { return m_statisticsAddrInfo; } std::set<std::string> const *SiteLocalConfigService::statisticsInfo() const { return m_statisticsInfoAvail ? &m_statisticsInfo : nullptr; } std::string const &SiteLocalConfigService::siteName() const { return m_siteName; } std::string const &SiteLocalConfigService::subSiteName() const { return m_subSiteName; } bool SiteLocalConfigService::useLocalConnectString() const { return m_useLocalConnectString; } std::string const &SiteLocalConfigService::localConnectPrefix() const { return m_localConnectPrefix; } std::string const &SiteLocalConfigService::localConnectSuffix() const { return m_localConnectSuffix; } void SiteLocalConfigService::getCatalog(tinyxml2::XMLElement const &cat, std::string site, std::string subSite) { edm::CatalogAttributes aCatalog; aCatalog.site = site; aCatalog.subSite = subSite; auto tmp_site = std::string(safe(cat.Attribute("site"))); //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 if (tmp_site.empty()) aCatalog.storageSite = site; //now storage site is explicitly defined in <data-access> else aCatalog.storageSite = tmp_site; aCatalog.volume = std::string(safe(cat.Attribute("volume"))); aCatalog.protocol = std::string(safe(cat.Attribute("protocol"))); m_dataCatalogs.push_back(aCatalog); } void SiteLocalConfigService::parse(std::string const &url) { tinyxml2::XMLDocument doc; auto loadErr = doc.LoadFile(url.c_str()); if (loadErr != tinyxml2::XML_SUCCESS) { return; } // The Site Config has the following format // <site-local-config> // <site name="FNAL"> // <subsite name="FNAL_SUBSITE"/> // <data-access> // <catalog volume="..." protocol="..."/> // <catalog site="..." volume="..." protocol="..."/> // </data-access> // <calib-data> // <frontier-connect> // ... frontier-interpreted server/proxy xml ... // </frontier-connect> // <local-connect> // <connectString prefix="anything1" suffix="anything2"/> // </local-connect> // </calib-data> // <source-config> // <cache-temp-dir name="/a/b/c"/> // <cache-hint value="..."/> // <read-hint value="..."/> // <ttree-cache-size value="0"/> // <native-protocols> // <protocol prefix="dcache"/> // <protocol prefix="file"/> // </native-protocols> // </source-config> // </site> // </site-local-config> auto rootElement = doc.RootElement(); for (auto site = rootElement->FirstChildElement("site"); site != nullptr; site = site->NextSiblingElement("site")) { auto subSite = site->FirstChildElement("subsite"); // Parse the site name m_siteName = safe(site->Attribute("name")); m_subSiteName = std::string(); if (subSite) { //check to make sure subSite has no children auto subSite_first_child = subSite->FirstChild(); if (subSite_first_child) { cms::Exception ex("SiteLocalConfigService"); ex << "Invalid site-local-config.xml. Subsite node has children!"; ex.addContext("edm::SiteLocalConfigService::parse()"); throw ex; } m_subSiteName = safe(subSite->Attribute("name")); } //data-access //let store catalog entry as: SITE,SUBSITE,STORAGE_SITE,VOLUME,PROTOCOL // SITE: from <site name= /> element // SUBSITE: from <subsite name= /> element. SUBSITE=SITE for site // 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 //Therefore //1. if STORAGE_SITE = SITE, use local storage.json since STORAGE_SITE is not a cross site //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. //get data-access auto dataAccess = site->FirstChildElement("data-access"); if (dataAccess) { //get catalogs auto catalog = dataAccess->FirstChildElement("catalog"); if (catalog) { //add all info for the first catlog here getCatalog(*catalog, m_siteName, m_subSiteName); //get next catlog catalog = catalog->NextSiblingElement("catalog"); while (catalog) { //add all info for the current catlog here getCatalog(*catalog, m_siteName, m_subSiteName); //get next catlog catalog = catalog->NextSiblingElement("catalog"); } } } // Parsing of the calib-data section auto calibData = site->FirstChildElement("calib-data"); if (calibData) { auto frontierConnect = calibData->FirstChildElement("frontier-connect"); if (frontierConnect) { m_frontierConnect = _toParenString(*frontierConnect); } auto localConnect = calibData->FirstChildElement("local-connect"); if (localConnect) { if (frontierConnect) { throw cms::Exception("Illegal site local configuration") << "It is illegal to include both frontier-connect and local-connect in the same XML file"; } m_useLocalConnectString = true; auto connectString = localConnect->FirstChildElement("connectString"); if (connectString) { m_localConnectPrefix = safe(connectString->Attribute("prefix")); m_localConnectSuffix = safe(connectString->Attribute("suffix")); } } } // Parsing of the source config section auto sourceConfig = site->FirstChildElement("source-config"); if (sourceConfig) { auto cacheTempDir = sourceConfig->FirstChildElement("cache-temp-dir"); if (cacheTempDir) { m_cacheTempDir = safe(cacheTempDir->Attribute("name")); m_cacheTempDirPtr = &m_cacheTempDir; } auto cacheMinFree = sourceConfig->FirstChildElement("cache-min-free"); if (cacheMinFree) { //TODO what did xerces do if it couldn't convert? m_cacheMinFree = cacheMinFree->DoubleAttribute("value"); m_cacheMinFreePtr = &m_cacheMinFree; } auto cacheHint = sourceConfig->FirstChildElement("cache-hint"); if (cacheHint) { m_cacheHint = safe(cacheHint->Attribute("value")); m_cacheHintPtr = &m_cacheHint; } auto cloneCacheHint = sourceConfig->FirstChildElement("clone-cache-hint"); if (cloneCacheHint) { m_cloneCacheHint = safe(cloneCacheHint->Attribute("value")); m_cloneCacheHintPtr = &m_cloneCacheHint; } auto readHint = sourceConfig->FirstChildElement("read-hint"); if (readHint) { m_readHint = safe(readHint->Attribute("value")); m_readHintPtr = &m_readHint; } auto ttreeCacheSize = sourceConfig->FirstChildElement("ttree-cache-size"); if (ttreeCacheSize) { m_ttreeCacheSize = ttreeCacheSize->UnsignedAttribute("value"); m_ttreeCacheSizePtr = &m_ttreeCacheSize; } auto timeout = sourceConfig->FirstChildElement("timeout-in-seconds"); if (timeout) { m_timeout = timeout->UnsignedAttribute("value"); m_timeoutPtr = &m_timeout; } auto statsDest = sourceConfig->FirstChildElement("statistics-destination"); if (statsDest) { m_statisticsDestination = safe(statsDest->Attribute("endpoint")); if (m_statisticsDestination.empty()) { m_statisticsDestination = safe(statsDest->Attribute("name")); } std::string tmpStatisticsInfo = safe(statsDest->Attribute("info")); boost::split(m_statisticsInfo, tmpStatisticsInfo, boost::is_any_of("\t ,")); m_statisticsInfoAvail = !tmpStatisticsInfo.empty(); } auto prefetching = sourceConfig->FirstChildElement("prefetching"); if (prefetching) { m_enablePrefetching = prefetching->BoolAttribute("value"); m_enablePrefetchingPtr = &m_enablePrefetching; } auto nativeProtocol = sourceConfig->FirstChildElement("native-protocols"); if (nativeProtocol) { for (auto child = nativeProtocol->FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) { m_nativeProtocols.push_back(safe(child->Attribute("prefix"))); } m_nativeProtocolsPtr = &m_nativeProtocols; } } } m_connected = true; } void SiteLocalConfigService::computeStatisticsDestination() { std::vector<std::string> inputStrings; boost::split(inputStrings, m_statisticsDestination, boost::is_any_of(":")); const std::string &host = inputStrings[0]; const std::string &port = (inputStrings.size() > 1) ? inputStrings[1] : m_statisticsDefaultPort; struct addrinfo *res; struct addrinfo hints; memset(&hints, '\0', sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; int e = getaddrinfo(host.c_str(), port.c_str(), &hints, &res); if (e != 0) { // Silent failure - there's no way to report non-fatal failures from here. return; } m_statisticsAddrInfo = res; } void SiteLocalConfigService::fillDescriptions(ConfigurationDescriptions &descriptions) { ParameterSetDescription desc; desc.setComment("Service to translate logical file names to physical file names."); desc.addOptionalUntracked<std::string>("siteLocalConfigFileUrl", std::string()) ->setComment( "Specify the file containing the site local config. Empty string will load from default directory."); desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir"); desc.addOptionalUntracked<double>("overrideSourceCacheMinFree"); desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir") ->setComment("Set cache hint. See TFileAdaptor plugin for valid values."); desc.addOptionalUntracked<std::string>("overrideSourceCloneCacheHintDir") ->setComment("Provide an alternate cache hint for fast cloning."); desc.addOptionalUntracked<std::string>("overrideSourceReadHint") ->setComment("Set read hint. See TFileAdaptor plugin for valid values."); desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols"); desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize"); desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout"); desc.addOptionalUntracked<unsigned int>("debugLevel"); desc.addOptionalUntracked<bool>("overridePrefetching") ->setComment("Request ROOT to asynchronously prefetch I/O during computation."); desc.addOptionalUntracked<std::string>("overrideStatisticsDestination") ->setComment( "Provide an alternate network destination for I/O statistics (must be in the form of host:port)."); desc.addOptionalUntracked<std::vector<std::string> >("overrideStatisticsInfo") ->setComment( "Provide an alternate listing of statistics to send (comma separated list; current options are 'dn' or " "'nodn'). If left blank, all information is snet (including DNs)."); desc.addOptionalUntracked<bool>("overrideUseLocalConnectString"); desc.addOptionalUntracked<std::string>("overrideLocalConnectPrefix"); desc.addOptionalUntracked<std::string>("overrideLocalConnectSuffix"); descriptions.add("SiteLocalConfigService", desc); } } // namespace service } // namespace edm