Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-02 23:19:22

0001 #include <memory>
0002 
0003 #include "CondCore/CondDB/interface/IOVProxy.h"
0004 #include "CondCore/CondDB/interface/Time.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 #include "SessionImpl.h"
0007 
0008 using cond::time::lumiIdToLumiNr;
0009 using cond::time::lumiIdToRun;
0010 namespace cond {
0011 
0012   namespace persistency {
0013 
0014     // comparison functor for iov tuples: Time_t only and Time_t,string
0015     struct IOVComp {
0016       bool operator()(const cond::Time_t& x, const cond::Time_t& y) { return (x < y); }
0017 
0018       bool operator()(const cond::Time_t& x, const std::tuple<cond::Time_t, cond::Hash>& y) {
0019         return (x < std::get<0>(y));
0020       }
0021     };
0022 
0023     // function to search in the vector the target time
0024     template <typename T>
0025     typename std::vector<T>::const_iterator search(const cond::Time_t& val, const std::vector<T>& container) {
0026       if (container.empty())
0027         return container.end();
0028       auto p = std::upper_bound(container.begin(), container.end(), val, IOVComp());
0029       return (p != container.begin()) ? p - 1 : container.end();
0030     }
0031 
0032     IOVArray::Iterator::Iterator() : m_current(), m_parent(nullptr) {}
0033 
0034     IOVArray::Iterator::Iterator(IOVContainer::const_iterator current, const IOVArray* parent)
0035         : m_current(current), m_parent(parent) {}
0036 
0037     IOVArray::Iterator::Iterator(const Iterator& rhs) : m_current(rhs.m_current), m_parent(rhs.m_parent) {}
0038 
0039     IOVArray::Iterator& IOVArray::Iterator::operator=(const Iterator& rhs) {
0040       if (this != &rhs) {
0041         m_current = rhs.m_current;
0042         m_parent = rhs.m_parent;
0043       }
0044       return *this;
0045     }
0046 
0047     cond::Iov_t IOVArray::Iterator::operator*() {
0048       cond::Iov_t retVal;
0049       retVal.since = std::get<0>(*m_current);
0050       auto next = m_current;
0051       next++;
0052       if (next == m_parent->m_array->end()) {
0053         retVal.till = cond::time::MAX_VAL;
0054       } else {
0055         retVal.till = cond::time::tillTimeFromNextSince(std::get<0>(*next), m_parent->m_tagInfo.timeType);
0056       }
0057       // default is the end of validity when set...
0058       if (retVal.till > m_parent->m_tagInfo.endOfValidity) {
0059         retVal.till = m_parent->m_tagInfo.endOfValidity;
0060       }
0061       retVal.payloadId = std::get<1>(*m_current);
0062 
0063       return retVal;
0064     }
0065 
0066     IOVArray::Iterator& IOVArray::Iterator::operator++() {
0067       m_current++;
0068       return *this;
0069     }
0070 
0071     IOVArray::Iterator IOVArray::Iterator::operator++(int) {
0072       Iterator tmp(*this);
0073       operator++();
0074       return tmp;
0075     }
0076 
0077     bool IOVArray::Iterator::operator==(const Iterator& rhs) const {
0078       if (m_current != rhs.m_current)
0079         return false;
0080       if (m_parent != rhs.m_parent)
0081         return false;
0082       return true;
0083     }
0084 
0085     bool IOVArray::Iterator::operator!=(const Iterator& rhs) const { return !operator==(rhs); }
0086 
0087     IOVArray::IOVArray() : m_array(new IOVContainer) {}
0088 
0089     IOVArray::IOVArray(const IOVArray& rhs) : m_array(), m_tagInfo(rhs.m_tagInfo) {
0090       m_array = std::make_unique<IOVContainer>(*rhs.m_array);
0091     }
0092 
0093     IOVArray& IOVArray::operator=(const IOVArray& rhs) {
0094       m_array = std::make_unique<IOVContainer>(*rhs.m_array);
0095       m_tagInfo = rhs.m_tagInfo;
0096       return *this;
0097     }
0098 
0099     const cond::Tag_t& IOVArray::tagInfo() const { return m_tagInfo; }
0100 
0101     IOVArray::Iterator IOVArray::begin() const { return Iterator(m_array->begin(), this); }
0102 
0103     IOVArray::Iterator IOVArray::end() const { return Iterator(m_array->end(), this); }
0104 
0105     IOVArray::Iterator IOVArray::find(cond::Time_t time) const { return Iterator(search(time, *m_array), this); }
0106 
0107     size_t IOVArray::size() const { return m_array->size(); }
0108 
0109     // returns true if at least one IOV is in the sequence.
0110     bool IOVArray::isEmpty() const { return m_array->empty(); }
0111 
0112     // implementation details...
0113     // only hosting data in this case
0114     class IOVProxyData {
0115     public:
0116       IOVProxyData() : iovSequence() {}
0117 
0118       // tag data
0119       cond::Tag_t tagInfo;
0120       // iov data
0121       boost::posix_time::ptime snapshotTime;
0122       cond::Time_t groupLowerIov = cond::time::MAX_VAL;
0123       cond::Time_t groupHigherIov = cond::time::MIN_VAL;
0124       bool cacheInitialized = false;
0125       std::vector<cond::Time_t> sinceGroups;
0126       IOVContainer iovSequence;
0127       // monitoring data
0128       size_t numberOfQueries = 0;
0129     };
0130 
0131     IOVProxy::IOVProxy(const std::shared_ptr<SessionImpl>& session) : m_data(new IOVProxyData), m_session(session) {}
0132 
0133     void IOVProxy::load(const std::string& tagName) {
0134       boost::posix_time::ptime notime;
0135       load(tagName, notime);
0136     }
0137 
0138     void IOVProxy::load(const std::string& tagName, const boost::posix_time::ptime& snapshotTime) {
0139       if (!m_data.get())
0140         return;
0141 
0142       // clear
0143       reset();
0144 
0145       checkTransaction("IOVProxyNew::load");
0146 
0147       int dummy;
0148       if (!m_session->iovSchema().tagTable().select(tagName,
0149                                                     m_data->tagInfo.timeType,
0150                                                     m_data->tagInfo.payloadType,
0151                                                     m_data->tagInfo.synchronizationType,
0152                                                     m_data->tagInfo.endOfValidity,
0153                                                     m_data->tagInfo.lastValidatedTime,
0154                                                     dummy)) {
0155         throwException("Tag \"" + tagName + "\" has not been found in the database.", "IOVProxy::load");
0156       }
0157       m_data->tagInfo.name = tagName;
0158       m_data->snapshotTime = snapshotTime;
0159     }
0160 
0161     void IOVProxy::loadGroups() {
0162       //if( !m_data.get() ) return;
0163 
0164       // clear
0165       resetIOVCache();
0166 
0167       //checkTransaction( "IOVProxyNew::load" );
0168       m_session->iovSchema().iovTable().getGroups(m_data->tagInfo.name,
0169                                                   m_data->snapshotTime,
0170                                                   cond::time::sinceGroupSize(m_data->tagInfo.timeType),
0171                                                   m_data->sinceGroups);
0172       m_data->cacheInitialized = true;
0173     }
0174 
0175     IOVArray IOVProxy::selectAll() {
0176       boost::posix_time::ptime no_time;
0177       return selectAll(no_time);
0178     }
0179 
0180     IOVArray IOVProxy::selectAll(const boost::posix_time::ptime& snapshottime) {
0181       if (!m_data.get())
0182         throwException("No tag has been loaded.", "IOVProxy::selectAll");
0183       checkTransaction("IOVProxy::selectAll");
0184       IOVArray ret;
0185       ret.m_tagInfo = m_data->tagInfo;
0186       m_session->iovSchema().iovTable().select(
0187           m_data->tagInfo.name, cond::time::MIN_VAL, cond::time::MAX_VAL, snapshottime, *ret.m_array);
0188       return ret;
0189     }
0190 
0191     IOVArray IOVProxy::selectRange(const cond::Time_t& begin, const cond::Time_t& end) {
0192       boost::posix_time::ptime no_time;
0193       return selectRange(begin, end, no_time);
0194     }
0195 
0196     IOVArray IOVProxy::selectRange(const cond::Time_t& begin,
0197                                    const cond::Time_t& end,
0198                                    const boost::posix_time::ptime& snapshotTime) {
0199       if (!m_data.get())
0200         throwException("No tag has been loaded.", "IOVProxy::selectRange");
0201 
0202       checkTransaction("IOVProxy::selectRange");
0203 
0204       IOVArray ret;
0205       ret.m_tagInfo = m_data->tagInfo;
0206       m_session->iovSchema().iovTable().getRange(m_data->tagInfo.name, begin, end, snapshotTime, *ret.m_array);
0207       return ret;
0208     }
0209 
0210     bool IOVProxy::selectRange(const cond::Time_t& begin, const cond::Time_t& end, IOVContainer& destination) {
0211       if (!m_data.get())
0212         throwException("No tag has been loaded.", "IOVProxy::selectRange");
0213 
0214       checkTransaction("IOVProxy::selectRange");
0215 
0216       boost::posix_time::ptime no_time;
0217       size_t prevSize = destination.size();
0218       m_session->iovSchema().iovTable().getRange(m_data->tagInfo.name, begin, end, no_time, destination);
0219       size_t niov = destination.size() - prevSize;
0220       return niov > 0;
0221     }
0222 
0223     void IOVProxy::resetIOVCache() {
0224       if (m_data.get()) {
0225         m_data->groupLowerIov = cond::time::MAX_VAL;
0226         m_data->groupHigherIov = cond::time::MIN_VAL;
0227         m_data->sinceGroups.clear();
0228         m_data->iovSequence.clear();
0229         m_data->numberOfQueries = 0;
0230       }
0231     }
0232 
0233     void IOVProxy::reset() {
0234       if (m_data.get()) {
0235         m_data->tagInfo.clear();
0236       }
0237       resetIOVCache();
0238     }
0239 
0240     cond::Tag_t IOVProxy::tagInfo() const { return m_data.get() ? m_data->tagInfo : cond::Tag_t(); }
0241 
0242     void setTillToLastIov(cond::Iov_t& target, cond::Time_t endOfValidity) {
0243       if (endOfValidity < cond::time::MAX_VAL) {
0244         if (target.since >= endOfValidity) {
0245           target.clear();
0246         } else {
0247           target.till = endOfValidity;
0248         }
0249       } else {
0250         target.till = cond::time::MAX_VAL;
0251       }
0252     }
0253 
0254     cond::TagInfo_t IOVProxy::iovSequenceInfo() const {
0255       if (!m_data.get())
0256         throwException("No tag has been loaded.", "IOVProxy::iovSequenceInfo");
0257       checkTransaction("IOVProxy::iovSequenceInfo");
0258       cond::TagInfo_t ret;
0259       m_session->iovSchema().iovTable().getSize(m_data->tagInfo.name, m_data->snapshotTime, ret.size);
0260       cond::Iov_t last;
0261       bool ok = m_session->iovSchema().iovTable().getLastIov(
0262           m_data->tagInfo.name, m_data->snapshotTime, ret.lastInterval.since, ret.lastInterval.payloadId);
0263       if (ok) {
0264         setTillToLastIov(ret.lastInterval, m_data->tagInfo.endOfValidity);
0265       }
0266       return ret;
0267     }
0268 
0269     std::tuple<std::string, boost::posix_time::ptime, boost::posix_time::ptime> IOVProxy::getMetadata() const {
0270       if (!m_data.get())
0271         throwException("No tag has been loaded.", "IOVProxy::getMetadata");
0272       checkTransaction("IOVProxy::getMetadata");
0273       std::tuple<std::string, boost::posix_time::ptime, boost::posix_time::ptime> ret;
0274       if (!m_session->iovSchema().tagTable().getMetadata(
0275               m_data->tagInfo.name, std::get<0>(ret), std::get<1>(ret), std::get<2>(ret))) {
0276         throwException("Metadata for tag \"" + m_data->tagInfo.name + "\" have not been found in the database.",
0277                        "IOVProxy::getMetadata");
0278       }
0279       return ret;
0280     }
0281 
0282     void IOVProxy::checkTransaction(const std::string& ctx) const {
0283       if (!m_session.get())
0284         throwException("The session is not active.", ctx);
0285       if (!m_session->isTransactionActive(false))
0286         throwException("The transaction is not active.", ctx);
0287     }
0288 
0289     void printTagInfoAndRanges(edm::LogSystem& log,
0290                                const IOVProxyData& iovProxyData,
0291                                cond::Time_t lowerGroup,
0292                                cond::Time_t higherGroup) {
0293       log << "Fetched new IOV for '" << iovProxyData.tagInfo.name << "'\n"
0294           << "payload type: " << iovProxyData.tagInfo.payloadType << "\n"
0295           << "request interval [ " << lowerGroup << " , " << higherGroup << " ]\n"
0296           << "new range [ " << iovProxyData.groupLowerIov << " , " << iovProxyData.groupHigherIov << " ]\n";
0297       if (iovProxyData.tagInfo.timeType == cond::TimeType::lumiid) {
0298         log << "request interval (run, LS): [ ("  // comments to override code-format
0299             << lumiIdToRun(lowerGroup) << ", " << lumiIdToLumiNr(lowerGroup) << ") , ("  //
0300             << lumiIdToRun(higherGroup) << ", " << lumiIdToLumiNr(higherGroup) << ") ]\n"
0301             << "new range (run, LS): [ ("  //
0302             << lumiIdToRun(iovProxyData.groupLowerIov) << ", " << lumiIdToLumiNr(iovProxyData.groupLowerIov) << ") , ("
0303             << lumiIdToRun(iovProxyData.groupHigherIov) << ", " << lumiIdToLumiNr(iovProxyData.groupHigherIov)
0304             << ") ]\n";
0305       }
0306     }
0307 
0308     void printIovsAndHashesOfSequence(edm::LogSystem& log, const IOVProxyData& iovProxyData) {
0309       const bool isLumiid = iovProxyData.tagInfo.timeType == cond::TimeType::lumiid;
0310       log << "#entries " << iovProxyData.iovSequence.size() << "\n"
0311           << "sequence [iov " << (isLumiid ? "(run, LS)" : "") << ", hash]:\n";
0312       for (const auto& [iov, hash] : iovProxyData.iovSequence) {
0313         log << iov << " ";
0314         if (isLumiid) {
0315           log << "(" << lumiIdToRun(iov) << ", " << lumiIdToLumiNr(iov) << ")";
0316         }
0317         log << ", " << hash << ",\n";
0318       }
0319     }
0320 
0321     void printIOVSequenceDiagnostics(const IOVProxyData& iovProxyData,
0322                                      cond::Time_t lowerGroup,
0323                                      cond::Time_t higherGroup) {
0324       edm::LogSystem log("NewIOV");  // creating here so everything is in one message
0325       printTagInfoAndRanges(log, iovProxyData, lowerGroup, higherGroup);
0326       printIovsAndHashesOfSequence(log, iovProxyData);
0327     }
0328 
0329     void IOVProxy::fetchSequence(cond::Time_t lowerGroup, cond::Time_t higherGroup) {
0330       m_data->iovSequence.clear();
0331       m_session->iovSchema().iovTable().select(
0332           m_data->tagInfo.name, lowerGroup, higherGroup, m_data->snapshotTime, m_data->iovSequence);
0333 
0334       if (m_data->iovSequence.empty()) {
0335         m_data->groupLowerIov = cond::time::MAX_VAL;
0336         m_data->groupHigherIov = cond::time::MIN_VAL;
0337       } else {
0338         if (lowerGroup > cond::time::MIN_VAL) {
0339           m_data->groupLowerIov = std::get<0>(m_data->iovSequence.front());
0340         } else {
0341           m_data->groupLowerIov = cond::time::MIN_VAL;
0342         }
0343         m_data->groupHigherIov = std::get<0>(m_data->iovSequence.back());
0344         if (higherGroup < cond::time::MAX_VAL) {
0345           m_data->groupHigherIov = cond::time::tillTimeFromNextSince(higherGroup, m_data->tagInfo.timeType);
0346         } else {
0347           m_data->groupHigherIov = cond::time::MAX_VAL;
0348         }
0349       }
0350       m_data->numberOfQueries++;
0351 
0352       if (m_printDebug) {
0353         printIOVSequenceDiagnostics(*m_data, lowerGroup, higherGroup);
0354       }
0355     }
0356 
0357     cond::Iov_t IOVProxy::getInterval(cond::Time_t time) {
0358       if (!m_data.get())
0359         throwException("No tag has been loaded.", "IOVProxy::getInterval");
0360       checkTransaction("IOVProxy::getInterval");
0361       if (!m_data->cacheInitialized)
0362         loadGroups();
0363       cond::Iov_t retVal;
0364       // organize iovs in pages...
0365       // first check the available iov cache:
0366       if (m_data->groupLowerIov == cond::time::MAX_VAL ||  // case 0 : empty cache ( the first request )
0367           time < m_data->groupLowerIov || time >= m_data->groupHigherIov) {  // case 1 : target outside
0368 
0369         // a new query required!
0370         // first determine the groups
0371         auto iGLow = search(time, m_data->sinceGroups);
0372         if (iGLow == m_data->sinceGroups.end()) {
0373           // no suitable group=no iov at all! exiting...
0374           return retVal;
0375         }
0376         auto iGHigh = iGLow;
0377         cond::Time_t lowG = *iGLow;
0378         iGHigh++;
0379         cond::Time_t highG = cond::time::MAX_VAL;
0380         if (iGHigh != m_data->sinceGroups.end())
0381           highG = *iGHigh;
0382 
0383         // finally, get the iovs for the selected group interval!!
0384         fetchSequence(lowG, highG);
0385       }
0386 
0387       // the current iov set is a good one...
0388       auto iIov = search(time, m_data->iovSequence);
0389       if (iIov == m_data->iovSequence.end()) {
0390         return retVal;
0391       }
0392 
0393       retVal.since = std::get<0>(*iIov);
0394       auto next = iIov;
0395       next++;
0396 
0397       // default is the end of validity when set...
0398       retVal.till = m_data->tagInfo.endOfValidity;
0399       // for the till, the next element of the sequence has to be looked up
0400       cond::Time_t tillVal;
0401       if (next != m_data->iovSequence.end()) {
0402         tillVal = cond::time::tillTimeFromNextSince(std::get<0>(*next), m_data->tagInfo.timeType);
0403       } else {
0404         tillVal = m_data->groupHigherIov;
0405       }
0406       if (tillVal < retVal.till)
0407         retVal.till = tillVal;
0408       //
0409       retVal.payloadId = std::get<1>(*iIov);
0410       return retVal;
0411     }
0412 
0413     cond::Iov_t IOVProxy::getLast() {
0414       checkTransaction("IOVProxy::getLast");
0415       cond::Iov_t ret;
0416       bool ok = m_session->iovSchema().iovTable().getLastIov(
0417           m_data->tagInfo.name, m_data->snapshotTime, ret.since, ret.payloadId);
0418       if (ok) {
0419         setTillToLastIov(ret, m_data->tagInfo.endOfValidity);
0420       }
0421       return ret;
0422     }
0423 
0424     int IOVProxy::loadedSize() const { return m_data.get() ? m_data->iovSequence.size() : 0; }
0425 
0426     int IOVProxy::sequenceSize() const {
0427       checkTransaction("IOVProxy::sequenceSize");
0428       size_t ret = 0;
0429       m_session->iovSchema().iovTable().getSize(m_data->tagInfo.name, m_data->snapshotTime, ret);
0430 
0431       return ret;
0432     }
0433 
0434     size_t IOVProxy::numberOfQueries() const { return m_data.get() ? m_data->numberOfQueries : 0; }
0435 
0436     std::pair<cond::Time_t, cond::Time_t> IOVProxy::loadedGroup() const {
0437       return m_data.get() ? std::make_pair(m_data->groupLowerIov, m_data->groupHigherIov)
0438                           : std::make_pair(cond::time::MAX_VAL, cond::time::MIN_VAL);
0439     }
0440 
0441     const std::shared_ptr<SessionImpl>& IOVProxy::session() const { return m_session; }
0442 
0443   }  // namespace persistency
0444 
0445 }  // namespace cond