Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-17 04:58:07

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