CMS 3D CMS Logo

SiteLocalConfigService.cc
Go to the documentation of this file.
1 //
3 // data catalogs are filled in "parse"
4 //
6 
7 //<<<<<< INCLUDES >>>>>>
8 
14 #include "tinyxml2.h"
15 #include <sstream>
16 #include <memory>
17 #include <boost/algorithm/string.hpp>
18 
19 //<<<<<< PRIVATE DEFINES >>>>>>
20 //<<<<<< PRIVATE CONSTANTS >>>>>>
21 //<<<<<< PRIVATE TYPES >>>>>>
22 //<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>>
23 //<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>>
24 //<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>>
25 //<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>>
26 //<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>>
27 //<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>>
28 
29 namespace {
30 
31  // concatenate all the XML node attribute/value pairs into a
32  // paren-separated string (for use by CORAL and frontier_client)
33  inline std::string _toParenString(tinyxml2::XMLElement const &nodeToConvert) {
34  std::ostringstream oss;
35 
36  for (auto child = nodeToConvert.FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) {
37  for (auto attribute = child->FirstAttribute(); attribute != nullptr; attribute = attribute->Next()) {
38  oss << "(" << child->Name() << attribute->Name() << "=" << attribute->Value() << ")";
39  }
40  }
41  return oss.str();
42  }
43 
44  template <typename T>
45  static void overrideFromPSet(char const *iName, edm::ParameterSet const &iPSet, T &iHolder, T const *&iPointer) {
46  if (iPSet.exists(iName)) {
47  iHolder = iPSet.getUntrackedParameter<T>(iName);
48  iPointer = &iHolder;
49  }
50  }
51 
52  constexpr char const *const kEmptyString = "";
53  const char *safe(const char *iCheck) {
54  if (iCheck == nullptr) {
55  return kEmptyString;
56  }
57  return iCheck;
58  }
59 
60  std::string defaultURL() {
61  std::string returnValue;
62  const char *tmp = std::getenv("CMS_PATH");
63  if (tmp) {
64  returnValue = tmp;
65  }
66  returnValue += "/SITECONF/local/JobConfig/site-local-config.xml";
67  return returnValue;
68  }
69 
70 } // namespace
71 
72 namespace edm {
73  namespace service {
74 
76 
78  : m_url(pset.getUntrackedParameter<std::string>("siteLocalConfigFileUrl", defaultURL())),
79  m_dataCatalogs(),
80  m_frontierConnect(),
81  m_rfioType("castor"),
82  m_connected(false),
83  m_cacheTempDir(),
84  m_cacheTempDirPtr(nullptr),
85  m_cacheMinFree(),
86  m_cacheMinFreePtr(nullptr),
87  m_cacheHint(),
88  m_cacheHintPtr(nullptr),
89  m_cloneCacheHint(),
90  m_cloneCacheHintPtr(nullptr),
91  m_readHint(),
92  m_readHintPtr(nullptr),
93  m_ttreeCacheSize(0U),
94  m_ttreeCacheSizePtr(nullptr),
95  m_timeout(0U),
96  m_timeoutPtr(nullptr),
97  m_debugLevel(0U),
98  m_enablePrefetching(false),
99  m_enablePrefetchingPtr(nullptr),
100  m_nativeProtocols(),
101  m_nativeProtocolsPtr(nullptr),
102  m_statisticsDestination(),
103  m_statisticsAddrInfo(nullptr),
104  m_statisticsInfoAvail(false),
105  m_siteName() {
106  this->parse(m_url);
107 
108  //apply overrides
109  overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
110  overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
111  overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
112  overrideFromPSet("overrideSourceCloneCacheHintDir", pset, m_cloneCacheHint, m_cloneCacheHintPtr);
113  overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
114  overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
115  overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
116  overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
117  overrideFromPSet("overridePrefetching", pset, m_enablePrefetching, m_enablePrefetchingPtr);
118  const std::string *tmpStringPtr = nullptr;
119  overrideFromPSet("overrideStatisticsDestination", pset, m_statisticsDestination, tmpStringPtr);
121  std::vector<std::string> tmpStatisticsInfo;
122  std::vector<std::string> const *tmpStatisticsInfoPtr = nullptr;
123  overrideFromPSet("overrideStatisticsInfo", pset, tmpStatisticsInfo, tmpStatisticsInfoPtr);
124  if (tmpStatisticsInfoPtr) {
125  m_statisticsInfoAvail = true;
126  m_statisticsInfo.clear();
127  for (auto &entry : tmpStatisticsInfo) {
129  }
130  }
131 
132  if (pset.exists("debugLevel")) {
133  m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel");
134  }
135  if (pset.exists("overrideUseLocalConnectString")) {
136  m_useLocalConnectString = pset.getUntrackedParameter<bool>("overrideUseLocalConnectString");
137  }
138  if (pset.exists("overrideLocalConnectPrefix")) {
139  m_localConnectPrefix = pset.getUntrackedParameter<std::string>("overrideLocalConnectPrefix");
140  }
141  if (pset.exists("overrideLocalConnectSuffix")) {
142  m_localConnectSuffix = pset.getUntrackedParameter<std::string>("overrideLocalConnectSuffix");
143  }
144  }
145 
147  if (m_statisticsAddrInfo) {
148  freeaddrinfo(m_statisticsAddrInfo);
149  m_statisticsAddrInfo = nullptr;
150  }
151  }
152 
153  std::vector<std::string> const &SiteLocalConfigService::dataCatalogs(void) const {
154  if (!m_connected) {
155  //throw cms::Exception("Incomplete configuration")
156  // << "Valid site-local-config not found at " << m_url;
157  // Return PoolFileCatalog.xml for now
158  static std::vector<std::string> const tmp{"file:PoolFileCatalog.xml"};
159  return tmp;
160  }
161 
162  if (m_dataCatalogs.empty()) {
163  throw cms::Exception("Incomplete configuration") << "Did not find catalogs in event-data section in " << m_url;
164  }
165 
166  return m_dataCatalogs;
167  }
168 
170  if (!m_connected) {
171  throw cms::Exception("Incomplete configuration") << "Valid site-local-config not found at " << m_url;
172  }
173 
174  if (m_frontierConnect.empty()) {
175  throw cms::Exception("Incomplete configuration")
176  << "Did not find frontier-connect in calib-data section in " << m_url;
177  }
178 
179  if (servlet.empty()) {
180  return m_frontierConnect;
181  }
182 
183  // Replace the last component of every "serverurl=" piece (up to the
184  // next close-paren) with the servlet
185  std::string::size_type nextparen = 0;
186  std::string::size_type serverurl, lastslash;
187  std::string complexstr = "";
188  while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
189  complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
190  nextparen = m_frontierConnect.find(')', serverurl);
191  lastslash = m_frontierConnect.rfind('/', nextparen);
192  complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
193  complexstr.append(servlet);
194  }
195  complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length() - nextparen);
196 
197  return complexstr;
198  }
199 
201  static std::string const proto = "frontier://";
202 
203  if (input.substr(0, proto.length()) == proto) {
204  // Replace the part after the frontier:// and before either an open-
205  // parentheses (which indicates user-supplied options) or the last
206  // slash (which indicates start of the schema) with the complex
207  // parenthesized string returned from frontierConnect() (which
208  // contains all the information needed to connect to frontier),
209  // if that part is a simple servlet name (non-empty and not
210  // containing special characters)
211  // Example connect strings where servlet is replaced:
212  // frontier://cms_conditions_data/CMS_COND_ECAL
213  // frontier://FrontierInt/CMS_COND_ECAL
214  // frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL
215  // Example connect strings left untouched:
216  // frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL
217  // frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL
218  std::string::size_type startservlet = proto.length();
219  // if user supplied extra parenthesized options, stop servlet there
220  std::string::size_type endservlet = input.find('(', startservlet);
221  if (endservlet == std::string::npos) {
222  endservlet = input.rfind('/', input.length());
223  }
224  std::string servlet = input.substr(startservlet, endservlet - startservlet);
225  if ((!servlet.empty()) && (servlet.find_first_of(":/)[]") == std::string::npos)) {
226  if (servlet == "cms_conditions_data") {
227  // use the default servlet from site-local-config.xml
228  servlet = "";
229  }
230  return proto + frontierConnect(servlet) + input.substr(endservlet);
231  }
232  }
233  return input;
234  }
235 
237 
239 
241 
243 
245 
247 
249 
250  unsigned int const *SiteLocalConfigService::sourceTimeout() const { return m_timeoutPtr; }
251 
254  }
255 
256  unsigned int SiteLocalConfigService::debugLevel() const { return m_debugLevel; }
257 
258  std::vector<std::string> const *SiteLocalConfigService::sourceNativeProtocols() const {
259  return m_nativeProtocolsPtr;
260  }
261 
263  return m_statisticsAddrInfo;
264  }
265 
266  std::set<std::string> const *SiteLocalConfigService::statisticsInfo() const {
267  return m_statisticsInfoAvail ? &m_statisticsInfo : nullptr;
268  }
269 
274 
276  tinyxml2::XMLDocument doc;
277  auto loadErr = doc.LoadFile(url.c_str());
278  if (loadErr != tinyxml2::XML_SUCCESS) {
279  return;
280  }
281 
282  // The Site Config has the following format
283  // <site-local-config>
284  // <site name="FNAL">
285  // <event-data>
286  // <catalog url="trivialcatalog_file:/x/y/z.xml"/>
287  // <rfiotype value="castor"/>
288  // </event-data>
289  // <calib-data>
290  // <catalog url="trivialcatalog_file:/x/y/z.xml"/>
291  // <frontier-connect>
292  // ... frontier-interpreted server/proxy xml ...
293  // </frontier-connect>
294  // <local-connect>
295  // <connectString prefix="anything1" suffix="anything2"/>
296  // </local-connect>
297  // </calib-data>
298  // <source-config>
299  // <cache-temp-dir name="/a/b/c"/>
300  // <cache-hint value="..."/>
301  // <read-hint value="..."/>
302  // <ttree-cache-size value="0"/>
303  // <native-protocols>
304  // <protocol prefix="dcache"/>
305  // <protocol prefix="file"/>
306  // </native-protocols>
307  // </source-config>
308  // </site>
309  // </site-local-config>
310  auto rootElement = doc.RootElement();
311 
312  for (auto site = rootElement->FirstChildElement("site"); site != nullptr;
313  site = site->NextSiblingElement("site")) {
314  // Parse the site name
315  m_siteName = safe(site->Attribute("name"));
316 
317  // Parsing of the event data section
318  {
319  auto eventData = site->FirstChildElement("event-data");
320  if (eventData) {
321  auto catalog = eventData->FirstChildElement("catalog");
322  if (catalog) {
323  m_dataCatalogs.push_back(safe(catalog->Attribute("url")));
324  catalog = catalog->NextSiblingElement("catalog");
325  while (catalog) {
326  m_dataCatalogs.push_back(safe(catalog->Attribute("url")));
327  catalog = catalog->NextSiblingElement("catalog");
328  }
329  }
330  auto rfiotype = eventData->FirstChildElement("rfiotype");
331  if (rfiotype) {
332  m_rfioType = safe(rfiotype->Attribute("value"));
333  }
334  }
335  }
336 
337  // Parsing of the calib-data section
338  {
339  auto calibData = site->FirstChildElement("calib-data");
340 
341  if (calibData) {
342  auto frontierConnect = calibData->FirstChildElement("frontier-connect");
343 
344  if (frontierConnect) {
345  m_frontierConnect = _toParenString(*frontierConnect);
346  }
347  auto localConnect = calibData->FirstChildElement("local-connect");
348  if (localConnect) {
349  if (frontierConnect) {
350  throw cms::Exception("Illegal site local configuration")
351  << "It is illegal to include both frontier-connect and local-connect in the same XML file";
352  }
354  auto connectString = localConnect->FirstChildElement("connectString");
355  if (connectString) {
356  m_localConnectPrefix = safe(connectString->Attribute("prefix"));
357  m_localConnectSuffix = safe(connectString->Attribute("suffix"));
358  }
359  }
360  }
361  }
362 
363  // Parsing of the source config section
364  {
365  auto sourceConfig = site->FirstChildElement("source-config");
366 
367  if (sourceConfig) {
368  auto cacheTempDir = sourceConfig->FirstChildElement("cache-temp-dir");
369 
370  if (cacheTempDir) {
371  m_cacheTempDir = safe(cacheTempDir->Attribute("name"));
373  }
374 
375  auto cacheMinFree = sourceConfig->FirstChildElement("cache-min-free");
376 
377  if (cacheMinFree) {
378  //TODO what did xerces do if it couldn't convert?
379  m_cacheMinFree = cacheMinFree->DoubleAttribute("value");
381  }
382 
383  auto cacheHint = sourceConfig->FirstChildElement("cache-hint");
384 
385  if (cacheHint) {
386  m_cacheHint = safe(cacheHint->Attribute("value"));
388  }
389 
390  auto cloneCacheHint = sourceConfig->FirstChildElement("clone-cache-hint");
391 
392  if (cloneCacheHint) {
393  m_cloneCacheHint = safe(cloneCacheHint->Attribute("value"));
395  }
396 
397  auto readHint = sourceConfig->FirstChildElement("read-hint");
398 
399  if (readHint) {
400  m_readHint = safe(readHint->Attribute("value"));
402  }
403 
404  auto ttreeCacheSize = sourceConfig->FirstChildElement("ttree-cache-size");
405 
406  if (ttreeCacheSize) {
407  m_ttreeCacheSize = ttreeCacheSize->UnsignedAttribute("value");
409  }
410 
411  auto timeout = sourceConfig->FirstChildElement("timeout-in-seconds");
412 
413  if (timeout) {
414  m_timeout = timeout->UnsignedAttribute("value");
416  }
417 
418  auto statsDest = sourceConfig->FirstChildElement("statistics-destination");
419 
420  if (statsDest) {
421  m_statisticsDestination = safe(statsDest->Attribute("endpoint"));
422  if (m_statisticsDestination.empty()) {
423  m_statisticsDestination = safe(statsDest->Attribute("name"));
424  }
425  std::string tmpStatisticsInfo = safe(statsDest->Attribute("info"));
426  boost::split(m_statisticsInfo, tmpStatisticsInfo, boost::is_any_of("\t ,"));
427  m_statisticsInfoAvail = !tmpStatisticsInfo.empty();
428  }
429 
430  auto prefetching = sourceConfig->FirstChildElement("prefetching");
431 
432  if (prefetching) {
433  m_enablePrefetching = prefetching->BoolAttribute("value");
435  }
436 
437  auto nativeProtocol = sourceConfig->FirstChildElement("native-protocols");
438 
439  if (nativeProtocol) {
440  for (auto child = nativeProtocol->FirstChildElement(); child != nullptr;
441  child = child->NextSiblingElement()) {
442  m_nativeProtocols.push_back(safe(child->Attribute("prefix")));
443  }
445  }
446  }
447  }
448  }
449  m_connected = true;
450  }
451 
453  std::vector<std::string> inputStrings;
454  boost::split(inputStrings, m_statisticsDestination, boost::is_any_of(":"));
455  const std::string &host = inputStrings[0];
456  const std::string &port = (inputStrings.size() > 1) ? inputStrings[1] : m_statisticsDefaultPort;
457  struct addrinfo *res;
458  struct addrinfo hints;
459  memset(&hints, '\0', sizeof(hints));
460  hints.ai_socktype = SOCK_DGRAM;
461  hints.ai_flags = AI_ADDRCONFIG;
462  hints.ai_family = AF_UNSPEC;
463  int e = getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
464  if (e != 0) {
465  // Silent failure - there's no way to report non-fatal failures from here.
466  return;
467  }
469  }
470 
473  desc.setComment("Service to translate logical file names to physical file names.");
474 
475  desc.addOptionalUntracked<std::string>("siteLocalConfigFileUrl", std::string())
476  ->setComment(
477  "Specify the file containing the site local config. Empty string will load from default directory.");
478  desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
479  desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
480  desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
481  desc.addOptionalUntracked<std::string>("overrideSourceCloneCacheHintDir")
482  ->setComment("Provide an alternate cache hint for fast cloning.");
483  desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
484  desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
485  desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
486  desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
487  desc.addOptionalUntracked<unsigned int>("debugLevel");
488  desc.addOptionalUntracked<bool>("overridePrefetching")
489  ->setComment("Request ROOT to asynchronously prefetch I/O during computation.");
490  desc.addOptionalUntracked<std::string>("overrideStatisticsDestination")
491  ->setComment(
492  "Provide an alternate network destination for I/O statistics (must be in the form of host:port).");
493  desc.addOptionalUntracked<std::vector<std::string> >("overrideStatisticsInfo")
494  ->setComment(
495  "Provide an alternate listing of statistics to send (comma separated list; current options are 'dn' or "
496  "'nodn'). If left blank, all information is snet (including DNs).");
497  desc.addOptionalUntracked<bool>("overrideUseLocalConnectString");
498  desc.addOptionalUntracked<std::string>("overrideLocalConnectPrefix");
499  desc.addOptionalUntracked<std::string>("overrideLocalConnectSuffix");
500  descriptions.add("SiteLocalConfigService", desc);
501  }
502  } // namespace service
503 } // namespace edm
static void fillDescriptions(ConfigurationDescriptions &descriptions)
struct addrinfo const * statisticsDestination() const override
string host
Definition: query.py:115
bool exists(std::string const &parameterName) const
checks if a parameter exists
static const std::string m_statisticsDefaultPort
std::string const * sourceCacheHint() const override
std::string const * sourceReadHint() const override
std::vector< std::string > const & dataCatalogs(void) const override
unsigned int const * sourceTimeout() const override
std::vector< std::string > m_dataCatalogs
int port
Definition: query.py:116
uint16_t size_type
Definition: Electron.h:6
std::vector< std::string > const * sourceNativeProtocols() const override
std::vector< std::string > const * m_nativeProtocolsPtr
std::string const * sourceCacheTempDir() const override
static std::string const input
Definition: EdmProvDump.cc:50
std::string const & localConnectPrefix() const override
T getUntrackedParameter(std::string const &, T const &) const
edm::propagate_const< struct addrinfo * > m_statisticsAddrInfo
std::string const rfioType(void) const override
std::string const frontierConnect(std::string const &servlet) const
std::vector< std::string > m_nativeProtocols
unsigned int const * sourceTTreeCacheSize() const override
std::string const & localConnectSuffix() const override
unsigned int debugLevel() const override
SiteLocalConfigService(ParameterSet const &pset)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::set< std::string > const * statisticsInfo() const override
static const char kEmptyString[1]
double const * sourceCacheMinFree() const override
HLT enums.
std::string const * sourceCloneCacheHint() const override
std::string const lookupCalibConnect(std::string const &input) const override
tmp
align.sh
Definition: createJobs.py:716
long double T
def move(src, dest)
Definition: eostools.py:511
std::string const & siteName() const override