Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:52

0001 // -*- C++ -*-
0002 //
0003 // Package:     Framework
0004 // Class  :     DependentRecordIntervalFinder
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Author:      Chris Jones
0010 // Created:     Sat Apr 30 19:37:22 EDT 2005
0011 //
0012 
0013 #include "FWCore/Framework/interface/DependentRecordIntervalFinder.h"
0014 #include "FWCore/Framework/interface/EventSetupRecordProvider.h"
0015 #include "FWCore/Utilities/interface/EDMException.h"
0016 
0017 #include <cassert>
0018 
0019 namespace edm {
0020   namespace eventsetup {
0021 
0022     DependentRecordIntervalFinder::DependentRecordIntervalFinder(const EventSetupRecordKey& iKey) : providers_() {
0023       findingRecordWithKey(iKey);
0024     }
0025 
0026     DependentRecordIntervalFinder::~DependentRecordIntervalFinder() {}
0027 
0028     void DependentRecordIntervalFinder::addProviderWeAreDependentOn(
0029         std::shared_ptr<EventSetupRecordProvider> iProvider) {
0030       providers_.push_back(iProvider);
0031     }
0032 
0033     void DependentRecordIntervalFinder::setAlternateFinder(std::shared_ptr<EventSetupRecordIntervalFinder> iOther) {
0034       alternate_ = iOther;
0035     }
0036 
0037     void DependentRecordIntervalFinder::setIntervalFor(const EventSetupRecordKey& iKey,
0038                                                        const IOVSyncValue& iTime,
0039                                                        ValidityInterval& oInterval) {
0040       //NOTE: oInterval is the last value that was used so if nothing changed do not modify oInterval
0041 
0042       //I am assuming that an invalidTime is always less then the first valid time
0043       assert(IOVSyncValue::invalidIOVSyncValue() < IOVSyncValue::beginOfTime());
0044       if (providers_.empty() && alternate_.get() == nullptr) {
0045         oInterval = ValidityInterval::invalidInterval();
0046         return;
0047       }
0048       bool haveAValidDependentRecord = false;
0049       bool allRecordsValid = true;
0050       ValidityInterval newInterval(IOVSyncValue::beginOfTime(), IOVSyncValue::endOfTime());
0051 
0052       if (alternate_.get() != nullptr) {
0053         ValidityInterval test = alternate_->findIntervalFor(iKey, iTime);
0054         if (test != ValidityInterval::invalidInterval()) {
0055           haveAValidDependentRecord = true;
0056           newInterval = test;
0057         }
0058       }
0059       bool intervalsWereComparible = true;
0060       for (Providers::iterator itProvider = providers_.begin(), itProviderEnd = providers_.end();
0061            itProvider != itProviderEnd;
0062            ++itProvider) {
0063         if ((*itProvider)->setValidityIntervalFor(iTime)) {
0064           haveAValidDependentRecord = true;
0065           ValidityInterval providerInterval = (*itProvider)->validityInterval();
0066           if ((!newInterval.first().comparable(providerInterval.first())) ||
0067               (!newInterval.last().comparable(providerInterval.last()))) {
0068             intervalsWereComparible = false;
0069             break;
0070           }
0071           if (newInterval.first() < providerInterval.first()) {
0072             newInterval.setFirst(providerInterval.first());
0073           }
0074           if (newInterval.last() > providerInterval.last()) {
0075             newInterval.setLast(providerInterval.last());
0076           }
0077         } else {
0078           allRecordsValid = false;
0079         }
0080       }
0081       if (intervalsWereComparible) {
0082         if (!haveAValidDependentRecord) {
0083           //If no Finder has no valid time, then this record is also invalid for this time
0084           newInterval = ValidityInterval::invalidInterval();
0085         }
0086         if (!allRecordsValid) {
0087           //since some of the dependent providers do not have a valid IOV for this syncvalue
0088           // we do not know what the true end IOV is.  Therefore we must make it open ended
0089           // so that we can check each time to see if those providers become valid.
0090           newInterval.setLast(IOVSyncValue::invalidIOVSyncValue());
0091         }
0092         oInterval = newInterval;
0093         return;
0094       }
0095       //handle the case where some providers use time and others use run/lumi/event
0096       // in this case all we can do is find an IOV which changed since last time
0097       // and use its start time to do the synching and use an 'invalid' end time
0098       // so the system always checks back to see if something has changed
0099       if (previousIOVs_.empty()) {
0100         std::vector<ValidityInterval> tmp(providers_.size(), ValidityInterval());
0101         previousIOVs_.swap(tmp);
0102       }
0103 
0104       //I'm using an heuristic to pick a reasonable starting point for the IOV. The idea is to
0105       // assume that lumi sections are 23 seconds long and therefore if we take a difference between
0106       // iTime and the beginning of a changed IOV we can pick the changed IOV with the start time
0107       // closest to iTime. This doesn't have to be perfect, we just want to reduce the dependency
0108       // on provider order to make the jobs more deterministic
0109 
0110       bool hadChangedIOV = false;
0111       //both start at the smallest value
0112       EventID closestID;
0113       Timestamp closestTimeStamp(0);
0114       std::vector<ValidityInterval>::iterator itIOVs = previousIOVs_.begin();
0115       for (Providers::iterator itProvider = providers_.begin(), itProviderEnd = providers_.end();
0116            itProvider != itProviderEnd;
0117            ++itProvider, ++itIOVs) {
0118         if ((*itProvider)->setValidityIntervalFor(iTime)) {
0119           ValidityInterval providerInterval = (*itProvider)->validityInterval();
0120           if (*itIOVs != providerInterval) {
0121             hadChangedIOV = true;
0122             if (providerInterval.first().time().value() == 0) {
0123               //this is a run/lumi based one
0124               if (closestID < providerInterval.first().eventID()) {
0125                 closestID = providerInterval.first().eventID();
0126               }
0127             } else {
0128               if (closestTimeStamp < providerInterval.first().time()) {
0129                 closestTimeStamp = providerInterval.first().time();
0130               }
0131             }
0132             *itIOVs = providerInterval;
0133           }
0134         }
0135       }
0136       if (hadChangedIOV) {
0137         if (closestID.run() != 0) {
0138           if (closestTimeStamp.value() == 0) {
0139             //no time
0140             oInterval = ValidityInterval(IOVSyncValue(closestID), IOVSyncValue::invalidIOVSyncValue());
0141           } else {
0142             if (closestID.run() == iTime.eventID().run()) {
0143               //can compare time to lumi
0144               const unsigned long long kLumiTimeLength = 23;
0145 
0146               if ((iTime.eventID().luminosityBlock() - closestID.luminosityBlock()) * kLumiTimeLength <
0147                   iTime.time().unixTime() - closestTimeStamp.unixTime()) {
0148                 //closestID was closer
0149                 oInterval = ValidityInterval(IOVSyncValue(closestID), IOVSyncValue::invalidIOVSyncValue());
0150               } else {
0151                 oInterval = ValidityInterval(IOVSyncValue(closestTimeStamp), IOVSyncValue::invalidIOVSyncValue());
0152               }
0153             } else {
0154               //since we don't know how to change run # into time we can't compare
0155               // so if we have a time just use it
0156               oInterval = ValidityInterval(IOVSyncValue(closestTimeStamp), IOVSyncValue::invalidIOVSyncValue());
0157             }
0158           }
0159         } else {
0160           oInterval = ValidityInterval(IOVSyncValue(closestTimeStamp), IOVSyncValue::invalidIOVSyncValue());
0161         }
0162       }
0163     }
0164 
0165     void DependentRecordIntervalFinder::doResetInterval(const eventsetup::EventSetupRecordKey& key) {
0166       if (alternate_.get()) {
0167         alternate_->resetInterval(key);
0168       }
0169       previousIOVs_.clear();
0170     }
0171 
0172     bool DependentRecordIntervalFinder::isConcurrentFinder() const {
0173       throw Exception(errors::LogicError)
0174           << "DependentRecordIntervalFinder::isConcurrentFinder() should never be called.\n"
0175           << "Contact a Framework developer\n";
0176       return true;
0177     }
0178 
0179     bool DependentRecordIntervalFinder::isNonconcurrentAndIOVNeedsUpdate(const EventSetupRecordKey& iKey,
0180                                                                          const IOVSyncValue& iTime) const {
0181       // Note that we do not worry about dependent records here because this function
0182       // will get called once for every record and we would just be checking the
0183       // dependent records multiple times if we checked them inside this function.
0184       if (alternate_.get()) {
0185         return alternate_->nonconcurrentAndIOVNeedsUpdate(iKey, iTime);
0186       }
0187       return false;
0188     }
0189 
0190   }  // namespace eventsetup
0191 }  // namespace edm