CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/FWCore/Services/src/SiteLocalConfigService.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
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 
00015 using namespace xercesc;
00016 
00017 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00018 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00019 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00020 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00021 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00022 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00023 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00024 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00025 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00026 
00027 namespace {
00028   inline std::string _toString(XMLCh const* toTranscode) {
00029       std::string tmp(XMLString::transcode(toTranscode));
00030       return tmp;
00031   }
00032 
00033   inline unsigned int _toUInt(XMLCh const* toTranscode) {
00034      std::istringstream iss(_toString(toTranscode));
00035      unsigned int returnValue;
00036      iss >> returnValue;
00037      return returnValue;
00038   }
00039 
00040   inline double _toDouble(XMLCh const* toTranscode) {
00041      std::istringstream iss(_toString(toTranscode));
00042      double returnValue;
00043      iss >> returnValue;
00044      return returnValue;
00045   }
00046 
00047   inline XMLCh*  _toDOMS(std::string temp) {
00048       XMLCh* buff = XMLString::transcode(temp.c_str());
00049       return  buff;
00050   }
00051 
00052   // concatenate all the XML node attribute/value pairs into a
00053   // paren-separated string (for use by CORAL and frontier_client)
00054   inline std::string _toParenString(DOMNode const& nodeToConvert) {
00055       std::ostringstream oss;
00056 
00057       DOMNodeList *childList = nodeToConvert.getChildNodes();
00058 
00059       unsigned int numNodes = childList->getLength();
00060       for (unsigned int i = 0; i < numNodes; ++i) {
00061         DOMNode *childNode = childList->item(i);
00062         if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
00063             continue;
00064         }
00065         DOMElement *child = static_cast<DOMElement *>(childNode);
00066 
00067         DOMNamedNodeMap *attributes = child->getAttributes();
00068         unsigned int numAttributes = attributes->getLength();
00069         for (unsigned int j = 0; j < numAttributes; ++j) {
00070             DOMNode *attributeNode = attributes->item(j);
00071             if (attributeNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) {
00072               continue;
00073             }
00074             DOMAttr *attribute = static_cast<DOMAttr *>(attributeNode);
00075 
00076             oss << "(" << _toString(child->getTagName()) <<
00077                           _toString(attribute->getName()) << "=" <<
00078                           _toString(attribute->getValue()) << ")";
00079         }
00080       }
00081       return oss.str();
00082   }
00083 
00084   template<typename T>
00085   static
00086   void overrideFromPSet(char const* iName, edm::ParameterSet const& iPSet,
00087                         T& iHolder, T const*& iPointer) {
00088      if(iPSet.exists(iName)) {
00089         iHolder = iPSet.getUntrackedParameter<T>(iName);
00090         iPointer = &iHolder;
00091      }
00092   }
00093 }
00094 
00095 namespace edm {
00096   namespace service {
00097     SiteLocalConfigService::SiteLocalConfigService(ParameterSet const& pset) :
00098           m_url("/SITECONF/local/JobConfig/site-local-config.xml"),
00099           m_dataCatalog(),
00100           m_fallbackDataCatalog(),
00101           m_frontierConnect(),
00102           m_rfioType("castor"),
00103           m_connected(false),
00104           m_cacheTempDir(),
00105           m_cacheTempDirPtr(0),
00106           m_cacheMinFree(),
00107           m_cacheMinFreePtr(0),
00108           m_cacheHint(),
00109           m_cacheHintPtr(0),
00110           m_readHint(),
00111           m_readHintPtr(0),
00112           m_ttreeCacheSize(0U),
00113           m_ttreeCacheSizePtr(0),
00114           m_timeout(0U),
00115           m_timeoutPtr(0),
00116           m_nativeProtocols(),
00117           m_nativeProtocolsPtr(0) {
00118 
00119         char* tmp = getenv("CMS_PATH");
00120 
00121         if (tmp) {
00122           m_url = tmp + m_url;
00123         }
00124 
00125         this->parse(m_url);
00126 
00127         //apply overrides
00128         overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
00129         overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
00130         overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
00131         overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
00132         overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
00133         overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
00134         overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
00135 
00136     }
00137 
00138     std::string const
00139     SiteLocalConfigService::dataCatalog(void) const {
00140         if (!m_connected) {
00141             //throw cms::Exception("Incomplete configuration")
00142             //    << "Valid site-local-config not found at " << m_url;
00143             // Return PoolFileCatalog.xml for now
00144             return "file:PoolFileCatalog.xml";
00145         }
00146 
00147         if (m_dataCatalog == "") {
00148           throw cms::Exception("Incomplete configuration")
00149             << "Did not find catalog in event-data section in " << m_url;
00150         }
00151 
00152         return m_dataCatalog;
00153     }
00154 
00155     std::string const
00156     SiteLocalConfigService::fallbackDataCatalog(void) const {
00157         if (!m_connected) {
00158             //throw cms::Exception("Incomplete configuration")
00159             //    << "Valid site-local-config not found at " << m_url;
00160             // Return PoolFileCatalog.xml for now
00161             return "file:PoolFileCatalog.xml";
00162         }
00163 
00164         // Note: Unlike the dataCatalog, the fallbackDataCatalog may be empty!
00165         return  m_fallbackDataCatalog;
00166     }
00167 
00168     std::string const
00169     SiteLocalConfigService::frontierConnect(std::string const& servlet) const {
00170         if (!m_connected) {
00171           throw cms::Exception("Incomplete configuration")
00172             << "Valid site-local-config not found at " << m_url;
00173         }
00174 
00175         if (m_frontierConnect == "") {
00176           throw cms::Exception("Incomplete configuration")
00177             << "Did not find frontier-connect in calib-data section in " << m_url;
00178         }
00179 
00180         if (servlet == "") {
00181           return m_frontierConnect;
00182         }
00183 
00184         // Replace the last component of every "serverurl=" piece (up to the
00185         //   next close-paren) with the servlet
00186         std::string::size_type nextparen = 0;
00187         std::string::size_type serverurl, lastslash;
00188         std::string complexstr = "";
00189         while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
00190           complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
00191           nextparen = m_frontierConnect.find(')', serverurl);
00192           lastslash = m_frontierConnect.rfind('/', nextparen);
00193           complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
00194           complexstr.append(servlet);
00195         }
00196         complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length()-nextparen);
00197 
00198         return complexstr;
00199     }
00200 
00201     std::string const
00202     SiteLocalConfigService::lookupCalibConnect(std::string const& input) const {
00203         static std::string const proto = "frontier://";
00204 
00205         if (input.substr(0,proto.length()) == proto) {
00206           // Replace the part after the frontier:// and before either an open-
00207           //  parentheses (which indicates user-supplied options) or the last
00208           //  slash (which indicates start of the schema) with the complex
00209           //  parenthesized string returned from frontierConnect() (which
00210           //  contains all the information needed to connect to frontier),
00211           //  if that part is a simple servlet name (non-empty and not
00212           //  containing special characters)
00213           // Example connect strings where servlet is replaced:
00214           //  frontier://cms_conditions_data/CMS_COND_ECAL
00215           //  frontier://FrontierInt/CMS_COND_ECAL
00216           //  frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL
00217           // Example connect strings left untouched:
00218           //  frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL
00219           //  frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL
00220           std::string::size_type startservlet = proto.length();
00221           // if user supplied extra parenthesized options, stop servlet there
00222           std::string::size_type endservlet = input.find("(", startservlet);
00223           if (endservlet == std::string::npos) {
00224               endservlet = input.rfind('/', input.length());
00225           }
00226           std::string servlet = input.substr(startservlet, endservlet - startservlet);
00227           if ((servlet != "") && (servlet.find_first_of(":/)[]") == std::string::npos)) {
00228               if (servlet == "cms_conditions_data") {
00229                 // use the default servlet from site-local-config.xml
00230                 servlet = "";
00231               }
00232               return proto + frontierConnect(servlet) + input.substr(endservlet);
00233           }
00234         }
00235         return input;
00236     }
00237 
00238     std::string const
00239     SiteLocalConfigService::rfioType(void) const {
00240         return m_rfioType;
00241     }
00242 
00243     std::string const*
00244     SiteLocalConfigService::sourceCacheTempDir() const {
00245        return m_cacheTempDirPtr;
00246     }
00247 
00248     double const*
00249     SiteLocalConfigService::sourceCacheMinFree() const {
00250        return m_cacheMinFreePtr;
00251     }
00252 
00253     std::string const*
00254     SiteLocalConfigService::sourceCacheHint() const {
00255        return m_cacheHintPtr;
00256     }
00257 
00258     std::string const*
00259     SiteLocalConfigService::sourceReadHint() const {
00260        return m_readHintPtr;
00261     }
00262 
00263     unsigned int const*
00264     SiteLocalConfigService::sourceTTreeCacheSize() const {
00265        return m_ttreeCacheSizePtr;
00266     }
00267 
00268     unsigned int const*
00269     SiteLocalConfigService::sourceTimeout() const {
00270        return m_timeoutPtr;
00271     }
00272 
00273     std::vector<std::string> const*
00274     SiteLocalConfigService::sourceNativeProtocols() const {
00275        return m_nativeProtocolsPtr;
00276     }
00277 
00278     void
00279     SiteLocalConfigService::parse(std::string const& url) {
00280       XMLPlatformUtils::Initialize();
00281       std::auto_ptr<XercesDOMParser> parser(new XercesDOMParser);
00282       try {
00283         parser->setValidationScheme(XercesDOMParser::Val_Auto);
00284         parser->setDoNamespaces(false);
00285 
00286         parser->parse(url.c_str());
00287         DOMDocument* doc = parser->getDocument();
00288         if (!doc) {
00289           return;
00290         }
00291 
00292         // The Site Config has the following format
00293         // <site-local-config>
00294         // <site name="FNAL">
00295         //   <event-data>
00296         //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
00297         //     <rfiotype value="castor"/>
00298         //   </event-data>
00299         //   <calib-data>
00300         //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
00301         //     <frontier-connect>
00302         //       ... frontier-interpreted server/proxy xml ...
00303             //     </frontier-connect>
00304         //   </calib-data>
00305             //   <source-config>
00306             //     <cache-temp-dir name="/a/b/c"/>
00307             //     <cache-hint value="..."/>
00308             //     <read-hint value="..."/>
00309             //     <ttree-cache-size value="0"/>
00310             //     <native-protocols>
00311             //        <protocol  prefix="dcache"/>
00312             //        <protocol prefix="file"/>
00313             //     </native-protocols>
00314             //   </source-config>
00315         // </site>
00316         // </site-local-config>
00317 
00318         // FIXME: should probably use the parser for validating the XML.
00319 
00320         DOMNodeList *sites = doc->getElementsByTagName(_toDOMS("site"));
00321         unsigned int numSites = sites->getLength();
00322         for (unsigned int i = 0; i < numSites; ++i) {
00323           DOMElement *site = static_cast<DOMElement *>(sites->item(i));
00324 
00325           // Parsing of the event data section
00326           {
00327             DOMNodeList *eventDataList = site->getElementsByTagName(_toDOMS("event-data"));
00328             if (eventDataList->getLength() > 0) {
00329               DOMElement *eventData = static_cast<DOMElement *>(eventDataList->item(0));
00330 
00331               DOMNodeList *catalogs = eventData->getElementsByTagName(_toDOMS("catalog"));
00332 
00333               if (catalogs->getLength() > 0) {
00334                 DOMElement * catalog = static_cast<DOMElement *>(catalogs->item(0));
00335                 m_dataCatalog = _toString(catalog->getAttribute(_toDOMS("url")));
00336               }
00337 
00338               if (catalogs->getLength() > 1) {
00339                 DOMElement * catalog = static_cast<DOMElement *>(catalogs->item(1));
00340                 m_fallbackDataCatalog = _toString(catalog->getAttribute(_toDOMS("url")));
00341               }
00342 
00343               DOMNodeList* rfiotypes = eventData->getElementsByTagName(_toDOMS("rfiotype"));
00344 
00345               if (rfiotypes->getLength() > 0) {
00346                 DOMElement* rfiotype = static_cast<DOMElement *>(rfiotypes->item(0));
00347                 m_rfioType = _toString(rfiotype->getAttribute(_toDOMS("value")));
00348               }
00349             }
00350           }
00351 
00352           // Parsing of the calib-data section
00353           {
00354             DOMNodeList *calibDataList = site->getElementsByTagName(_toDOMS("calib-data"));
00355 
00356             if (calibDataList->getLength() > 0) {
00357               DOMElement *calibData = static_cast<DOMElement *>(calibDataList->item(0));
00358               DOMNodeList *frontierConnectList = calibData->getElementsByTagName(_toDOMS("frontier-connect"));
00359 
00360               if (frontierConnectList->getLength() > 0) {
00361                 DOMElement *frontierConnect = static_cast<DOMElement *>(frontierConnectList->item(0));
00362                 m_frontierConnect = _toParenString(*frontierConnect);
00363               }
00364             }
00365           }
00366           // Parsing of the source config section
00367           {
00368             DOMNodeList *sourceConfigList = site->getElementsByTagName(_toDOMS("source-config"));
00369 
00370             if (sourceConfigList->getLength() > 0) {
00371               DOMElement *sourceConfig = static_cast<DOMElement *>(sourceConfigList->item(0));
00372               DOMNodeList *cacheTempDirList = sourceConfig->getElementsByTagName(_toDOMS("cache-temp-dir"));
00373 
00374               if (cacheTempDirList->getLength() > 0) {
00375                 DOMElement *cacheTempDir = static_cast<DOMElement *>(cacheTempDirList->item(0));
00376                 m_cacheTempDir = _toString(cacheTempDir->getAttribute(_toDOMS("name")));
00377                 m_cacheTempDirPtr = &m_cacheTempDir;
00378               }
00379 
00380               DOMNodeList *cacheMinFreeList = sourceConfig->getElementsByTagName(_toDOMS("cache-min-free"));
00381 
00382               if (cacheMinFreeList->getLength() > 0) {
00383                 DOMElement *cacheMinFree = static_cast<DOMElement *>(cacheMinFreeList->item(0));
00384                 m_cacheMinFree = _toDouble(cacheMinFree->getAttribute(_toDOMS("value")));
00385                 m_cacheMinFreePtr = &m_cacheMinFree;
00386               }
00387 
00388               DOMNodeList *cacheHintList = sourceConfig->getElementsByTagName(_toDOMS("cache-hint"));
00389 
00390               if (cacheHintList->getLength() > 0) {
00391                 DOMElement *cacheHint = static_cast<DOMElement *>(cacheHintList->item(0));
00392                 m_cacheHint = _toString(cacheHint->getAttribute(_toDOMS("value")));
00393                 m_cacheHintPtr = &m_cacheHint;
00394               }
00395 
00396               DOMNodeList *readHintList = sourceConfig->getElementsByTagName(_toDOMS("read-hint"));
00397 
00398               if (readHintList->getLength() > 0) {
00399                 DOMElement *readHint = static_cast<DOMElement *>(readHintList->item(0));
00400                 m_readHint = _toString(readHint->getAttribute(_toDOMS("value")));
00401                 m_readHintPtr = &m_readHint;
00402               }
00403 
00404               DOMNodeList *ttreeCacheSizeList = sourceConfig->getElementsByTagName(_toDOMS("ttree-cache-size"));
00405 
00406               if (ttreeCacheSizeList->getLength() > 0) {
00407                 DOMElement *ttreeCacheSize = static_cast<DOMElement *>(ttreeCacheSizeList->item(0));
00408                 m_ttreeCacheSize = _toUInt(ttreeCacheSize->getAttribute(_toDOMS("value")));
00409                 m_ttreeCacheSizePtr = &m_ttreeCacheSize;
00410               }
00411 
00412               DOMNodeList *timeoutList = sourceConfig->getElementsByTagName(_toDOMS("timeout-in-seconds"));
00413 
00414               if (timeoutList->getLength() > 0) {
00415                 DOMElement *timeout = static_cast<DOMElement *>(timeoutList->item(0));
00416                 m_timeout = _toUInt(timeout->getAttribute(_toDOMS("value")));
00417                 m_timeoutPtr = &m_timeout;
00418               }
00419 
00420               DOMNodeList *nativeProtocolsList = sourceConfig->getElementsByTagName(_toDOMS("native-protocols"));
00421 
00422               if (nativeProtocolsList->getLength() > 0) {
00423                 DOMElement *nativeProtocol = static_cast<DOMElement *>(nativeProtocolsList->item(0));
00424                 DOMNodeList *childList = nativeProtocol->getChildNodes();
00425 
00426                 XMLCh* prefixXMLCh = _toDOMS("prefix");
00427                 unsigned int numNodes = childList->getLength();
00428                 for (unsigned int i = 0; i < numNodes; ++i) {
00429                   DOMNode *childNode = childList->item(i);
00430                   if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
00431                     continue;
00432                   }
00433                   DOMElement *child = static_cast<DOMElement *>(childNode);
00434                   m_nativeProtocols.push_back(_toString(child->getAttribute(prefixXMLCh)));
00435                 }
00436                 m_nativeProtocolsPtr = &m_nativeProtocols;
00437               }
00438             }
00439           }
00440         }
00441         m_connected = true;
00442       }
00443       catch (xercesc::DOMException const& e) {
00444       }
00445     }
00446 
00447     void
00448     SiteLocalConfigService::fillDescriptions(ConfigurationDescriptions& descriptions) {
00449       ParameterSetDescription desc;
00450       desc.setComment("Service to translate logical file names to physical file names.");
00451 
00452       desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
00453       desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
00454       desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
00455       desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
00456       desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
00457       desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
00458       desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
00459 
00460       descriptions.add("SiteLocalConfigService", desc);
00461     }
00462   }
00463 }