00001
00002
00003 #include "FWCore/Services/src/SiteLocalConfigService.h"
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00007 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00008 #include <xercesc/dom/DOM.hpp>
00009 #include <xercesc/parsers/XercesDOMParser.hpp>
00010 #include <xercesc/util/PlatformUtils.hpp>
00011 #include <xercesc/util/XMLString.hpp>
00012 #include <sstream>
00013 #include <memory>
00014 #include <boost/algorithm/string.hpp>
00015
00016 using namespace xercesc;
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 namespace {
00029 inline std::string _toString(XMLCh const* toTranscode) {
00030 std::string tmp(XMLString::transcode(toTranscode));
00031 return tmp;
00032 }
00033
00034 inline unsigned int _toUInt(XMLCh const* toTranscode) {
00035 std::istringstream iss(_toString(toTranscode));
00036 unsigned int returnValue;
00037 iss >> returnValue;
00038 return returnValue;
00039 }
00040
00041 inline bool _toBool(XMLCh const* toTranscode) {
00042 std::string value = _toString(toTranscode);
00043 if ((value == "true") || (value == "1"))
00044 return true;
00045 return false;
00046 }
00047
00048 inline double _toDouble(XMLCh const* toTranscode) {
00049 std::istringstream iss(_toString(toTranscode));
00050 double returnValue;
00051 iss >> returnValue;
00052 return returnValue;
00053 }
00054
00055 inline XMLCh* _toDOMS(std::string temp) {
00056 XMLCh* buff = XMLString::transcode(temp.c_str());
00057 return buff;
00058 }
00059
00060
00061
00062 inline std::string _toParenString(DOMNode const& nodeToConvert) {
00063 std::ostringstream oss;
00064
00065 DOMNodeList *childList = nodeToConvert.getChildNodes();
00066
00067 unsigned int numNodes = childList->getLength();
00068 for (unsigned int i = 0; i < numNodes; ++i) {
00069 DOMNode *childNode = childList->item(i);
00070 if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
00071 continue;
00072 }
00073 DOMElement *child = static_cast<DOMElement *>(childNode);
00074
00075 DOMNamedNodeMap *attributes = child->getAttributes();
00076 unsigned int numAttributes = attributes->getLength();
00077 for (unsigned int j = 0; j < numAttributes; ++j) {
00078 DOMNode *attributeNode = attributes->item(j);
00079 if (attributeNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) {
00080 continue;
00081 }
00082 DOMAttr *attribute = static_cast<DOMAttr *>(attributeNode);
00083
00084 oss << "(" << _toString(child->getTagName()) <<
00085 _toString(attribute->getName()) << "=" <<
00086 _toString(attribute->getValue()) << ")";
00087 }
00088 }
00089 return oss.str();
00090 }
00091
00092 template<typename T>
00093 static
00094 void overrideFromPSet(char const* iName, edm::ParameterSet const& iPSet,
00095 T& iHolder, T const*& iPointer) {
00096 if(iPSet.exists(iName)) {
00097 iHolder = iPSet.getUntrackedParameter<T>(iName);
00098 iPointer = &iHolder;
00099 }
00100 }
00101 }
00102
00103 namespace edm {
00104 namespace service {
00105
00106 const std::string SiteLocalConfigService::m_statisticsDefaultPort = "3334";
00107
00108 SiteLocalConfigService::SiteLocalConfigService(ParameterSet const& pset) :
00109 m_url("/SITECONF/local/JobConfig/site-local-config.xml"),
00110 m_dataCatalog(),
00111 m_fallbackDataCatalog(),
00112 m_frontierConnect(),
00113 m_rfioType("castor"),
00114 m_connected(false),
00115 m_cacheTempDir(),
00116 m_cacheTempDirPtr(nullptr),
00117 m_cacheMinFree(),
00118 m_cacheMinFreePtr(nullptr),
00119 m_cacheHint(),
00120 m_cacheHintPtr(nullptr),
00121 m_readHint(),
00122 m_readHintPtr(nullptr),
00123 m_ttreeCacheSize(0U),
00124 m_ttreeCacheSizePtr(nullptr),
00125 m_timeout(0U),
00126 m_timeoutPtr(nullptr),
00127 m_debugLevel(0U),
00128 m_enablePrefetching(false),
00129 m_enablePrefetchingPtr(nullptr),
00130 m_nativeProtocols(),
00131 m_nativeProtocolsPtr(nullptr),
00132 m_statisticsDestination(),
00133 m_statisticsAddrInfo(nullptr),
00134 m_siteName() {
00135
00136 char* tmp = getenv("CMS_PATH");
00137
00138 if (tmp) {
00139 m_url = tmp + m_url;
00140 }
00141
00142 this->parse(m_url);
00143
00144
00145 overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
00146 overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
00147 overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
00148 overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
00149 overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
00150 overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
00151 overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
00152 overrideFromPSet("overridePrefetching", pset, m_enablePrefetching, m_enablePrefetchingPtr);
00153 const std::string * tmpStringPtr = NULL;
00154 overrideFromPSet("overrideStatisticsDestination", pset, m_statisticsDestination, tmpStringPtr);
00155 this->computeStatisticsDestination();
00156
00157 if(pset.exists("debugLevel")) {
00158 m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel");
00159 }
00160
00161 }
00162
00163 SiteLocalConfigService::~SiteLocalConfigService() {
00164 if (m_statisticsAddrInfo) {
00165 freeaddrinfo(m_statisticsAddrInfo);
00166 m_statisticsAddrInfo = nullptr;
00167 }
00168 }
00169
00170 std::string const
00171 SiteLocalConfigService::dataCatalog(void) const {
00172 if (!m_connected) {
00173
00174
00175
00176 return "file:PoolFileCatalog.xml";
00177 }
00178
00179 if (m_dataCatalog == "") {
00180 throw cms::Exception("Incomplete configuration")
00181 << "Did not find catalog in event-data section in " << m_url;
00182 }
00183
00184 return m_dataCatalog;
00185 }
00186
00187 std::string const
00188 SiteLocalConfigService::fallbackDataCatalog(void) const {
00189 if (!m_connected) {
00190
00191
00192
00193 return "file:PoolFileCatalog.xml";
00194 }
00195
00196
00197 return m_fallbackDataCatalog;
00198 }
00199
00200 std::string const
00201 SiteLocalConfigService::frontierConnect(std::string const& servlet) const {
00202 if (!m_connected) {
00203 throw cms::Exception("Incomplete configuration")
00204 << "Valid site-local-config not found at " << m_url;
00205 }
00206
00207 if (m_frontierConnect == "") {
00208 throw cms::Exception("Incomplete configuration")
00209 << "Did not find frontier-connect in calib-data section in " << m_url;
00210 }
00211
00212 if (servlet == "") {
00213 return m_frontierConnect;
00214 }
00215
00216
00217
00218 std::string::size_type nextparen = 0;
00219 std::string::size_type serverurl, lastslash;
00220 std::string complexstr = "";
00221 while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
00222 complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
00223 nextparen = m_frontierConnect.find(')', serverurl);
00224 lastslash = m_frontierConnect.rfind('/', nextparen);
00225 complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
00226 complexstr.append(servlet);
00227 }
00228 complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length()-nextparen);
00229
00230 return complexstr;
00231 }
00232
00233 std::string const
00234 SiteLocalConfigService::lookupCalibConnect(std::string const& input) const {
00235 static std::string const proto = "frontier://";
00236
00237 if (input.substr(0,proto.length()) == proto) {
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 std::string::size_type startservlet = proto.length();
00253
00254 std::string::size_type endservlet = input.find("(", startservlet);
00255 if (endservlet == std::string::npos) {
00256 endservlet = input.rfind('/', input.length());
00257 }
00258 std::string servlet = input.substr(startservlet, endservlet - startservlet);
00259 if ((servlet != "") && (servlet.find_first_of(":/)[]") == std::string::npos)) {
00260 if (servlet == "cms_conditions_data") {
00261
00262 servlet = "";
00263 }
00264 return proto + frontierConnect(servlet) + input.substr(endservlet);
00265 }
00266 }
00267 return input;
00268 }
00269
00270 std::string const
00271 SiteLocalConfigService::rfioType(void) const {
00272 return m_rfioType;
00273 }
00274
00275 std::string const*
00276 SiteLocalConfigService::sourceCacheTempDir() const {
00277 return m_cacheTempDirPtr;
00278 }
00279
00280 double const*
00281 SiteLocalConfigService::sourceCacheMinFree() const {
00282 return m_cacheMinFreePtr;
00283 }
00284
00285 std::string const*
00286 SiteLocalConfigService::sourceCacheHint() const {
00287 return m_cacheHintPtr;
00288 }
00289
00290 std::string const*
00291 SiteLocalConfigService::sourceReadHint() const {
00292 return m_readHintPtr;
00293 }
00294
00295 unsigned int const*
00296 SiteLocalConfigService::sourceTTreeCacheSize() const {
00297 return m_ttreeCacheSizePtr;
00298 }
00299
00300 unsigned int const*
00301 SiteLocalConfigService::sourceTimeout() const {
00302 return m_timeoutPtr;
00303 }
00304
00305 bool
00306 SiteLocalConfigService::enablePrefetching() const {
00307 return m_enablePrefetchingPtr ? *m_enablePrefetchingPtr : false;
00308 }
00309
00310 unsigned int
00311 SiteLocalConfigService::debugLevel() const {
00312 return m_debugLevel;
00313 }
00314
00315 std::vector<std::string> const*
00316 SiteLocalConfigService::sourceNativeProtocols() const {
00317 return m_nativeProtocolsPtr;
00318 }
00319
00320 struct addrinfo const*
00321 SiteLocalConfigService::statisticsDestination() const {
00322 return m_statisticsAddrInfo;
00323 }
00324
00325 std::string const&
00326 SiteLocalConfigService::siteName() const {
00327 return m_siteName;
00328 }
00329
00330 void
00331 SiteLocalConfigService::parse(std::string const& url) {
00332 XMLPlatformUtils::Initialize();
00333 std::auto_ptr<XercesDOMParser> parser(new XercesDOMParser);
00334 try {
00335 parser->setValidationScheme(XercesDOMParser::Val_Auto);
00336 parser->setDoNamespaces(false);
00337
00338 parser->parse(url.c_str());
00339 DOMDocument* doc = parser->getDocument();
00340 if (!doc) {
00341 return;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 DOMNodeList *sites = doc->getElementsByTagName(_toDOMS("site"));
00373 unsigned int numSites = sites->getLength();
00374 for (unsigned int i = 0; i < numSites; ++i) {
00375 DOMElement *site = static_cast<DOMElement *>(sites->item(i));
00376
00377
00378 m_siteName = _toString(site->getAttribute(_toDOMS("name")));
00379
00380
00381 {
00382 DOMNodeList *eventDataList = site->getElementsByTagName(_toDOMS("event-data"));
00383 if (eventDataList->getLength() > 0) {
00384 DOMElement *eventData = static_cast<DOMElement *>(eventDataList->item(0));
00385
00386 DOMNodeList *catalogs = eventData->getElementsByTagName(_toDOMS("catalog"));
00387
00388 if (catalogs->getLength() > 0) {
00389 DOMElement * catalog = static_cast<DOMElement *>(catalogs->item(0));
00390 m_dataCatalog = _toString(catalog->getAttribute(_toDOMS("url")));
00391 }
00392
00393 if (catalogs->getLength() > 1) {
00394 DOMElement * catalog = static_cast<DOMElement *>(catalogs->item(1));
00395 m_fallbackDataCatalog = _toString(catalog->getAttribute(_toDOMS("url")));
00396 }
00397
00398 DOMNodeList* rfiotypes = eventData->getElementsByTagName(_toDOMS("rfiotype"));
00399
00400 if (rfiotypes->getLength() > 0) {
00401 DOMElement* rfiotype = static_cast<DOMElement *>(rfiotypes->item(0));
00402 m_rfioType = _toString(rfiotype->getAttribute(_toDOMS("value")));
00403 }
00404 }
00405 }
00406
00407
00408 {
00409 DOMNodeList *calibDataList = site->getElementsByTagName(_toDOMS("calib-data"));
00410
00411 if (calibDataList->getLength() > 0) {
00412 DOMElement *calibData = static_cast<DOMElement *>(calibDataList->item(0));
00413 DOMNodeList *frontierConnectList = calibData->getElementsByTagName(_toDOMS("frontier-connect"));
00414
00415 if (frontierConnectList->getLength() > 0) {
00416 DOMElement *frontierConnect = static_cast<DOMElement *>(frontierConnectList->item(0));
00417 m_frontierConnect = _toParenString(*frontierConnect);
00418 }
00419 }
00420 }
00421
00422 {
00423 DOMNodeList *sourceConfigList = site->getElementsByTagName(_toDOMS("source-config"));
00424
00425 if (sourceConfigList->getLength() > 0) {
00426 DOMElement *sourceConfig = static_cast<DOMElement *>(sourceConfigList->item(0));
00427 DOMNodeList *cacheTempDirList = sourceConfig->getElementsByTagName(_toDOMS("cache-temp-dir"));
00428
00429 if (cacheTempDirList->getLength() > 0) {
00430 DOMElement *cacheTempDir = static_cast<DOMElement *>(cacheTempDirList->item(0));
00431 m_cacheTempDir = _toString(cacheTempDir->getAttribute(_toDOMS("name")));
00432 m_cacheTempDirPtr = &m_cacheTempDir;
00433 }
00434
00435 DOMNodeList *cacheMinFreeList = sourceConfig->getElementsByTagName(_toDOMS("cache-min-free"));
00436
00437 if (cacheMinFreeList->getLength() > 0) {
00438 DOMElement *cacheMinFree = static_cast<DOMElement *>(cacheMinFreeList->item(0));
00439 m_cacheMinFree = _toDouble(cacheMinFree->getAttribute(_toDOMS("value")));
00440 m_cacheMinFreePtr = &m_cacheMinFree;
00441 }
00442
00443 DOMNodeList *cacheHintList = sourceConfig->getElementsByTagName(_toDOMS("cache-hint"));
00444
00445 if (cacheHintList->getLength() > 0) {
00446 DOMElement *cacheHint = static_cast<DOMElement *>(cacheHintList->item(0));
00447 m_cacheHint = _toString(cacheHint->getAttribute(_toDOMS("value")));
00448 m_cacheHintPtr = &m_cacheHint;
00449 }
00450
00451 DOMNodeList *readHintList = sourceConfig->getElementsByTagName(_toDOMS("read-hint"));
00452
00453 if (readHintList->getLength() > 0) {
00454 DOMElement *readHint = static_cast<DOMElement *>(readHintList->item(0));
00455 m_readHint = _toString(readHint->getAttribute(_toDOMS("value")));
00456 m_readHintPtr = &m_readHint;
00457 }
00458
00459 DOMNodeList *ttreeCacheSizeList = sourceConfig->getElementsByTagName(_toDOMS("ttree-cache-size"));
00460
00461 if (ttreeCacheSizeList->getLength() > 0) {
00462 DOMElement *ttreeCacheSize = static_cast<DOMElement *>(ttreeCacheSizeList->item(0));
00463 m_ttreeCacheSize = _toUInt(ttreeCacheSize->getAttribute(_toDOMS("value")));
00464 m_ttreeCacheSizePtr = &m_ttreeCacheSize;
00465 }
00466
00467 DOMNodeList *timeoutList = sourceConfig->getElementsByTagName(_toDOMS("timeout-in-seconds"));
00468
00469 if (timeoutList->getLength() > 0) {
00470 DOMElement *timeout = static_cast<DOMElement *>(timeoutList->item(0));
00471 m_timeout = _toUInt(timeout->getAttribute(_toDOMS("value")));
00472 m_timeoutPtr = &m_timeout;
00473 }
00474
00475 DOMNodeList *statsDestList = sourceConfig->getElementsByTagName(_toDOMS("statistics-destination"));
00476
00477 if (statsDestList->getLength() > 0) {
00478 DOMElement *statsDest = static_cast<DOMElement *>(statsDestList->item(0));
00479 m_statisticsDestination = _toString(statsDest->getAttribute(_toDOMS("name")));
00480 }
00481
00482 DOMNodeList *prefetchingList = sourceConfig->getElementsByTagName(_toDOMS("prefetching"));
00483
00484 if (prefetchingList->getLength() > 0) {
00485 DOMElement *prefetching = static_cast<DOMElement *>(prefetchingList->item(0));
00486 m_enablePrefetching = _toBool(prefetching->getAttribute(_toDOMS("value")));
00487 m_enablePrefetchingPtr = &m_enablePrefetching;
00488 }
00489
00490 DOMNodeList *nativeProtocolsList = sourceConfig->getElementsByTagName(_toDOMS("native-protocols"));
00491
00492 if (nativeProtocolsList->getLength() > 0) {
00493 DOMElement *nativeProtocol = static_cast<DOMElement *>(nativeProtocolsList->item(0));
00494 DOMNodeList *childList = nativeProtocol->getChildNodes();
00495
00496 XMLCh* prefixXMLCh = _toDOMS("prefix");
00497 unsigned int numNodes = childList->getLength();
00498 for (unsigned int i = 0; i < numNodes; ++i) {
00499 DOMNode *childNode = childList->item(i);
00500 if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
00501 continue;
00502 }
00503 DOMElement *child = static_cast<DOMElement *>(childNode);
00504 m_nativeProtocols.push_back(_toString(child->getAttribute(prefixXMLCh)));
00505 }
00506 m_nativeProtocolsPtr = &m_nativeProtocols;
00507 }
00508 }
00509 }
00510 }
00511 m_connected = true;
00512 }
00513 catch (xercesc::DOMException const& e) {
00514 }
00515 }
00516
00517 void
00518 SiteLocalConfigService::computeStatisticsDestination() {
00519 std::vector<std::string> inputStrings;
00520 boost::split(inputStrings, m_statisticsDestination, boost::is_any_of(":"));
00521 const std::string &host=inputStrings[0];
00522 const std::string &port = (inputStrings.size() > 1) ? inputStrings[1] : m_statisticsDefaultPort;
00523 struct addrinfo *res;
00524 struct addrinfo hints;
00525 memset(&hints, '\0', sizeof(hints));
00526 hints.ai_socktype = SOCK_DGRAM;
00527 hints.ai_flags = AI_ADDRCONFIG;
00528 hints.ai_family = AF_UNSPEC;
00529 int e = getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
00530 if (e != 0) {
00531
00532 return;
00533 }
00534 m_statisticsAddrInfo = res;
00535 }
00536
00537 void
00538 SiteLocalConfigService::fillDescriptions(ConfigurationDescriptions& descriptions) {
00539 ParameterSetDescription desc;
00540 desc.setComment("Service to translate logical file names to physical file names.");
00541
00542 desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
00543 desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
00544 desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
00545 desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
00546 desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
00547 desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
00548 desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
00549 desc.addOptionalUntracked<unsigned int>("debugLevel");
00550 desc.addOptionalUntracked<bool>("overridePrefetching")
00551 ->setComment("Request ROOT to asynchronously prefetch I/O during computation.");
00552 desc.addOptionalUntracked<std::string>("overrideStatisticsDestination")
00553 ->setComment("Provide an alternate network destination for I/O statistics (must be in the form of host:port).");
00554
00555 descriptions.add("SiteLocalConfigService", desc);
00556 }
00557 }
00558 }