Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-01-16 23:25:22

0001 //
0002 // Package:     CondCore/ESSources
0003 // Module:      CondDBESSource
0004 //
0005 // Description: <one line class summary>
0006 //
0007 // Implementation:
0008 //     <Notes on implementation>
0009 //
0010 // Author:      Zhen Xie
0011 // Fixes and other changes: Giacomo Govi
0012 //
0013 #include "CondDBESSource.h"
0014 
0015 #include <boost/algorithm/string.hpp>
0016 #include "CondCore/CondDB/interface/Exception.h"
0017 #include "CondCore/CondDB/interface/Time.h"
0018 #include "CondCore/CondDB/interface/Types.h"
0019 #include "CondCore/CondDB/interface/Utils.h"
0020 
0021 #include "CondCore/ESSources/interface/ProxyFactory.h"
0022 #include "CondCore/ESSources/interface/DataProxy.h"
0023 
0024 #include "CondCore/CondDB/interface/PayloadProxy.h"
0025 #include "FWCore/Catalog/interface/SiteLocalConfig.h"
0026 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0027 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0028 #include "FWCore/ServiceRegistry/interface/Service.h"
0029 #include <exception>
0030 
0031 #include <iomanip>
0032 
0033 namespace {
0034   /* utility ot build the name of the plugin corresponding to a given record
0035      se ESSources
0036    */
0037   std::string buildName(std::string const& iRecordName) { return iRecordName + std::string("@NewProxy"); }
0038 
0039   std::string joinRecordAndLabel(std::string const& iRecordName, std::string const& iLabelName) {
0040     return iRecordName + std::string("@") + iLabelName;
0041   }
0042 
0043   /* utility class to return a IOVs associated to a given "name"
0044      This implementation return the IOV associated to a record...
0045      It is essentialy a workaround to get the full IOV out of the tag colector
0046      that is not accessible as hidden in the ESSource
0047      FIXME: need to support label??
0048    */
0049   class CondGetterFromESSource : public cond::persistency::CondGetter {
0050   public:
0051     CondGetterFromESSource(CondDBESSource::ProxyMap const& ip) : m_proxies(ip) {}
0052     ~CondGetterFromESSource() override {}
0053 
0054     cond::persistency::IOVProxy get(std::string name) const override {
0055       CondDBESSource::ProxyMap::const_iterator p = m_proxies.find(name);
0056       if (p != m_proxies.end())
0057         return (*p).second->iovProxy();
0058       return cond::persistency::IOVProxy();
0059     }
0060 
0061     CondDBESSource::ProxyMap const& m_proxies;
0062   };
0063 
0064   // This needs to be re-design and implemented...
0065   // dump the state of a DataProxy
0066   void dumpInfo(std::ostream& out, std::string const& recName, cond::DataProxyWrapperBase const& proxy) {
0067     //cond::SequenceState state(proxy.proxy()->iov().state());
0068     out << recName << " / " << proxy.label() << ": " << proxy.connString() << ", " << proxy.tag()
0069         << "\n  "
0070         //  << state.size() << ", " << state.revision()  << ", "
0071         //  << cond::time::to_boost(state.timestamp())     << "\n  "
0072         //  << state.comment()
0073         << "\n  "
0074         //  << "refresh " << proxy.proxy()->stats.nRefresh
0075         //  << "/" << proxy.proxy()->stats.nArefresh
0076         //  << ", reconnect " << proxy.proxy()->stats.nReconnect
0077         //  << "/" << proxy.proxy()->stats.nAreconnect
0078         //  << ", make " << proxy.proxy()->stats.nMake
0079         //  << ", load " << proxy.proxy()->stats.nLoad
0080         ;
0081     //if ( proxy.proxy()->stats.nLoad>0) {
0082     out << "Time look up, payloadIds:" << std::endl;
0083     const auto& pids = *proxy.requests();
0084     for (const auto& id : pids)
0085       out << "   " << id.since << " - " << id.till << " : " << id.payloadId << std::endl;
0086   }
0087 
0088 }  // namespace
0089 
0090 /*
0091  *  config Param
0092  *  RefreshEachRun: if true will refresh the IOV at each new run (or lumiSection)
0093  *  DumpStat: if true dump the statistics of all DataProxy (currently on cout)
0094  *  DBParameters: configuration set of the connection
0095  *  globaltag: The GlobalTag
0096  *  toGet: list of record label tag connection-string to add/overwrite the content of the global-tag
0097  */
0098 CondDBESSource::CondDBESSource(const edm::ParameterSet& iConfig)
0099     : m_connection(),
0100       m_connectionString(""),
0101       m_frontierKey(""),
0102       m_lastRun(0),   // for the stat
0103       m_lastLumi(0),  // for the stat
0104       m_policy(NOREFRESH),
0105       m_doDump(iConfig.getUntrackedParameter<bool>("DumpStat", false)) {
0106   if (iConfig.getUntrackedParameter<bool>("RefreshAlways", false)) {
0107     m_policy = REFRESH_ALWAYS;
0108   }
0109   if (iConfig.getUntrackedParameter<bool>("RefreshOpenIOVs", false)) {
0110     m_policy = REFRESH_OPEN_IOVS;
0111   }
0112   if (iConfig.getUntrackedParameter<bool>("RefreshEachRun", false)) {
0113     m_policy = REFRESH_EACH_RUN;
0114   }
0115   if (iConfig.getUntrackedParameter<bool>("ReconnectEachRun", false)) {
0116     m_policy = RECONNECT_EACH_RUN;
0117   }
0118 
0119   Stats s = {0, 0, 0, 0, 0, 0, 0, 0};
0120   m_stats = s;
0121 
0122   /*parameter set parsing
0123    */
0124   std::string globaltag("");
0125   if (iConfig.exists("globaltag")) {
0126     globaltag = iConfig.getParameter<std::string>("globaltag");
0127     // the global tag _requires_ a connection string
0128     m_connectionString = iConfig.getParameter<std::string>("connect");
0129 
0130     if (!globaltag.empty()) {
0131       edm::Service<edm::SiteLocalConfig> siteLocalConfig;
0132       if (siteLocalConfig.isAvailable()) {
0133         if (siteLocalConfig->useLocalConnectString()) {
0134           std::string const& localConnectPrefix = siteLocalConfig->localConnectPrefix();
0135           std::string const& localConnectSuffix = siteLocalConfig->localConnectSuffix();
0136           m_connectionString = localConnectPrefix + globaltag + localConnectSuffix;
0137         }
0138       }
0139     }
0140   } else if (iConfig.exists("connect"))  // default connection string
0141     m_connectionString = iConfig.getParameter<std::string>("connect");
0142 
0143   // frontier key
0144   m_frontierKey = iConfig.getUntrackedParameter<std::string>("frontierKey", "");
0145 
0146   // snapshot
0147   boost::posix_time::ptime snapshotTime;
0148   if (iConfig.exists("snapshotTime")) {
0149     std::string snapshotTimeString = iConfig.getParameter<std::string>("snapshotTime");
0150     if (!snapshotTimeString.empty())
0151       snapshotTime = boost::posix_time::time_from_string(snapshotTimeString);
0152   }
0153 
0154   // connection configuration
0155   if (iConfig.exists("DBParameters")) {
0156     edm::ParameterSet connectionPset = iConfig.getParameter<edm::ParameterSet>("DBParameters");
0157     m_connection.setParameters(connectionPset);
0158   }
0159   m_connection.configure();
0160 
0161   // load specific record/tag info - it will overwrite the global tag ( if any )
0162   std::map<std::string, cond::GTEntry_t> replacements;
0163   std::map<std::string, boost::posix_time::ptime> specialSnapshots;
0164   if (iConfig.exists("toGet")) {
0165     typedef std::vector<edm::ParameterSet> Parameters;
0166     Parameters toGet = iConfig.getParameter<Parameters>("toGet");
0167     for (Parameters::iterator itToGet = toGet.begin(); itToGet != toGet.end(); ++itToGet) {
0168       std::string recordname = itToGet->getParameter<std::string>("record");
0169       if (recordname.empty())
0170         throw cond::Exception("ESSource: The record name has not been provided in a \"toGet\" entry.");
0171       std::string labelname = itToGet->getUntrackedParameter<std::string>("label", "");
0172       std::string pfn("");
0173       if (m_connectionString.empty() || itToGet->exists("connect"))
0174         pfn = itToGet->getParameter<std::string>("connect");
0175       std::string tag("");
0176       std::string fqTag("");
0177       if (itToGet->exists("tag")) {
0178         tag = itToGet->getParameter<std::string>("tag");
0179         fqTag = cond::persistency::fullyQualifiedTag(tag, pfn);
0180       }
0181       boost::posix_time::ptime tagSnapshotTime =
0182           boost::posix_time::time_from_string(std::string(cond::time::MAX_TIMESTAMP));
0183       if (itToGet->exists("snapshotTime"))
0184         tagSnapshotTime = boost::posix_time::time_from_string(itToGet->getParameter<std::string>("snapshotTime"));
0185       if (itToGet->exists("refreshTime")) {
0186         cond::Time_t refreshTime = itToGet->getParameter<unsigned long long>("refreshTime");
0187         m_refreshTimeForRecord.insert(std::make_pair(recordname, std::make_pair(refreshTime, true)));
0188       }
0189 
0190       std::string recordLabelKey = joinRecordAndLabel(recordname, labelname);
0191       replacements.insert(
0192           std::make_pair(recordLabelKey, cond::GTEntry_t(std::make_tuple(recordname, labelname, fqTag))));
0193       specialSnapshots.insert(std::make_pair(recordLabelKey, tagSnapshotTime));
0194     }
0195   }
0196 
0197   // get the global tag, merge with "replacement" store in "tagCollection"
0198   std::vector<std::string> globaltagList;
0199   std::vector<std::string> connectList;
0200   std::vector<std::string> pfnPrefixList;
0201   std::vector<std::string> pfnPostfixList;
0202   if (!globaltag.empty()) {
0203     std::string pfnPrefix(iConfig.getUntrackedParameter<std::string>("pfnPrefix", ""));
0204     std::string pfnPostfix(iConfig.getUntrackedParameter<std::string>("pfnPostfix", ""));
0205     boost::split(globaltagList, globaltag, boost::is_any_of("|"), boost::token_compress_off);
0206     fillList(m_connectionString, connectList, globaltagList.size(), "connection");
0207     fillList(pfnPrefix, pfnPrefixList, globaltagList.size(), "pfnPrefix");
0208     fillList(pfnPostfix, pfnPostfixList, globaltagList.size(), "pfnPostfix");
0209   }
0210 
0211   cond::GTMetadata_t gtMetadata;
0212   fillTagCollectionFromDB(connectList, pfnPrefixList, pfnPostfixList, globaltagList, replacements, gtMetadata);
0213   // if no job specific setting has been found, use the GT timestamp
0214   if (snapshotTime.is_not_a_date_time())
0215     snapshotTime = gtMetadata.snapshotTime;
0216 
0217   TagCollection::iterator it;
0218   TagCollection::iterator itBeg = m_tagCollection.begin();
0219   TagCollection::iterator itEnd = m_tagCollection.end();
0220 
0221   std::map<std::string, cond::persistency::Session> sessions;
0222 
0223   /* load DataProxy Plugin (it is strongly typed due to EventSetup ideosyncrasis)
0224    * construct proxy
0225    * contrary to EventSetup the "object-name" is not used as identifier: multiple entries in a record are
0226    * dinstinguished only by their label...
0227    * done in two step: first create ProxyWrapper loading ALL required dictionaries
0228    * this will allow to initialize POOL in one go for each "database"
0229    * The real initialization of the Data-Proxies is done in the second loop 
0230    */
0231   std::vector<std::unique_ptr<cond::DataProxyWrapperBase>> proxyWrappers(m_tagCollection.size());
0232   size_t ipb = 0;
0233   for (it = itBeg; it != itEnd; ++it) {
0234     size_t ind = ipb++;
0235     proxyWrappers[ind] = std::unique_ptr<cond::DataProxyWrapperBase>{
0236         cond::ProxyFactory::get()->tryToCreate(buildName(it->second.recordName()))};
0237     if (!proxyWrappers[ind].get()) {
0238       edm::LogWarning("CondDBESSource") << "Plugin for Record " << it->second.recordName() << " has not been found.";
0239     }
0240   }
0241 
0242   // now all required libraries have been loaded
0243   // init sessions and DataProxies
0244   ipb = 0;
0245   for (it = itBeg; it != itEnd; ++it) {
0246     std::string connStr = m_connectionString;
0247     std::string tag = it->second.tagName();
0248     std::pair<std::string, std::string> tagParams = cond::persistency::parseTag(it->second.tagName());
0249     if (!tagParams.second.empty()) {
0250       connStr = tagParams.second;
0251       tag = tagParams.first;
0252     }
0253     std::map<std::string, cond::persistency::Session>::iterator p = sessions.find(connStr);
0254     cond::persistency::Session nsess;
0255     if (p == sessions.end()) {
0256       std::string oracleConnStr = cond::persistency::convertoToOracleConnection(connStr);
0257       std::tuple<std::string, std::string, std::string> connPars =
0258           cond::persistency::parseConnectionString(oracleConnStr);
0259       std::string dbService = std::get<1>(connPars);
0260       std::string dbAccount = std::get<2>(connPars);
0261       if ((dbService == "cms_orcon_prod" || dbService == "cms_orcon_adg") && dbAccount != "CMS_CONDITIONS")
0262         edm::LogWarning("CondDBESSource")
0263             << "[WARNING] You are reading tag \"" << tag << "\" from V1 account \"" << connStr
0264             << "\". The concerned Conditions might be out of date." << std::endl;
0265       //open db get tag info (i.e. the IOV token...)
0266       nsess = m_connection.createReadOnlySession(connStr, "");
0267       sessions.insert(std::make_pair(connStr, nsess));
0268     } else
0269       nsess = (*p).second;
0270 
0271     // ownership...
0272     ProxyP proxy(std::move(proxyWrappers[ipb++]));
0273     //  instert in the map
0274     if (proxy.get()) {
0275       m_proxies.insert(std::make_pair(it->second.recordName(), proxy));
0276       // initialize
0277       boost::posix_time::ptime tagSnapshotTime = snapshotTime;
0278       auto tagSnapshotIter = specialSnapshots.find(it->first);
0279       if (tagSnapshotIter != specialSnapshots.end())
0280         tagSnapshotTime = tagSnapshotIter->second;
0281       // finally, if the snapshot is set to infinity, reset the snapshot to null, to take the full iov set...
0282       if (tagSnapshotTime == boost::posix_time::time_from_string(std::string(cond::time::MAX_TIMESTAMP)))
0283         tagSnapshotTime = boost::posix_time::ptime();
0284 
0285       proxy->lateInit(nsess, tag, tagSnapshotTime, it->second.recordLabel(), connStr, &m_queue, &m_mutex);
0286     }
0287   }
0288 
0289   // one loaded expose all other tags to the Proxy!
0290   CondGetterFromESSource visitor(m_proxies);
0291   ProxyMap::iterator b = m_proxies.begin();
0292   ProxyMap::iterator e = m_proxies.end();
0293   for (; b != e; b++) {
0294     (*b).second->proxy(0)->loadMore(visitor);
0295 
0296     /// required by eventsetup
0297     EventSetupRecordKey recordKey(EventSetupRecordKey::TypeTag::findType((*b).first));
0298     if (recordKey.type() != EventSetupRecordKey::TypeTag()) {
0299       findingRecordWithKey(recordKey);
0300       usingRecordWithKey(recordKey);
0301     }
0302   }
0303 
0304   m_stats.nData = m_proxies.size();
0305 }
0306 
0307 void CondDBESSource::fillList(const std::string& stringList,
0308                               std::vector<std::string>& listToFill,
0309                               const unsigned int listSize,
0310                               const std::string& type) {
0311   boost::split(listToFill, stringList, boost::is_any_of("|"), boost::token_compress_off);
0312   // If it is one clone it for each GT
0313   if (listToFill.size() == 1) {
0314     for (unsigned int i = 1; i < listSize; ++i) {
0315       listToFill.push_back(stringList);
0316     }
0317   }
0318   // else if they don't match the number of GTs throw an exception
0319   else if (listSize != listToFill.size()) {
0320     throw cond::Exception(
0321         std::string("ESSource: number of global tag components does not match number of " + type + " strings"));
0322   }
0323 }
0324 
0325 CondDBESSource::~CondDBESSource() {
0326   //dump info FIXME: find a more suitable place...
0327   if (m_doDump) {
0328     std::cout << "CondDBESSource Statistics" << std::endl
0329               << "DataProxy " << m_stats.nData << " setInterval " << m_stats.nSet << " Runs " << m_stats.nRun
0330               << " Lumis " << m_stats.nLumi << " Refresh " << m_stats.nRefresh << " Actual Refresh "
0331               << m_stats.nActualRefresh << " Reconnect " << m_stats.nReconnect << " Actual Reconnect "
0332               << m_stats.nActualReconnect;
0333     std::cout << std::endl;
0334 
0335     ProxyMap::iterator b = m_proxies.begin();
0336     ProxyMap::iterator e = m_proxies.end();
0337     for (; b != e; b++) {
0338       dumpInfo(std::cout, (*b).first, *(*b).second);
0339       std::cout << "\n" << std::endl;
0340     }
0341 
0342     // FIXME
0343     // We shall eventually close transaction and session...
0344   }
0345 }
0346 
0347 //
0348 // invoked by EventSetUp: for a given record return the smallest IOV for which iTime is valid
0349 // limit to next run/lumisection of Refresh is required
0350 //
0351 void CondDBESSource::setIntervalFor(const EventSetupRecordKey& iKey,
0352                                     const edm::IOVSyncValue& iTime,
0353                                     edm::ValidityInterval& oInterval) {
0354   std::string recordname = iKey.name();
0355 
0356   edm::LogInfo("CondDBESSource") << "Getting data for record \"" << recordname
0357                                  << "\" to be consumed on Run: " << iTime.eventID().run()
0358                                  << " - Lumiblock:" << iTime.luminosityBlockNumber()
0359                                  << " - Timestamp: " << iTime.time().value() << "; from CondDBESSource::setIntervalFor";
0360 
0361   std::lock_guard<std::mutex> guard(m_mutex);
0362   m_stats.nSet++;
0363 
0364   if (iTime.eventID().run() != m_lastRun) {
0365     m_lastRun = iTime.eventID().run();
0366     m_stats.nRun++;
0367   }
0368   if (iTime.luminosityBlockNumber() != m_lastLumi) {
0369     m_lastLumi = iTime.luminosityBlockNumber();
0370     m_stats.nLumi++;
0371   }
0372 
0373   bool doRefresh = false;
0374   cond::Time_t defaultIovSize = cond::time::MAX_VAL;
0375   bool refreshThisRecord = false;
0376   bool reconnectThisRecord = false;
0377 
0378   auto iR = m_refreshTimeForRecord.find(recordname);
0379   refreshThisRecord = iR != m_refreshTimeForRecord.end();
0380   if (refreshThisRecord) {
0381     defaultIovSize = iR->second.first;
0382     reconnectThisRecord = iR->second.second;
0383     iR->second.second = false;
0384   }
0385 
0386   if (m_policy == REFRESH_EACH_RUN || m_policy == RECONNECT_EACH_RUN) {
0387     // find out the last run number for the proxy of the specified record
0388     std::map<std::string, unsigned int>::iterator iRec = m_lastRecordRuns.find(recordname);
0389     if (iRec != m_lastRecordRuns.end()) {
0390       cond::Time_t lastRecordRun = iRec->second;
0391       if (lastRecordRun != m_lastRun) {
0392         // a refresh is required!
0393         doRefresh = true;
0394         iRec->second = m_lastRun;
0395         edm::LogInfo("CondDBESSource") << "Preparing refresh for record \"" << recordname
0396                                        << "\" since there has been a transition from run/lumi " << lastRecordRun
0397                                        << " to run/lumi " << m_lastRun << "; from CondDBESSource::setIntervalFor";
0398       }
0399     } else {
0400       doRefresh = true;
0401       m_lastRecordRuns.insert(std::make_pair(recordname, m_lastRun));
0402       edm::LogInfo("CondDBESSource") << "Preparing refresh for record \"" << recordname << "\" for " << iTime.eventID()
0403                                      << ", timestamp: " << iTime.time().value()
0404                                      << "; from CondDBESSource::setIntervalFor";
0405     }
0406     if (!doRefresh)
0407       edm::LogInfo("CondDBESSource") << "Though enabled, refresh not needed for record \"" << recordname << "\" for "
0408                                      << iTime.eventID() << ", timestamp: " << iTime.time().value()
0409                                      << "; from CondDBESSource::setIntervalFor";
0410   } else if (m_policy == REFRESH_ALWAYS || m_policy == REFRESH_OPEN_IOVS) {
0411     doRefresh = true;
0412     edm::LogInfo("CondDBESSource") << "Forcing refresh for record \"" << recordname << "\" for " << iTime.eventID()
0413                                    << ", timestamp: " << iTime.time().value()
0414                                    << "; from CondDBESSource::setIntervalFor";
0415   }
0416 
0417   oInterval = edm::ValidityInterval::invalidInterval();
0418 
0419   // compute the smallest interval (assume all objects have the same timetype....)
0420   cond::ValidityInterval recordValidity(1, cond::TIMELIMIT);
0421   cond::TimeType timetype = cond::TimeType::invalid;
0422   bool userTime = true;
0423 
0424   //FIXME use equal_range
0425   ProxyMap::const_iterator pmBegin = m_proxies.lower_bound(recordname);
0426   ProxyMap::const_iterator pmEnd = m_proxies.upper_bound(recordname);
0427   if (pmBegin == pmEnd) {
0428     edm::LogInfo("CondDBESSource") << "No DataProxy (Pluging) found for record \"" << recordname
0429                                    << "\"; from CondDBESSource::setIntervalFor";
0430     return;
0431   }
0432 
0433   for (ProxyMap::const_iterator pmIter = pmBegin; pmIter != pmEnd; ++pmIter) {
0434     edm::LogInfo("CondDBESSource") << "Processing record \"" << recordname << "\" and label \""
0435                                    << pmIter->second->label() << "\" for " << iTime.eventID()
0436                                    << ", timestamp: " << iTime.time().value()
0437                                    << "; from CondDBESSource::setIntervalFor";
0438 
0439     timetype = (*pmIter).second->timeType();
0440 
0441     cond::Time_t abtime = cond::time::fromIOVSyncValue(iTime, timetype);
0442     userTime = (0 == abtime);
0443 
0444     if (userTime)
0445       return;  //  oInterval invalid to avoid that make is called...
0446 
0447     if (doRefresh || refreshThisRecord) {
0448       std::string recKey = joinRecordAndLabel(recordname, pmIter->second->label());
0449       TagCollection::const_iterator tcIter = m_tagCollection.find(recKey);
0450       if (tcIter == m_tagCollection.end()) {
0451         edm::LogInfo("CondDBESSource") << "No Tag found for record \"" << recordname << "\" and label \""
0452                                        << pmIter->second->label() << "\"; from CondDBESSource::setIntervalFor";
0453         return;
0454       }
0455 
0456       // first reconnect if required
0457       if (m_policy == RECONNECT_EACH_RUN || reconnectThisRecord) {
0458         edm::LogInfo("CondDBESSource")
0459             << "Checking if the session must be closed and re-opened for getting correct conditions"
0460             << "; from CondDBESSource::setIntervalFor";
0461         std::string transId;
0462         if (!reconnectThisRecord) {
0463           transId = std::to_string(abtime);
0464         } else {
0465           transId = cond::time::transactionIdForLumiTime(abtime, defaultIovSize, m_frontierKey);
0466         }
0467         std::string connStr = m_connectionString;
0468         std::pair<std::string, std::string> tagParams = cond::persistency::parseTag(tcIter->second.tagName());
0469         if (!tagParams.second.empty())
0470           connStr = tagParams.second;
0471         std::map<std::string, std::pair<cond::persistency::Session, std::string>>* sessionPool = &m_sessionPool;
0472         if (refreshThisRecord) {
0473           sessionPool = &m_sessionPoolForLumiConditions;
0474         }
0475         auto iSess = sessionPool->find(connStr);
0476         bool reopen = false;
0477         if (iSess != sessionPool->end()) {
0478           if (iSess->second.second != transId) {
0479             // the available session is open for a different run: reopen
0480             reopen = true;
0481             iSess->second.second = transId;
0482           }
0483         } else {
0484           // no available session: probably first run analysed...
0485           iSess =
0486               sessionPool->insert(std::make_pair(connStr, std::make_pair(cond::persistency::Session(), transId))).first;
0487           reopen = true;
0488         }
0489         if (reopen) {
0490           iSess->second.first = m_connection.createReadOnlySession(connStr, transId);
0491           edm::LogInfo("CondDBESSource") << "Re-opening the session with connection string " << connStr
0492                                          << " and new transaction Id " << transId
0493                                          << "; from CondDBESSource::setIntervalFor";
0494         }
0495 
0496         edm::LogInfo("CondDBESSource") << "Reconnecting to \"" << connStr << "\" for getting new payload for record \""
0497                                        << recordname << "\" and label \"" << pmIter->second->label()
0498                                        << "\" from IOV tag \"" << tcIter->second.tagName() << "\" to be consumed by "
0499                                        << iTime.eventID() << ", timestamp: " << iTime.time().value()
0500                                        << "; from CondDBESSource::setIntervalFor";
0501         pmIter->second->session() = iSess->second.first;
0502         pmIter->second->reload();
0503         m_stats.nReconnect++;
0504       } else {
0505         edm::LogInfo("CondDBESSource") << "Refreshing IOV sequence labeled by tag \"" << tcIter->second.tagName()
0506                                        << "\" for getting new payload for record \"" << recordname << "\" and label \""
0507                                        << pmIter->second->label() << "\" to be consumed by " << iTime.eventID()
0508                                        << ", timestamp: " << iTime.time().value()
0509                                        << "; from CondDBESSource::setIntervalFor";
0510         pmIter->second->reload();
0511         m_stats.nRefresh++;
0512       }
0513     }
0514 
0515     //query the IOVSequence
0516     cond::ValidityInterval validity = (*pmIter).second->setIntervalFor(abtime);
0517 
0518     edm::LogInfo("CondDBESSource") << "Validity coming from IOV sequence for record \"" << recordname
0519                                    << "\" and label \"" << pmIter->second->label() << "\": (" << validity.first << ", "
0520                                    << validity.second << ") for time (type: " << cond::timeTypeNames(timetype) << ") "
0521                                    << abtime << "; from CondDBESSource::setIntervalFor";
0522 
0523     recordValidity.first = std::max(recordValidity.first, validity.first);
0524     recordValidity.second = std::min(recordValidity.second, validity.second);
0525     if (refreshThisRecord && recordValidity.second == cond::TIMELIMIT) {
0526       iR->second.second = true;
0527       if (defaultIovSize)
0528         recordValidity.second = cond::time::tillTimeForIOV(abtime, defaultIovSize, timetype);
0529       else {
0530         recordValidity.second = 0;
0531       }
0532     }
0533   }
0534 
0535   if (m_policy == REFRESH_OPEN_IOVS) {
0536     doRefresh = (recordValidity.second == cond::timeTypeSpecs[timetype].endValue);
0537     edm::LogInfo("CondDBESSource") << "Validity for record \"" << recordname
0538                                    << "\" and the corresponding label(s) coming from Condition DB: ("
0539                                    << recordValidity.first << ", " << recordValidity.first
0540                                    << ") as the last IOV element in the IOV sequence is infinity"
0541                                    << "; from CondDBESSource::setIntervalFor";
0542   }
0543 
0544   // to force refresh we set end-value to the minimum such an IOV can extend to: current run or lumiblock
0545   if ((!userTime) && recordValidity.second != 0) {
0546     edm::IOVSyncValue start = cond::time::toIOVSyncValue(recordValidity.first, timetype, true);
0547     edm::IOVSyncValue stop = doRefresh ? cond::time::limitedIOVSyncValue(iTime, timetype)
0548                                        : cond::time::toIOVSyncValue(recordValidity.second, timetype, false);
0549 
0550     if (start == edm::IOVSyncValue::invalidIOVSyncValue() && stop != edm::IOVSyncValue::invalidIOVSyncValue()) {
0551       start = edm::IOVSyncValue::beginOfTime();
0552     }
0553     oInterval = edm::ValidityInterval(start, stop);
0554   }
0555 
0556   edm::LogInfo("CondDBESSource") << "Setting validity for record \"" << recordname
0557                                  << "\" and corresponding label(s): starting at " << oInterval.first().eventID()
0558                                  << ", timestamp: " << oInterval.first().time().value() << ", ending at "
0559                                  << oInterval.last().eventID() << ", timestamp: " << oInterval.last().time().value()
0560                                  << ", for " << iTime.eventID() << ", timestamp: " << iTime.time().value()
0561                                  << "; from CondDBESSource::setIntervalFor";
0562 }
0563 
0564 //required by EventSetup System
0565 edm::eventsetup::DataProxyProvider::KeyedProxiesVector CondDBESSource::registerProxies(
0566     const EventSetupRecordKey& iRecordKey, unsigned int iovIndex) {
0567   KeyedProxiesVector keyedProxiesVector;
0568 
0569   std::string recordname = iRecordKey.name();
0570 
0571   ProxyMap::const_iterator b = m_proxies.lower_bound(recordname);
0572   ProxyMap::const_iterator e = m_proxies.upper_bound(recordname);
0573   if (b == e) {
0574     edm::LogInfo("CondDBESSource") << "No DataProxy (Pluging) found for record \"" << recordname
0575                                    << "\"; from CondDBESSource::registerProxies";
0576     return keyedProxiesVector;
0577   }
0578 
0579   for (ProxyMap::const_iterator p = b; p != e; ++p) {
0580     if (nullptr != (*p).second.get()) {
0581       edm::eventsetup::TypeTag type = (*p).second->type();
0582       DataKey key(type, edm::eventsetup::IdTags((*p).second->label().c_str()));
0583       keyedProxiesVector.emplace_back(key, (*p).second->edmProxy(iovIndex));
0584     }
0585   }
0586   return keyedProxiesVector;
0587 }
0588 
0589 void CondDBESSource::initConcurrentIOVs(const EventSetupRecordKey& key, unsigned int nConcurrentIOVs) {
0590   std::string recordname = key.name();
0591   ProxyMap::const_iterator b = m_proxies.lower_bound(recordname);
0592   ProxyMap::const_iterator e = m_proxies.upper_bound(recordname);
0593   for (ProxyMap::const_iterator p = b; p != e; ++p) {
0594     if (p->second) {
0595       p->second->initConcurrentIOVs(nConcurrentIOVs);
0596     }
0597   }
0598 }
0599 
0600 // Fills tag collection from the given globaltag
0601 void CondDBESSource::fillTagCollectionFromGT(const std::string& connectionString,
0602                                              const std::string& prefix,
0603                                              const std::string& postfix,
0604                                              const std::string& roottag,
0605                                              std::set<cond::GTEntry_t>& tagcoll,
0606                                              cond::GTMetadata_t& gtMetadata) {
0607   if (!roottag.empty()) {
0608     if (connectionString.empty())
0609       throw cond::Exception(std::string("ESSource: requested global tag ") + roottag +
0610                             std::string(" but not connection string given"));
0611     std::tuple<std::string, std::string, std::string> connPars =
0612         cond::persistency::parseConnectionString(connectionString);
0613     if (std::get<2>(connPars) == "CMS_COND_31X_GLOBALTAG") {
0614       edm::LogWarning("CondDBESSource")
0615           << "[WARNING] You are reading Global Tag \"" << roottag
0616           << "\" from V1 account \"CMS_COND_31X_GLOBALTAG\". The concerned Conditions might be out of date."
0617           << std::endl;
0618     } else if (roottag.rfind("::All") != std::string::npos && std::get<2>(connPars) == "CMS_CONDITIONS") {
0619       edm::LogWarning("CondDBESSource") << "[WARNING] You are trying to read Global Tag \"" << roottag
0620                                         << "\" - postfix \"::All\" should not be used for V2." << std::endl;
0621     }
0622     cond::persistency::Session session = m_connection.createSession(connectionString);
0623     session.transaction().start(true);
0624     cond::persistency::GTProxy gtp = session.readGlobalTag(roottag, prefix, postfix);
0625     gtMetadata.snapshotTime = gtp.snapshotTime();
0626     for (const auto& gte : gtp) {
0627       tagcoll.insert(gte);
0628     }
0629     session.transaction().commit();
0630   }
0631 }
0632 
0633 // fills tagcollection merging with replacement
0634 // Note: it assumem the coraldbList and roottagList have the same length. This checked in the constructor that prepares the two lists before calling this method.
0635 void CondDBESSource::fillTagCollectionFromDB(const std::vector<std::string>& connectionStringList,
0636                                              const std::vector<std::string>& prefixList,
0637                                              const std::vector<std::string>& postfixList,
0638                                              const std::vector<std::string>& roottagList,
0639                                              std::map<std::string, cond::GTEntry_t>& replacement,
0640                                              cond::GTMetadata_t& gtMetadata) {
0641   std::set<cond::GTEntry_t> tagcoll;
0642 
0643   auto connectionString = connectionStringList.begin();
0644   auto prefix = prefixList.begin();
0645   auto postfix = postfixList.begin();
0646   for (auto roottag = roottagList.begin(); roottag != roottagList.end();
0647        ++roottag, ++connectionString, ++prefix, ++postfix) {
0648     fillTagCollectionFromGT(*connectionString, *prefix, *postfix, *roottag, tagcoll, gtMetadata);
0649   }
0650 
0651   std::set<cond::GTEntry_t>::iterator tagCollIter;
0652   std::set<cond::GTEntry_t>::iterator tagCollBegin = tagcoll.begin();
0653   std::set<cond::GTEntry_t>::iterator tagCollEnd = tagcoll.end();
0654 
0655   // FIXME the logic is a bit perverse: can be surely linearized (at least simplified!) ....
0656   for (tagCollIter = tagCollBegin; tagCollIter != tagCollEnd; ++tagCollIter) {
0657     std::string recordLabelKey = joinRecordAndLabel(tagCollIter->recordName(), tagCollIter->recordLabel());
0658     std::map<std::string, cond::GTEntry_t>::iterator fid = replacement.find(recordLabelKey);
0659     if (fid != replacement.end()) {
0660       if (!fid->second.tagName().empty()) {
0661         cond::GTEntry_t tagMetadata(
0662             std::make_tuple(tagCollIter->recordName(), tagCollIter->recordLabel(), fid->second.tagName()));
0663         m_tagCollection.insert(std::make_pair(recordLabelKey, tagMetadata));
0664         edm::LogInfo("CondDBESSource") << "Replacing tag \"" << tagCollIter->tagName() << "\" for record \""
0665                                        << tagMetadata.recordName() << "\" and label \"" << tagMetadata.recordLabel()
0666                                        << "\" with tag " << tagMetadata.tagName()
0667                                        << "\"; from CondDBESSource::fillTagCollectionFromDB";
0668       } else {
0669         m_tagCollection.insert(std::make_pair(recordLabelKey, *tagCollIter));
0670       }
0671       replacement.erase(fid);
0672     } else {
0673       m_tagCollection.insert(std::make_pair(recordLabelKey, *tagCollIter));
0674     }
0675   }
0676   std::map<std::string, cond::GTEntry_t>::iterator replacementIter;
0677   std::map<std::string, cond::GTEntry_t>::iterator replacementBegin = replacement.begin();
0678   std::map<std::string, cond::GTEntry_t>::iterator replacementEnd = replacement.end();
0679   for (replacementIter = replacementBegin; replacementIter != replacementEnd; ++replacementIter) {
0680     if (replacementIter->second.tagName().empty()) {
0681       std::stringstream msg;
0682       msg << "ESSource: no tag provided for record " << replacementIter->second.recordName();
0683       if (!replacementIter->second.recordLabel().empty())
0684         msg << " and label " << replacementIter->second.recordLabel();
0685       throw cond::Exception(msg.str());
0686     }
0687     m_tagCollection.insert(*replacementIter);
0688   }
0689 }
0690 
0691 // backward compatibility for configuration files
0692 class PoolDBESSource : public CondDBESSource {
0693 public:
0694   explicit PoolDBESSource(const edm::ParameterSet& ps) : CondDBESSource(ps) {}
0695 };
0696 
0697 #include "FWCore/Framework/interface/SourceFactory.h"
0698 //define this as a plug-in
0699 DEFINE_FWK_EVENTSETUP_SOURCE(PoolDBESSource);