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
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
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
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
0110 bool IOVArray::isEmpty() const { return m_array->empty(); }
0111
0112
0113
0114 class IOVProxyData {
0115 public:
0116 IOVProxyData() : iovSequence() {}
0117
0118
0119 cond::Tag_t tagInfo;
0120
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
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
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
0163
0164
0165 resetIOVCache();
0166
0167
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): [ ("
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");
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
0365
0366 if (m_data->groupLowerIov == cond::time::MAX_VAL ||
0367 time < m_data->groupLowerIov || time >= m_data->groupHigherIov) {
0368
0369
0370
0371 auto iGLow = search(time, m_data->sinceGroups);
0372 if (iGLow == m_data->sinceGroups.end()) {
0373
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
0384 fetchSequence(lowG, highG);
0385 }
0386
0387
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
0398 retVal.till = m_data->tagInfo.endOfValidity;
0399
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 }
0444
0445 }