CMS 3D CMS Logo

SiteLocalConfigService.cc
Go to the documentation of this file.
1 //<<<<<< INCLUDES >>>>>>
2 
8 #include <xercesc/dom/DOM.hpp>
9 #include <xercesc/parsers/XercesDOMParser.hpp>
12 #include <sstream>
13 #include <memory>
14 #include <boost/algorithm/string.hpp>
15 
16 using namespace xercesc;
17 using namespace cms::xerces;
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(DOMNode const &nodeToConvert) {
34  std::ostringstream oss;
35 
36  DOMNodeList *childList = nodeToConvert.getChildNodes();
37 
38  XMLSize_t numNodes = childList->getLength();
39  for (XMLSize_t i = 0; i < numNodes; ++i) {
40  DOMNode *childNode = childList->item(i);
41  if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
42  continue;
43  }
44  DOMElement *child = static_cast<DOMElement *>(childNode);
45 
46  DOMNamedNodeMap *attributes = child->getAttributes();
47  XMLSize_t numAttributes = attributes->getLength();
48  for (XMLSize_t j = 0; j < numAttributes; ++j) {
49  DOMNode *attributeNode = attributes->item(j);
50  if (attributeNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) {
51  continue;
52  }
53  DOMAttr *attribute = static_cast<DOMAttr *>(attributeNode);
54 
55  oss << "(" << toString(child->getTagName()) << toString(attribute->getName()) << "="
56  << toString(attribute->getValue()) << ")";
57  }
58  }
59  return oss.str();
60  }
61 
62  template <typename T>
63  static void overrideFromPSet(char const *iName, edm::ParameterSet const &iPSet, T &iHolder, T const *&iPointer) {
64  if (iPSet.exists(iName)) {
65  iHolder = iPSet.getUntrackedParameter<T>(iName);
66  iPointer = &iHolder;
67  }
68  }
69 } // namespace
70 
71 namespace edm {
72  namespace service {
73 
74  const std::string SiteLocalConfigService::m_statisticsDefaultPort = "3334";
75 
76  SiteLocalConfigService::SiteLocalConfigService(ParameterSet const &pset)
77  : m_url("/SITECONF/local/JobConfig/site-local-config.xml"),
78  m_dataCatalog(),
79  m_fallbackDataCatalog(),
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  char *tmp = getenv("CMS_PATH");
107 
108  if (tmp) {
109  m_url = tmp + m_url;
110  }
111 
112  this->parse(m_url);
113 
114  //apply overrides
115  overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
116  overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
117  overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
118  overrideFromPSet("overrideSourceCloneCacheHintDir", pset, m_cloneCacheHint, m_cloneCacheHintPtr);
119  overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
120  overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
121  overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
122  overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
123  overrideFromPSet("overridePrefetching", pset, m_enablePrefetching, m_enablePrefetchingPtr);
124  const std::string *tmpStringPtr = nullptr;
125  overrideFromPSet("overrideStatisticsDestination", pset, m_statisticsDestination, tmpStringPtr);
127  std::vector<std::string> tmpStatisticsInfo;
128  std::vector<std::string> const *tmpStatisticsInfoPtr = nullptr;
129  overrideFromPSet("overrideStatisticsInfo", pset, tmpStatisticsInfo, tmpStatisticsInfoPtr);
130  if (tmpStatisticsInfoPtr) {
131  m_statisticsInfoAvail = true;
132  m_statisticsInfo.clear();
133  for (auto &entry : tmpStatisticsInfo) {
135  }
136  }
137 
138  if (pset.exists("debugLevel")) {
139  m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel");
140  }
141  }
142 
144  if (m_statisticsAddrInfo) {
145  freeaddrinfo(m_statisticsAddrInfo);
146  m_statisticsAddrInfo = nullptr;
147  }
148  }
149 
151  if (!m_connected) {
152  //throw cms::Exception("Incomplete configuration")
153  // << "Valid site-local-config not found at " << m_url;
154  // Return PoolFileCatalog.xml for now
155  return "file:PoolFileCatalog.xml";
156  }
157 
158  if (m_dataCatalog.empty()) {
159  throw cms::Exception("Incomplete configuration") << "Did not find catalog in event-data section in " << m_url;
160  }
161 
162  return m_dataCatalog;
163  }
164 
166  if (!m_connected) {
167  //throw cms::Exception("Incomplete configuration")
168  // << "Valid site-local-config not found at " << m_url;
169  // Return PoolFileCatalog.xml for now
170  return "file:PoolFileCatalog.xml";
171  }
172 
173  // Note: Unlike the dataCatalog, the fallbackDataCatalog may be empty!
174  return m_fallbackDataCatalog;
175  }
176 
178  if (!m_connected) {
179  throw cms::Exception("Incomplete configuration") << "Valid site-local-config not found at " << m_url;
180  }
181 
182  if (m_frontierConnect.empty()) {
183  throw cms::Exception("Incomplete configuration")
184  << "Did not find frontier-connect in calib-data section in " << m_url;
185  }
186 
187  if (servlet.empty()) {
188  return m_frontierConnect;
189  }
190 
191  // Replace the last component of every "serverurl=" piece (up to the
192  // next close-paren) with the servlet
193  std::string::size_type nextparen = 0;
194  std::string::size_type serverurl, lastslash;
195  std::string complexstr = "";
196  while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
197  complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
198  nextparen = m_frontierConnect.find(')', serverurl);
199  lastslash = m_frontierConnect.rfind('/', nextparen);
200  complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
201  complexstr.append(servlet);
202  }
203  complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length() - nextparen);
204 
205  return complexstr;
206  }
207 
209  static std::string const proto = "frontier://";
210 
211  if (input.substr(0, proto.length()) == proto) {
212  // Replace the part after the frontier:// and before either an open-
213  // parentheses (which indicates user-supplied options) or the last
214  // slash (which indicates start of the schema) with the complex
215  // parenthesized string returned from frontierConnect() (which
216  // contains all the information needed to connect to frontier),
217  // if that part is a simple servlet name (non-empty and not
218  // containing special characters)
219  // Example connect strings where servlet is replaced:
220  // frontier://cms_conditions_data/CMS_COND_ECAL
221  // frontier://FrontierInt/CMS_COND_ECAL
222  // frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL
223  // Example connect strings left untouched:
224  // frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL
225  // frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL
226  std::string::size_type startservlet = proto.length();
227  // if user supplied extra parenthesized options, stop servlet there
228  std::string::size_type endservlet = input.find("(", startservlet);
229  if (endservlet == std::string::npos) {
230  endservlet = input.rfind('/', input.length());
231  }
232  std::string servlet = input.substr(startservlet, endservlet - startservlet);
233  if ((!servlet.empty()) && (servlet.find_first_of(":/)[]") == std::string::npos)) {
234  if (servlet == "cms_conditions_data") {
235  // use the default servlet from site-local-config.xml
236  servlet = "";
237  }
238  return proto + frontierConnect(servlet) + input.substr(endservlet);
239  }
240  }
241  return input;
242  }
243 
245 
247 
249 
251 
253 
255 
257 
258  unsigned int const *SiteLocalConfigService::sourceTimeout() const { return m_timeoutPtr; }
259 
262  }
263 
264  unsigned int SiteLocalConfigService::debugLevel() const { return m_debugLevel; }
265 
266  std::vector<std::string> const *SiteLocalConfigService::sourceNativeProtocols() const {
267  return m_nativeProtocolsPtr;
268  }
269 
270  struct addrinfo const *SiteLocalConfigService::statisticsDestination() const {
271  return m_statisticsAddrInfo;
272  }
273 
274  std::set<std::string> const *SiteLocalConfigService::statisticsInfo() const {
275  return m_statisticsInfoAvail ? &m_statisticsInfo : nullptr;
276  }
277 
279 
282  {
283  auto parser = std::make_unique<XercesDOMParser>();
284  try {
285  parser->setValidationScheme(XercesDOMParser::Val_Auto);
286  parser->setDoNamespaces(false);
287 
288  parser->parse(url.c_str());
289  DOMDocument *doc = parser->getDocument();
290  if (!doc) {
291  return;
292  }
293 
294  // The Site Config has the following format
295  // <site-local-config>
296  // <site name="FNAL">
297  // <event-data>
298  // <catalog url="trivialcatalog_file:/x/y/z.xml"/>
299  // <rfiotype value="castor"/>
300  // </event-data>
301  // <calib-data>
302  // <catalog url="trivialcatalog_file:/x/y/z.xml"/>
303  // <frontier-connect>
304  // ... frontier-interpreted server/proxy xml ...
305  // </frontier-connect>
306  // </calib-data>
307  // <source-config>
308  // <cache-temp-dir name="/a/b/c"/>
309  // <cache-hint value="..."/>
310  // <read-hint value="..."/>
311  // <ttree-cache-size value="0"/>
312  // <native-protocols>
313  // <protocol prefix="dcache"/>
314  // <protocol prefix="file"/>
315  // </native-protocols>
316  // </source-config>
317  // </site>
318  // </site-local-config>
319 
320  // FIXME: should probably use the parser for validating the XML.
321 
322  DOMNodeList *sites = doc->getElementsByTagName(uStr("site").ptr());
323  XMLSize_t numSites = sites->getLength();
324  for (XMLSize_t i = 0; i < numSites; ++i) {
325  DOMElement *site = static_cast<DOMElement *>(sites->item(i));
326 
327  // Parse the site name
328  m_siteName = toString(site->getAttribute(uStr("name").ptr()));
329 
330  // Parsing of the event data section
331  {
332  DOMNodeList *eventDataList = site->getElementsByTagName(uStr("event-data").ptr());
333  if (eventDataList->getLength() > 0) {
334  DOMElement *eventData = static_cast<DOMElement *>(eventDataList->item(0));
335 
336  DOMNodeList *catalogs = eventData->getElementsByTagName(uStr("catalog").ptr());
337 
338  if (catalogs->getLength() > 0) {
339  DOMElement *catalog = static_cast<DOMElement *>(catalogs->item(0));
340  m_dataCatalog = toString(catalog->getAttribute(uStr("url").ptr()));
341  }
342 
343  if (catalogs->getLength() > 1) {
344  DOMElement *catalog = static_cast<DOMElement *>(catalogs->item(1));
345  m_fallbackDataCatalog = toString(catalog->getAttribute(uStr("url").ptr()));
346  }
347 
348  DOMNodeList *rfiotypes = eventData->getElementsByTagName(uStr("rfiotype").ptr());
349 
350  if (rfiotypes->getLength() > 0) {
351  DOMElement *rfiotype = static_cast<DOMElement *>(rfiotypes->item(0));
352  m_rfioType = toString(rfiotype->getAttribute(uStr("value").ptr()));
353  }
354  }
355  }
356 
357  // Parsing of the calib-data section
358  {
359  DOMNodeList *calibDataList = site->getElementsByTagName(uStr("calib-data").ptr());
360 
361  if (calibDataList->getLength() > 0) {
362  DOMElement *calibData = static_cast<DOMElement *>(calibDataList->item(0));
363  DOMNodeList *frontierConnectList = calibData->getElementsByTagName(uStr("frontier-connect").ptr());
364 
365  if (frontierConnectList->getLength() > 0) {
366  DOMElement *frontierConnect = static_cast<DOMElement *>(frontierConnectList->item(0));
367  m_frontierConnect = _toParenString(*frontierConnect);
368  }
369  }
370  }
371  // Parsing of the source config section
372  {
373  DOMNodeList *sourceConfigList = site->getElementsByTagName(uStr("source-config").ptr());
374 
375  if (sourceConfigList->getLength() > 0) {
376  DOMElement *sourceConfig = static_cast<DOMElement *>(sourceConfigList->item(0));
377  DOMNodeList *cacheTempDirList = sourceConfig->getElementsByTagName(uStr("cache-temp-dir").ptr());
378 
379  if (cacheTempDirList->getLength() > 0) {
380  DOMElement *cacheTempDir = static_cast<DOMElement *>(cacheTempDirList->item(0));
381  m_cacheTempDir = toString(cacheTempDir->getAttribute(uStr("name").ptr()));
383  }
384 
385  DOMNodeList *cacheMinFreeList = sourceConfig->getElementsByTagName(uStr("cache-min-free").ptr());
386 
387  if (cacheMinFreeList->getLength() > 0) {
388  DOMElement *cacheMinFree = static_cast<DOMElement *>(cacheMinFreeList->item(0));
389  m_cacheMinFree = toDouble(cacheMinFree->getAttribute(uStr("value").ptr()));
391  }
392 
393  DOMNodeList *cacheHintList = sourceConfig->getElementsByTagName(uStr("cache-hint").ptr());
394 
395  if (cacheHintList->getLength() > 0) {
396  DOMElement *cacheHint = static_cast<DOMElement *>(cacheHintList->item(0));
397  m_cacheHint = toString(cacheHint->getAttribute(uStr("value").ptr()));
399  }
400 
401  DOMNodeList *cloneCacheHintList = sourceConfig->getElementsByTagName(uStr("clone-cache-hint").ptr());
402 
403  if (cloneCacheHintList->getLength() > 0) {
404  DOMElement *cloneCacheHint = static_cast<DOMElement *>(cloneCacheHintList->item(0));
405  m_cloneCacheHint = toString(cloneCacheHint->getAttribute(uStr("value").ptr()));
407  }
408 
409  DOMNodeList *readHintList = sourceConfig->getElementsByTagName(uStr("read-hint").ptr());
410 
411  if (readHintList->getLength() > 0) {
412  DOMElement *readHint = static_cast<DOMElement *>(readHintList->item(0));
413  m_readHint = toString(readHint->getAttribute(uStr("value").ptr()));
415  }
416 
417  DOMNodeList *ttreeCacheSizeList = sourceConfig->getElementsByTagName(uStr("ttree-cache-size").ptr());
418 
419  if (ttreeCacheSizeList->getLength() > 0) {
420  DOMElement *ttreeCacheSize = static_cast<DOMElement *>(ttreeCacheSizeList->item(0));
421  m_ttreeCacheSize = toUInt(ttreeCacheSize->getAttribute(uStr("value").ptr()));
423  }
424 
425  DOMNodeList *timeoutList = sourceConfig->getElementsByTagName(uStr("timeout-in-seconds").ptr());
426 
427  if (timeoutList->getLength() > 0) {
428  DOMElement *timeout = static_cast<DOMElement *>(timeoutList->item(0));
429  m_timeout = toUInt(timeout->getAttribute(uStr("value").ptr()));
431  }
432 
433  DOMNodeList *statsDestList = sourceConfig->getElementsByTagName(uStr("statistics-destination").ptr());
434 
435  if (statsDestList->getLength() > 0) {
436  DOMElement *statsDest = static_cast<DOMElement *>(statsDestList->item(0));
437  m_statisticsDestination = toString(statsDest->getAttribute(uStr("endpoint").ptr()));
438  if (m_statisticsDestination.empty()) {
439  m_statisticsDestination = toString(statsDest->getAttribute(uStr("name").ptr()));
440  }
441  std::string tmpStatisticsInfo = toString(statsDest->getAttribute(uStr("info").ptr()));
442  boost::split(m_statisticsInfo, tmpStatisticsInfo, boost::is_any_of("\t ,"));
443  m_statisticsInfoAvail = !tmpStatisticsInfo.empty();
444  }
445 
446  DOMNodeList *prefetchingList = sourceConfig->getElementsByTagName(uStr("prefetching").ptr());
447 
448  if (prefetchingList->getLength() > 0) {
449  DOMElement *prefetching = static_cast<DOMElement *>(prefetchingList->item(0));
450  m_enablePrefetching = toBool(prefetching->getAttribute(uStr("value").ptr()));
452  }
453 
454  DOMNodeList *nativeProtocolsList = sourceConfig->getElementsByTagName(uStr("native-protocols").ptr());
455 
456  if (nativeProtocolsList->getLength() > 0) {
457  DOMElement *nativeProtocol = static_cast<DOMElement *>(nativeProtocolsList->item(0));
458  DOMNodeList *childList = nativeProtocol->getChildNodes();
459 
460  XMLSize_t numNodes = childList->getLength();
461  for (XMLSize_t i = 0; i < numNodes; ++i) {
462  DOMNode *childNode = childList->item(i);
463  if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
464  continue;
465  }
466  DOMElement *child = static_cast<DOMElement *>(childNode);
467  m_nativeProtocols.push_back(toString(child->getAttribute(uStr("prefix").ptr())));
468  }
470  }
471  }
472  }
473  }
474  m_connected = true;
475  } catch (xercesc::DOMException const &e) {
476  }
477  } // The extra pair of braces ensures that
478  // all implicit destructors are called
479  // *before* terminating Xerces-C++.
481  }
482 
484  std::vector<std::string> inputStrings;
485  boost::split(inputStrings, m_statisticsDestination, boost::is_any_of(":"));
486  const std::string &host = inputStrings[0];
487  const std::string &port = (inputStrings.size() > 1) ? inputStrings[1] : m_statisticsDefaultPort;
488  struct addrinfo *res;
489  struct addrinfo hints;
490  memset(&hints, '\0', sizeof(hints));
491  hints.ai_socktype = SOCK_DGRAM;
492  hints.ai_flags = AI_ADDRCONFIG;
493  hints.ai_family = AF_UNSPEC;
494  int e = getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
495  if (e != 0) {
496  // Silent failure - there's no way to report non-fatal failures from here.
497  return;
498  }
499  m_statisticsAddrInfo = res;
500  }
501 
504  desc.setComment("Service to translate logical file names to physical file names.");
505 
506  desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
507  desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
508  desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
509  desc.addOptionalUntracked<std::string>("overrideSourceCloneCacheHintDir")
510  ->setComment("Provide an alternate cache hint for fast cloning.");
511  desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
512  desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
513  desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
514  desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
515  desc.addOptionalUntracked<unsigned int>("debugLevel");
516  desc.addOptionalUntracked<bool>("overridePrefetching")
517  ->setComment("Request ROOT to asynchronously prefetch I/O during computation.");
518  desc.addOptionalUntracked<std::string>("overrideStatisticsDestination")
519  ->setComment(
520  "Provide an alternate network destination for I/O statistics (must be in the form of host:port).");
521  desc.addOptionalUntracked<std::vector<std::string> >("overrideStatisticsInfo")
522  ->setComment(
523  "Provide an alternate listing of statistics to send (comma separated list; current options are 'dn' or "
524  "'nodn'). If left blank, all information is snet (including DNs).");
525 
526  descriptions.add("SiteLocalConfigService", desc);
527  }
528  } // namespace service
529 } // namespace edm
T getUntrackedParameter(std::string const &, T const &) const
host
Definition: query.py:115
unsigned int const * sourceTTreeCacheSize() const override
static void fillDescriptions(ConfigurationDescriptions &descriptions)
std::string const fallbackDataCatalog(void) const override
void xercesTerminate()
Definition: Xerces.cc:23
static const std::string m_statisticsDefaultPort
#define nullptr
bool exists(std::string const &parameterName) const
checks if a parameter exists
double toDouble(XMLCh const *toTranscode)
void xercesInitialize()
Definition: Xerces.cc:18
uint16_t size_type
std::string const dataCatalog(void) const override
port
Definition: query.py:116
Definition: Electron.h:6
std::vector< std::string > const * m_nativeProtocolsPtr
static std::string const input
Definition: EdmProvDump.cc:48
std::set< std::string > const * statisticsInfo() const override
void setComment(std::string const &value)
edm::propagate_const< struct addrinfo * > m_statisticsAddrInfo
unsigned int const * sourceTimeout() const override
std::string const rfioType(void) const override
unsigned int toUInt(XMLCh const *toTranscode)
std::string const * sourceCloneCacheHint() const override
ZStr< XMLCh > uStr(char const *str)
std::string const & siteName() const override
std::vector< std::string > const * sourceNativeProtocols() const override
std::string const * sourceCacheHint() const override
struct addrinfo const * statisticsDestination() const override
std::vector< std::string > m_nativeProtocols
double const * sourceCacheMinFree() const override
std::string const * sourceReadHint() const override
std::string const lookupCalibConnect(std::string const &input) const override
std::string toString(const std::pair< T, T > &aT)
Definition: CaloEllipse.h:72
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
HLT enums.
std::string const * sourceCacheTempDir() const override
ParameterDescriptionBase * addOptionalUntracked(U const &iLabel, T const &value)
std::string const frontierConnect(std::string const &servlet) const
bool toBool(XMLCh const *toTranscode)
long double T
double split
Definition: MVATrainer.cc:139
def move(src, dest)
Definition: eostools.py:511
unsigned int debugLevel() const override