Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:28

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