Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-05-08 02:39:31

0001 #include "CondCore/CondDB/interface/IOVEditor.h"
0002 #include "CondCore/CondDB/interface/Auth.h"
0003 #include "CondCore/CondDB/interface/Utils.h"
0004 #include "SessionImpl.h"
0005 //
0006 
0007 namespace cond {
0008 
0009   namespace persistency {
0010 
0011     // implementation details. holds only data.
0012     class IOVEditorData {
0013     public:
0014       explicit IOVEditorData()
0015           : tag(""),
0016             timeType(cond::invalid),
0017             payloadType(""),
0018             synchronizationType(cond::SYNCH_ANY),
0019             description(""),
0020             iovBuffer(),
0021             deleteBuffer(),
0022             changes() {}
0023       std::string tag;
0024       cond::TimeType timeType;
0025       std::string payloadType;
0026       cond::SynchronizationType synchronizationType;
0027       std::string description;
0028       cond::Time_t endOfValidity = cond::time::MAX_VAL;
0029       cond::Time_t lastValidatedTime = cond::time::MIN_VAL;
0030       boost::posix_time::ptime creationTime;
0031       bool change = false;
0032       bool metadataChange = false;
0033       bool exists = false;
0034       // buffer for the iov sequence
0035       std::vector<std::tuple<cond::Time_t, cond::Hash, boost::posix_time::ptime> > iovBuffer;
0036       std::vector<std::tuple<cond::Time_t, cond::Hash> > deleteBuffer;
0037       std::set<std::string> changes;
0038       int protectionCode = 0;
0039     };
0040 
0041     IOVEditor::IOVEditor() : m_data(), m_session() {}
0042 
0043     IOVEditor::IOVEditor(const std::shared_ptr<SessionImpl>& session) : m_data(new IOVEditorData), m_session(session) {}
0044 
0045     IOVEditor::IOVEditor(const std::shared_ptr<SessionImpl>& session,
0046                          const std::string& tag,
0047                          cond::TimeType timeType,
0048                          const std::string& payloadObjectType,
0049                          cond::SynchronizationType synchronizationType,
0050                          const boost::posix_time::ptime& creationTime)
0051         : m_data(new IOVEditorData), m_session(session) {
0052       m_data->tag = tag;
0053       m_data->timeType = timeType;
0054       m_data->payloadType = payloadObjectType;
0055       m_data->synchronizationType = synchronizationType;
0056       m_data->creationTime = creationTime;
0057       m_data->change = true;
0058       m_data->metadataChange = true;
0059     }
0060 
0061     IOVEditor::IOVEditor(const IOVEditor& rhs) : m_data(rhs.m_data), m_session(rhs.m_session) {}
0062 
0063     IOVEditor::~IOVEditor() {}
0064 
0065     IOVEditor& IOVEditor::operator=(const IOVEditor& rhs) {
0066       m_data = rhs.m_data;
0067       m_session = rhs.m_session;
0068       return *this;
0069     }
0070 
0071     void IOVEditor::load(const std::string& tag) {
0072       checkTransaction("IOVEditor::load");
0073       // loads the current header data in memory
0074       if (!m_session->iovSchema().tagTable().select(tag,
0075                                                     m_data->timeType,
0076                                                     m_data->payloadType,
0077                                                     m_data->synchronizationType,
0078                                                     m_data->endOfValidity,
0079                                                     m_data->lastValidatedTime,
0080                                                     m_data->protectionCode)) {
0081         cond::throwException("Tag \"" + tag + "\" has not been found in the database.", "IOVEditor::load");
0082       }
0083       if (m_data->protectionCode) {
0084         if (m_data->protectionCode & cond::auth::COND_DBTAG_WRITE_ACCESS_CODE) {
0085           bool writeAllowed = m_session->iovSchema().tagAccessPermissionTable().getAccessPermission(
0086               tag,
0087               m_session->principalName,
0088               cond::auth::COND_DBKEY_CREDENTIAL_CODE,
0089               cond::auth::COND_DBTAG_WRITE_ACCESS_CODE);
0090           if (!writeAllowed)
0091             cond::throwException(
0092                 "Tag \"" + tag + "\" can't be accessed for update by db-user \"" + m_session->principalName + "\".",
0093                 "IOVEditor::load");
0094         }
0095         if (m_data->protectionCode & cond::auth::COND_DBTAG_LOCK_ACCESS_CODE) {
0096           bool mylock = m_session->iovSchema().tagAccessPermissionTable().getAccessPermission(
0097               tag, m_session->sessionHash, cond::auth::COND_SESSION_HASH_CODE, cond::auth::COND_DBTAG_LOCK_ACCESS_CODE);
0098           if (!mylock)
0099             cond::throwException(
0100                 "Tag \"" + tag + "\" can't be accessed for update, because it has been locked by an other session.",
0101                 "IOVEditor::load");
0102         }
0103       }
0104       m_data->tag = tag;
0105       m_data->exists = true;
0106       m_data->change = false;
0107     }
0108 
0109     std::string IOVEditor::tag() const { return m_data.get() ? m_data->tag : ""; }
0110 
0111     cond::TimeType IOVEditor::timeType() const { return m_data.get() ? m_data->timeType : cond::invalid; }
0112 
0113     std::string IOVEditor::payloadType() const { return m_data.get() ? m_data->payloadType : ""; }
0114 
0115     cond::SynchronizationType IOVEditor::synchronizationType() const {
0116       return m_data.get() ? m_data->synchronizationType : cond::SYNCH_ANY;
0117     }
0118 
0119     void IOVEditor::setSynchronizationType(cond::SynchronizationType synchronizationType) {
0120       if (m_data.get()) {
0121         m_data->synchronizationType = synchronizationType;
0122         m_data->change = true;
0123         m_data->changes.insert("SynchronizationType");
0124       }
0125     }
0126 
0127     cond::Time_t IOVEditor::endOfValidity() const { return m_data.get() ? m_data->endOfValidity : cond::time::MIN_VAL; }
0128 
0129     void IOVEditor::setEndOfValidity(cond::Time_t time) {
0130       if (m_data.get()) {
0131         m_data->endOfValidity = time;
0132         m_data->change = true;
0133         m_data->changes.insert("EndOfValidity");
0134       }
0135     }
0136 
0137     std::string IOVEditor::description() const { return m_data.get() ? m_data->description : ""; }
0138 
0139     void IOVEditor::setDescription(const std::string& description) {
0140       if (m_data.get()) {
0141         m_data->description = description;
0142         m_data->metadataChange = true;
0143         m_data->changes.insert("Description");
0144       }
0145     }
0146 
0147     cond::Time_t IOVEditor::lastValidatedTime() const {
0148       return m_data.get() ? m_data->lastValidatedTime : cond::time::MIN_VAL;
0149     }
0150 
0151     void IOVEditor::setLastValidatedTime(cond::Time_t time) {
0152       if (m_data.get()) {
0153         m_data->lastValidatedTime = time;
0154         m_data->change = true;
0155         m_data->changes.insert("LastValidatedTime");
0156       }
0157     }
0158 
0159     void IOVEditor::insert(cond::Time_t since, const cond::Hash& payloadHash, bool checkType) {
0160       boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
0161       insert(since, payloadHash, now, checkType);
0162     }
0163 
0164     void IOVEditor::insert(cond::Time_t since,
0165                            const cond::Hash& payloadHash,
0166                            const boost::posix_time::ptime& insertionTime,
0167                            bool) {
0168       if (m_data.get()) {
0169         // here the type check could be added
0170         m_data->iovBuffer.push_back(std::tie(since, payloadHash, insertionTime));
0171       }
0172     }
0173 
0174     void IOVEditor::erase(cond::Time_t since, const cond::Hash& payloadHash) {
0175       if (m_data.get()) {
0176         m_data->deleteBuffer.push_back(std::tie(since, payloadHash));
0177       }
0178     }
0179 
0180     bool iovSorter(const std::tuple<cond::Time_t, cond::Hash, boost::posix_time::ptime>& f,
0181                    const std::tuple<cond::Time_t, cond::Hash, boost::posix_time::ptime>& s) {
0182       return std::get<0>(f) < std::get<0>(s);
0183     }
0184 
0185     bool IOVEditor::flush(const std::string& logText,
0186                           const boost::posix_time::ptime& operationTime,
0187                           bool forceInsertion) {
0188       bool ret = false;
0189       checkTransaction("IOVEditor::flush");
0190       std::string lt = logText;
0191       if (lt.empty())
0192         lt = "-";
0193       if (m_data->change || m_data->metadataChange) {
0194         if (m_data->metadataChange && m_data->description.empty())
0195           throwException("A non-empty description string is mandatory.", "IOVEditor::flush");
0196         //if (m_data->validationMode)
0197         //  m_session->iovSchema().tagTable().setValidationMode();
0198         if (!m_data->exists) {
0199           // set the creation time ( only available in the migration from v1...)
0200           if (m_data->creationTime.is_not_a_date_time())
0201             m_data->creationTime = operationTime;
0202           m_session->iovSchema().tagTable().insert(m_data->tag,
0203                                                    m_data->timeType,
0204                                                    m_data->payloadType,
0205                                                    m_data->synchronizationType,
0206                                                    m_data->endOfValidity,
0207                                                    m_data->description,
0208                                                    m_data->lastValidatedTime,
0209                                                    m_data->creationTime);
0210           if (m_session->iovSchema().tagLogTable().exists())
0211             m_session->iovSchema().tagLogTable().insert(m_data->tag,
0212                                                         m_data->creationTime,
0213                                                         cond::getUserName(),
0214                                                         cond::getHostName(),
0215                                                         cond::getCommand(),
0216                                                         std::string("New tag created."),
0217                                                         lt);
0218           m_data->exists = true;
0219           ret = true;
0220         } else {
0221           if (m_data->change) {
0222             m_session->iovSchema().tagTable().update(m_data->tag,
0223                                                      m_data->synchronizationType,
0224                                                      m_data->endOfValidity,
0225                                                      m_data->lastValidatedTime,
0226                                                      operationTime);
0227           }
0228           if (m_data->metadataChange) {
0229             m_session->iovSchema().tagTable().updateMetadata(m_data->tag, m_data->description, operationTime);
0230           }
0231           if (m_session->iovSchema().tagLogTable().exists()) {
0232             std::string action("Tag header updated. Changes involve: ");
0233             size_t i = 0;
0234             for (const auto& c : m_data->changes) {
0235               action += c;
0236               if (i == (m_data->changes.size() - 1))
0237                 action += ".";
0238               else
0239                 action += ", ";
0240               i++;
0241             }
0242             m_session->iovSchema().tagLogTable().insert(
0243                 m_data->tag, operationTime, cond::getUserName(), cond::getHostName(), cond::getCommand(), action, lt);
0244           }
0245           ret = true;
0246         }
0247         m_data->change = false;
0248       }
0249       if (!m_data->iovBuffer.empty()) {
0250         std::sort(m_data->iovBuffer.begin(), m_data->iovBuffer.end(), iovSorter);
0251         cond::Time_t l = std::get<0>(m_data->iovBuffer.front());
0252         //We do not allow for IOV updates (i.e. insertion in the past or overriding) on tags whose syncrosization is not "ANY" or "VALIDATION".
0253         //This policy is stricter than the one deployed in the Condition Upload service,
0254         //which allows insertions in the past or overriding for IOVs larger than the first condition safe run for HLT ("HLT"/"EXPRESS" synchronizations) and Tier0 ("PROMPT"/"PCL").
0255         //This is intended: in the C++ API we have no way to determine the first condition safe runs.
0256         if (!forceInsertion && m_data->synchronizationType != cond::SYNCH_ANY &&
0257             m_data->synchronizationType != cond::SYNCH_VALIDATION) {
0258           // retrieve the last since
0259           cond::Time_t last = 0;
0260           cond::Hash h;
0261           boost::posix_time::ptime no_time;
0262           m_session->iovSchema().iovTable().getLastIov(m_data->tag, no_time, last, h);
0263           // check if the min iov is greater then the last since
0264           if (l <= last) {
0265             std::stringstream msg;
0266             msg << "Can't insert iov since " << l << " on the tag " << m_data->tag << ": last since is " << last
0267                 << " and synchronization is \"" << cond::synchronizationTypeNames(m_data->synchronizationType) << "\"";
0268             throwException(msg.str(), "IOVEditor::flush");
0269           }
0270         }
0271         // set the insertion time ( only for the migration from v1 will be available... )
0272         for (auto& iov : m_data->iovBuffer) {
0273           boost::posix_time::ptime& insertionTime = std::get<2>(iov);
0274           if (insertionTime.is_not_a_date_time())
0275             insertionTime = operationTime;
0276         }
0277         // insert the new iovs
0278         m_session->iovSchema().iovTable().insertMany(m_data->tag, m_data->iovBuffer);
0279         ret = true;
0280       }
0281       if (!m_data->deleteBuffer.empty()) {
0282         // delete the specified iovs
0283         m_session->iovSchema().iovTable().eraseMany(m_data->tag, m_data->deleteBuffer);
0284         ret = true;
0285       }
0286       if (m_session->iovSchema().tagLogTable().exists()) {
0287         std::stringstream msg;
0288         if (!m_data->iovBuffer.empty())
0289           msg << m_data->iovBuffer.size() << " iov(s) inserted";
0290         if (!msg.str().empty())
0291           msg << "; ";
0292         else
0293           msg << ".";
0294         if (!m_data->deleteBuffer.empty())
0295           msg << m_data->deleteBuffer.size() << " iov(s) deleted.";
0296         if (ret) {
0297           m_session->iovSchema().tagLogTable().insert(
0298               m_data->tag, operationTime, cond::getUserName(), cond::getHostName(), cond::getCommand(), msg.str(), lt);
0299         }
0300       }
0301       m_data->iovBuffer.clear();
0302       m_data->deleteBuffer.clear();
0303       m_data->changes.clear();
0304       return ret;
0305     }
0306 
0307     bool IOVEditor::flush(const std::string& logText) {
0308       return flush(logText, boost::posix_time::microsec_clock::universal_time(), false);
0309     }
0310 
0311     bool IOVEditor::flush(const boost::posix_time::ptime& operationTime) {
0312       return flush(std::string("-"), operationTime, false);
0313     }
0314 
0315     bool IOVEditor::flush() {
0316       return flush(std::string("-"), boost::posix_time::microsec_clock::universal_time(), false);
0317     }
0318 
0319     bool IOVEditor::flush(const std::string& logText, bool forceInsertion) {
0320       return flush(logText, boost::posix_time::microsec_clock::universal_time(), forceInsertion);
0321     }
0322 
0323     bool IOVEditor::isLocked() const { return m_data->protectionCode & cond::auth::COND_DBTAG_LOCK_ACCESS_CODE; }
0324 
0325     void IOVEditor::lock() {
0326       if (isLocked())
0327         return;
0328       checkTransaction("IOVEditor::lock");
0329       m_session->iovSchema().tagAccessPermissionTable().setAccessPermission(m_data->tag,
0330                                                                             m_session->sessionHash,
0331                                                                             cond::auth::COND_SESSION_HASH_CODE,
0332                                                                             cond::auth::COND_DBTAG_LOCK_ACCESS_CODE);
0333       m_data->protectionCode |= cond::auth::COND_DBTAG_LOCK_ACCESS_CODE;
0334       m_session->iovSchema().tagTable().setProtectionCode(m_data->tag, cond::auth::COND_DBTAG_LOCK_ACCESS_CODE);
0335       m_session->lockedTags.insert(m_data->tag);
0336       std::string lt("-");
0337       std::string action("Lock set by session ");
0338       action += m_session->sessionHash;
0339       m_session->iovSchema().tagLogTable().insert(m_data->tag,
0340                                                   boost::posix_time::microsec_clock::universal_time(),
0341                                                   cond::getUserName(),
0342                                                   cond::getHostName(),
0343                                                   cond::getCommand(),
0344                                                   action,
0345                                                   lt);
0346     }
0347 
0348     void IOVEditor::unlock() {
0349       if (!isLocked())
0350         return;
0351       checkTransaction("IOVEditor::unlock");
0352       m_session->iovSchema().tagAccessPermissionTable().removeAccessPermission(
0353           m_data->tag, m_session->sessionHash, cond::auth::COND_SESSION_HASH_CODE);
0354       m_data->protectionCode &= cond::auth::COND_DBTAG_WRITE_ACCESS_CODE;
0355       m_session->iovSchema().tagTable().unsetProtectionCode(m_data->tag, cond::auth::COND_DBTAG_LOCK_ACCESS_CODE);
0356       m_session->lockedTags.erase(m_data->tag);
0357       std::string lt("-");
0358       std::string action("Lock released by session ");
0359       action += m_session->sessionHash;
0360       m_session->iovSchema().tagLogTable().insert(m_data->tag,
0361                                                   boost::posix_time::microsec_clock::universal_time(),
0362                                                   cond::getUserName(),
0363                                                   cond::getHostName(),
0364                                                   cond::getCommand(),
0365                                                   action,
0366                                                   lt);
0367     }
0368 
0369     void IOVEditor::checkTransaction(const std::string& ctx) {
0370       if (!m_session.get())
0371         throwException("The session is not active.", ctx);
0372       if (!m_session->isTransactionActive(false))
0373         throwException("The transaction is not active.", ctx);
0374     }
0375 
0376   }  // namespace persistency
0377 }  // namespace cond