Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-07-16 02:42:36

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