CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/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_debugLevel(0U),
00117           m_nativeProtocols(),
00118           m_nativeProtocolsPtr(0) {
00119 
00120         char* tmp = getenv("CMS_PATH");
00121 
00122         if (tmp) {
00123           m_url = tmp + m_url;
00124         }
00125 
00126         this->parse(m_url);
00127 
00128         //apply overrides
00129         overrideFromPSet("overrideSourceCacheTempDir", pset, m_cacheTempDir, m_cacheTempDirPtr);
00130         overrideFromPSet("overrideSourceCacheMinFree", pset, m_cacheMinFree, m_cacheMinFreePtr);
00131         overrideFromPSet("overrideSourceCacheHintDir", pset, m_cacheHint, m_cacheHintPtr);
00132         overrideFromPSet("overrideSourceReadHint", pset, m_readHint, m_readHintPtr);
00133         overrideFromPSet("overrideSourceNativeProtocols", pset, m_nativeProtocols, m_nativeProtocolsPtr);
00134         overrideFromPSet("overrideSourceTTreeCacheSize", pset, m_ttreeCacheSize, m_ttreeCacheSizePtr);
00135         overrideFromPSet("overrideSourceTimeout", pset, m_timeout, m_timeoutPtr);
00136 
00137        if(pset.exists("debugLevel")) {
00138             m_debugLevel = pset.getUntrackedParameter<unsigned int>("debugLevel");
00139        }
00140 
00141     }
00142 
00143     std::string const
00144     SiteLocalConfigService::dataCatalog(void) const {
00145         if (!m_connected) {
00146             //throw cms::Exception("Incomplete configuration")
00147             //    << "Valid site-local-config not found at " << m_url;
00148             // Return PoolFileCatalog.xml for now
00149             return "file:PoolFileCatalog.xml";
00150         }
00151 
00152         if (m_dataCatalog == "") {
00153           throw cms::Exception("Incomplete configuration")
00154             << "Did not find catalog in event-data section in " << m_url;
00155         }
00156 
00157         return m_dataCatalog;
00158     }
00159 
00160     std::string const
00161     SiteLocalConfigService::fallbackDataCatalog(void) const {
00162         if (!m_connected) {
00163             //throw cms::Exception("Incomplete configuration")
00164             //    << "Valid site-local-config not found at " << m_url;
00165             // Return PoolFileCatalog.xml for now
00166             return "file:PoolFileCatalog.xml";
00167         }
00168 
00169         // Note: Unlike the dataCatalog, the fallbackDataCatalog may be empty!
00170         return  m_fallbackDataCatalog;
00171     }
00172 
00173     std::string const
00174     SiteLocalConfigService::frontierConnect(std::string const& servlet) const {
00175         if (!m_connected) {
00176           throw cms::Exception("Incomplete configuration")
00177             << "Valid site-local-config not found at " << m_url;
00178         }
00179 
00180         if (m_frontierConnect == "") {
00181           throw cms::Exception("Incomplete configuration")
00182             << "Did not find frontier-connect in calib-data section in " << m_url;
00183         }
00184 
00185         if (servlet == "") {
00186           return m_frontierConnect;
00187         }
00188 
00189         // Replace the last component of every "serverurl=" piece (up to the
00190         //   next close-paren) with the servlet
00191         std::string::size_type nextparen = 0;
00192         std::string::size_type serverurl, lastslash;
00193         std::string complexstr = "";
00194         while ((serverurl = m_frontierConnect.find("(serverurl=", nextparen)) != std::string::npos) {
00195           complexstr.append(m_frontierConnect, nextparen, serverurl - nextparen);
00196           nextparen = m_frontierConnect.find(')', serverurl);
00197           lastslash = m_frontierConnect.rfind('/', nextparen);
00198           complexstr.append(m_frontierConnect, serverurl, lastslash - serverurl + 1);
00199           complexstr.append(servlet);
00200         }
00201         complexstr.append(m_frontierConnect, nextparen, m_frontierConnect.length()-nextparen);
00202 
00203         return complexstr;
00204     }
00205 
00206     std::string const
00207     SiteLocalConfigService::lookupCalibConnect(std::string const& input) const {
00208         static std::string const proto = "frontier://";
00209 
00210         if (input.substr(0,proto.length()) == proto) {
00211           // Replace the part after the frontier:// and before either an open-
00212           //  parentheses (which indicates user-supplied options) or the last
00213           //  slash (which indicates start of the schema) with the complex
00214           //  parenthesized string returned from frontierConnect() (which
00215           //  contains all the information needed to connect to frontier),
00216           //  if that part is a simple servlet name (non-empty and not
00217           //  containing special characters)
00218           // Example connect strings where servlet is replaced:
00219           //  frontier://cms_conditions_data/CMS_COND_ECAL
00220           //  frontier://FrontierInt/CMS_COND_ECAL
00221           //  frontier://FrontierInt(retrieve-ziplevel=0)/CMS_COND_ECAL
00222           // Example connect strings left untouched:
00223           //  frontier://cmsfrontier.cern.ch:8000/FrontierInt/CMS_COND_ECAL
00224           //  frontier://(serverurl=cmsfrontier.cern.ch:8000/FrontierInt)/CMS_COND_ECAL
00225           std::string::size_type startservlet = proto.length();
00226           // if user supplied extra parenthesized options, stop servlet there
00227           std::string::size_type endservlet = input.find("(", startservlet);
00228           if (endservlet == std::string::npos) {
00229               endservlet = input.rfind('/', input.length());
00230           }
00231           std::string servlet = input.substr(startservlet, endservlet - startservlet);
00232           if ((servlet != "") && (servlet.find_first_of(":/)[]") == std::string::npos)) {
00233               if (servlet == "cms_conditions_data") {
00234                 // use the default servlet from site-local-config.xml
00235                 servlet = "";
00236               }
00237               return proto + frontierConnect(servlet) + input.substr(endservlet);
00238           }
00239         }
00240         return input;
00241     }
00242 
00243     std::string const
00244     SiteLocalConfigService::rfioType(void) const {
00245         return m_rfioType;
00246     }
00247 
00248     std::string const*
00249     SiteLocalConfigService::sourceCacheTempDir() const {
00250        return m_cacheTempDirPtr;
00251     }
00252 
00253     double const*
00254     SiteLocalConfigService::sourceCacheMinFree() const {
00255        return m_cacheMinFreePtr;
00256     }
00257 
00258     std::string const*
00259     SiteLocalConfigService::sourceCacheHint() const {
00260        return m_cacheHintPtr;
00261     }
00262 
00263     std::string const*
00264     SiteLocalConfigService::sourceReadHint() const {
00265        return m_readHintPtr;
00266     }
00267 
00268     unsigned int const*
00269     SiteLocalConfigService::sourceTTreeCacheSize() const {
00270        return m_ttreeCacheSizePtr;
00271     }
00272 
00273     unsigned int const*
00274     SiteLocalConfigService::sourceTimeout() const {
00275        return m_timeoutPtr;
00276     }
00277 
00278     unsigned int
00279     SiteLocalConfigService::debugLevel() const {
00280        return m_debugLevel;
00281     }
00282 
00283     std::vector<std::string> const*
00284     SiteLocalConfigService::sourceNativeProtocols() const {
00285        return m_nativeProtocolsPtr;
00286     }
00287 
00288     void
00289     SiteLocalConfigService::parse(std::string const& url) {
00290       XMLPlatformUtils::Initialize();
00291       std::auto_ptr<XercesDOMParser> parser(new XercesDOMParser);
00292       try {
00293         parser->setValidationScheme(XercesDOMParser::Val_Auto);
00294         parser->setDoNamespaces(false);
00295 
00296         parser->parse(url.c_str());
00297         DOMDocument* doc = parser->getDocument();
00298         if (!doc) {
00299           return;
00300         }
00301 
00302         // The Site Config has the following format
00303         // <site-local-config>
00304         // <site name="FNAL">
00305         //   <event-data>
00306         //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
00307         //     <rfiotype value="castor"/>
00308         //   </event-data>
00309         //   <calib-data>
00310         //     <catalog url="trivialcatalog_file:/x/y/z.xml"/>
00311         //     <frontier-connect>
00312         //       ... frontier-interpreted server/proxy xml ...
00313             //     </frontier-connect>
00314         //   </calib-data>
00315             //   <source-config>
00316             //     <cache-temp-dir name="/a/b/c"/>
00317             //     <cache-hint value="..."/>
00318             //     <read-hint value="..."/>
00319             //     <ttree-cache-size value="0"/>
00320             //     <native-protocols>
00321             //        <protocol  prefix="dcache"/>
00322             //        <protocol prefix="file"/>
00323             //     </native-protocols>
00324             //   </source-config>
00325         // </site>
00326         // </site-local-config>
00327 
00328         // FIXME: should probably use the parser for validating the XML.
00329 
00330         DOMNodeList *sites = doc->getElementsByTagName(_toDOMS("site"));
00331         unsigned int numSites = sites->getLength();
00332         for (unsigned int i = 0; i < numSites; ++i) {
00333           DOMElement *site = static_cast<DOMElement *>(sites->item(i));
00334 
00335           // Parsing of the event data section
00336           {
00337             DOMNodeList *eventDataList = site->getElementsByTagName(_toDOMS("event-data"));
00338             if (eventDataList->getLength() > 0) {
00339               DOMElement *eventData = static_cast<DOMElement *>(eventDataList->item(0));
00340 
00341               DOMNodeList *catalogs = eventData->getElementsByTagName(_toDOMS("catalog"));
00342 
00343               if (catalogs->getLength() > 0) {
00344                 DOMElement * catalog = static_cast<DOMElement *>(catalogs->item(0));
00345                 m_dataCatalog = _toString(catalog->getAttribute(_toDOMS("url")));
00346               }
00347 
00348               if (catalogs->getLength() > 1) {
00349                 DOMElement * catalog = static_cast<DOMElement *>(catalogs->item(1));
00350                 m_fallbackDataCatalog = _toString(catalog->getAttribute(_toDOMS("url")));
00351               }
00352 
00353               DOMNodeList* rfiotypes = eventData->getElementsByTagName(_toDOMS("rfiotype"));
00354 
00355               if (rfiotypes->getLength() > 0) {
00356                 DOMElement* rfiotype = static_cast<DOMElement *>(rfiotypes->item(0));
00357                 m_rfioType = _toString(rfiotype->getAttribute(_toDOMS("value")));
00358               }
00359             }
00360           }
00361 
00362           // Parsing of the calib-data section
00363           {
00364             DOMNodeList *calibDataList = site->getElementsByTagName(_toDOMS("calib-data"));
00365 
00366             if (calibDataList->getLength() > 0) {
00367               DOMElement *calibData = static_cast<DOMElement *>(calibDataList->item(0));
00368               DOMNodeList *frontierConnectList = calibData->getElementsByTagName(_toDOMS("frontier-connect"));
00369 
00370               if (frontierConnectList->getLength() > 0) {
00371                 DOMElement *frontierConnect = static_cast<DOMElement *>(frontierConnectList->item(0));
00372                 m_frontierConnect = _toParenString(*frontierConnect);
00373               }
00374             }
00375           }
00376           // Parsing of the source config section
00377           {
00378             DOMNodeList *sourceConfigList = site->getElementsByTagName(_toDOMS("source-config"));
00379 
00380             if (sourceConfigList->getLength() > 0) {
00381               DOMElement *sourceConfig = static_cast<DOMElement *>(sourceConfigList->item(0));
00382               DOMNodeList *cacheTempDirList = sourceConfig->getElementsByTagName(_toDOMS("cache-temp-dir"));
00383 
00384               if (cacheTempDirList->getLength() > 0) {
00385                 DOMElement *cacheTempDir = static_cast<DOMElement *>(cacheTempDirList->item(0));
00386                 m_cacheTempDir = _toString(cacheTempDir->getAttribute(_toDOMS("name")));
00387                 m_cacheTempDirPtr = &m_cacheTempDir;
00388               }
00389 
00390               DOMNodeList *cacheMinFreeList = sourceConfig->getElementsByTagName(_toDOMS("cache-min-free"));
00391 
00392               if (cacheMinFreeList->getLength() > 0) {
00393                 DOMElement *cacheMinFree = static_cast<DOMElement *>(cacheMinFreeList->item(0));
00394                 m_cacheMinFree = _toDouble(cacheMinFree->getAttribute(_toDOMS("value")));
00395                 m_cacheMinFreePtr = &m_cacheMinFree;
00396               }
00397 
00398               DOMNodeList *cacheHintList = sourceConfig->getElementsByTagName(_toDOMS("cache-hint"));
00399 
00400               if (cacheHintList->getLength() > 0) {
00401                 DOMElement *cacheHint = static_cast<DOMElement *>(cacheHintList->item(0));
00402                 m_cacheHint = _toString(cacheHint->getAttribute(_toDOMS("value")));
00403                 m_cacheHintPtr = &m_cacheHint;
00404               }
00405 
00406               DOMNodeList *readHintList = sourceConfig->getElementsByTagName(_toDOMS("read-hint"));
00407 
00408               if (readHintList->getLength() > 0) {
00409                 DOMElement *readHint = static_cast<DOMElement *>(readHintList->item(0));
00410                 m_readHint = _toString(readHint->getAttribute(_toDOMS("value")));
00411                 m_readHintPtr = &m_readHint;
00412               }
00413 
00414               DOMNodeList *ttreeCacheSizeList = sourceConfig->getElementsByTagName(_toDOMS("ttree-cache-size"));
00415 
00416               if (ttreeCacheSizeList->getLength() > 0) {
00417                 DOMElement *ttreeCacheSize = static_cast<DOMElement *>(ttreeCacheSizeList->item(0));
00418                 m_ttreeCacheSize = _toUInt(ttreeCacheSize->getAttribute(_toDOMS("value")));
00419                 m_ttreeCacheSizePtr = &m_ttreeCacheSize;
00420               }
00421 
00422               DOMNodeList *timeoutList = sourceConfig->getElementsByTagName(_toDOMS("timeout-in-seconds"));
00423 
00424               if (timeoutList->getLength() > 0) {
00425                 DOMElement *timeout = static_cast<DOMElement *>(timeoutList->item(0));
00426                 m_timeout = _toUInt(timeout->getAttribute(_toDOMS("value")));
00427                 m_timeoutPtr = &m_timeout;
00428               }
00429 
00430               DOMNodeList *nativeProtocolsList = sourceConfig->getElementsByTagName(_toDOMS("native-protocols"));
00431 
00432               if (nativeProtocolsList->getLength() > 0) {
00433                 DOMElement *nativeProtocol = static_cast<DOMElement *>(nativeProtocolsList->item(0));
00434                 DOMNodeList *childList = nativeProtocol->getChildNodes();
00435 
00436                 XMLCh* prefixXMLCh = _toDOMS("prefix");
00437                 unsigned int numNodes = childList->getLength();
00438                 for (unsigned int i = 0; i < numNodes; ++i) {
00439                   DOMNode *childNode = childList->item(i);
00440                   if (childNode->getNodeType() != DOMNode::ELEMENT_NODE) {
00441                     continue;
00442                   }
00443                   DOMElement *child = static_cast<DOMElement *>(childNode);
00444                   m_nativeProtocols.push_back(_toString(child->getAttribute(prefixXMLCh)));
00445                 }
00446                 m_nativeProtocolsPtr = &m_nativeProtocols;
00447               }
00448             }
00449           }
00450         }
00451         m_connected = true;
00452       }
00453       catch (xercesc::DOMException const& e) {
00454       }
00455     }
00456 
00457     void
00458     SiteLocalConfigService::fillDescriptions(ConfigurationDescriptions& descriptions) {
00459       ParameterSetDescription desc;
00460       desc.setComment("Service to translate logical file names to physical file names.");
00461 
00462       desc.addOptionalUntracked<std::string>("overrideSourceCacheTempDir");
00463       desc.addOptionalUntracked<double>("overrideSourceCacheMinFree");
00464       desc.addOptionalUntracked<std::string>("overrideSourceCacheHintDir");
00465       desc.addOptionalUntracked<std::string>("overrideSourceReadHint");
00466       desc.addOptionalUntracked<std::vector<std::string> >("overrideSourceNativeProtocols");
00467       desc.addOptionalUntracked<unsigned int>("overrideSourceTTreeCacheSize");
00468       desc.addOptionalUntracked<unsigned int>("overrideSourceTimeout");
00469       desc.addOptionalUntracked<unsigned int>("debugLevel");
00470 
00471       descriptions.add("SiteLocalConfigService", desc);
00472     }
00473   }
00474 }