diff --git a/CondCore/CondDB/interface/KeyList.h b/CondCore/CondDB/interface/KeyList.h index e014ab44f00d1..84907980af764 100644 --- a/CondCore/CondDB/interface/KeyList.h +++ b/CondCore/CondDB/interface/KeyList.h @@ -32,6 +32,7 @@ namespace cond { class KeyList { public: void init(IOVProxy iovProxy); + void init(KeyList const&); void load(const std::vector& keys); diff --git a/CondCore/CondDB/interface/KeyListProxy.h b/CondCore/CondDB/interface/KeyListProxy.h index f00d81a100831..ae0b217bba154 100644 --- a/CondCore/CondDB/interface/KeyListProxy.h +++ b/CondCore/CondDB/interface/KeyListProxy.h @@ -3,30 +3,40 @@ #include "CondCore/CondDB/interface/PayloadProxy.h" #include "CondCore/CondDB/interface/KeyList.h" +#include #include #include namespace cond { + struct Iov_t; + namespace persistency { + + class Session; + template <> - class PayloadProxy : public PayloadProxy > { + class PayloadProxy : public PayloadProxy> { public: typedef std::vector DataT; typedef PayloadProxy super; - explicit PayloadProxy(const char* source = nullptr) : super(source), m_keyList() { + explicit PayloadProxy(Iov_t const* mostRecentCurrentIov, + Session const* mostRecentSession, + std::shared_ptr> const* mostRecentRequests, + const char* source = nullptr) + : super(mostRecentCurrentIov, mostRecentSession, mostRecentRequests, source), m_keyList() { if (source) m_name = source; } ~PayloadProxy() override {} + void initKeyList(PayloadProxy const& originalPayloadProxy) { m_keyList.init(originalPayloadProxy.m_keyList); } + // dereference (does not load) const KeyList& operator()() const { return m_keyList; } - void invalidateCache() override { super::invalidateCache(); } - void loadMore(CondGetter const& getter) override { m_keyList.init(getter.get(m_name)); } protected: diff --git a/CondCore/CondDB/interface/PayloadProxy.h b/CondCore/CondDB/interface/PayloadProxy.h index ba0a02bdc13e7..e9fc6fbb2f7de 100644 --- a/CondCore/CondDB/interface/PayloadProxy.h +++ b/CondCore/CondDB/interface/PayloadProxy.h @@ -1,8 +1,14 @@ #ifndef CondCore_CondDB_PayloadProxy_h #define CondCore_CondDB_PayloadProxy_h +#include "CondCore/CondDB/interface/Exception.h" +#include "CondCore/CondDB/interface/IOVProxy.h" #include "CondCore/CondDB/interface/Session.h" -#include "CondCore/CondDB/interface/Time.h" +#include "CondCore/CondDB/interface/Types.h" + +#include +#include +#include namespace cond { @@ -21,58 +27,49 @@ namespace cond { class BasePayloadProxy { public: // - BasePayloadProxy(); - - void setUp(Session dbSession); - - void loadTag(const std::string& tag); - - void loadTag(const std::string& tag, const boost::posix_time::ptime& snapshotTime); - - void reload(); + BasePayloadProxy(Iov_t const* mostRecentCurrentIov, + Session const* mostRecentSession, + std::shared_ptr> const* mostRecentRequests); virtual ~BasePayloadProxy(); virtual void make() = 0; - virtual void invalidateCache() = 0; - - // current cached object token - const Hash& payloadId() const { return m_currentIov.payloadId; } - - // this one had the loading in a separate function in the previous impl - ValidityInterval setIntervalFor(Time_t target, bool loadPayload = false); - bool isValid() const; - TimeType timeType() const { return m_iovProxy.timeType(); } - virtual void loadMore(CondGetter const&) {} - IOVProxy iov(); - - const std::vector& requests() const { return m_requests; } + void initializeForNewIOV(); private: virtual void loadPayload() = 0; protected: - IOVProxy m_iovProxy; - Iov_t m_currentIov; + Iov_t m_iovAtInitialization; Session m_session; - std::vector m_requests; + std::shared_ptr> m_requests; + + Iov_t const* m_mostRecentCurrentIov; + Session const* m_mostRecentSession; + std::shared_ptr> const* m_mostRecentRequests; }; /* proxy to the payload valid at a given time... - + */ template class PayloadProxy : public BasePayloadProxy { public: - explicit PayloadProxy(const char* source = nullptr) : BasePayloadProxy() {} + explicit PayloadProxy(Iov_t const* mostRecentCurrentIov, + Session const* mostRecentSession, + std::shared_ptr> const* mostRecentRequests, + const char* source = nullptr) + : BasePayloadProxy(mostRecentCurrentIov, mostRecentSession, mostRecentRequests) {} ~PayloadProxy() override {} + void initKeyList(PayloadProxy const&) {} + // dereference const DataT& operator()() const { if (!m_data) { @@ -83,7 +80,7 @@ namespace cond { void make() override { if (isValid()) { - if (m_currentIov.payloadId == m_currentPayloadId) + if (m_iovAtInitialization.payloadId == m_currentPayloadId) return; m_session.transaction().start(true); loadPayload(); @@ -91,30 +88,18 @@ namespace cond { } } - virtual void invalidateTransientCache() { - m_data.reset(); - m_currentPayloadId.clear(); - } - - void invalidateCache() override { - m_data.reset(); - m_currentPayloadId.clear(); - m_currentIov.clear(); - m_requests.clear(); - } - protected: void loadPayload() override { - if (m_currentIov.payloadId.empty()) { + if (m_iovAtInitialization.payloadId.empty()) { throwException("Can't load payload: no valid IOV found.", "PayloadProxy::loadPayload"); } - m_data = m_session.fetchPayload(m_currentIov.payloadId); - m_currentPayloadId = m_currentIov.payloadId; - m_requests.push_back(m_currentIov); + m_data = m_session.fetchPayload(m_iovAtInitialization.payloadId); + m_currentPayloadId = m_iovAtInitialization.payloadId; + m_requests->push_back(m_iovAtInitialization); } private: - std::shared_ptr m_data; + std::unique_ptr m_data; Hash m_currentPayloadId; }; diff --git a/CondCore/CondDB/src/KeyList.cc b/CondCore/CondDB/src/KeyList.cc index df82b6154dbee..166766c13aaa6 100644 --- a/CondCore/CondDB/src/KeyList.cc +++ b/CondCore/CondDB/src/KeyList.cc @@ -11,6 +11,8 @@ namespace cond { m_objects.clear(); } + void KeyList::init(KeyList const& originalKeyList) { init(originalKeyList.m_proxy); } + void KeyList::load(const std::vector& keys) { std::shared_ptr simpl = m_proxy.session(); if (!simpl.get()) diff --git a/CondCore/CondDB/src/PayloadProxy.cc b/CondCore/CondDB/src/PayloadProxy.cc index bfdb9fac35e4e..4a1b047b4465b 100644 --- a/CondCore/CondDB/src/PayloadProxy.cc +++ b/CondCore/CondDB/src/PayloadProxy.cc @@ -4,53 +4,22 @@ namespace cond { namespace persistency { - BasePayloadProxy::BasePayloadProxy() : m_iovProxy(), m_session() {} + BasePayloadProxy::BasePayloadProxy(Iov_t const* mostRecentCurrentIov, + Session const* mostRecentSession, + std::shared_ptr> const* mostRecentRequests) + : m_mostRecentCurrentIov(mostRecentCurrentIov), + m_mostRecentSession(mostRecentSession), + m_mostRecentRequests(mostRecentRequests) {} BasePayloadProxy::~BasePayloadProxy() {} - void BasePayloadProxy::setUp(Session dbSession) { - m_session = dbSession; - invalidateCache(); - } - - void BasePayloadProxy::loadTag(const std::string& tag) { - m_session.transaction().start(true); - m_iovProxy = m_session.readIov(tag); - m_session.transaction().commit(); - invalidateCache(); - } - - void BasePayloadProxy::loadTag(const std::string& tag, const boost::posix_time::ptime& snapshotTime) { - m_session.transaction().start(true); - m_iovProxy = m_session.readIov(tag, snapshotTime); - m_session.transaction().commit(); - invalidateCache(); - } + bool BasePayloadProxy::isValid() const { return m_iovAtInitialization.isValid(); } - void BasePayloadProxy::reload() { - std::string tag = m_iovProxy.tag(); - if (!tag.empty()) - loadTag(tag); + void BasePayloadProxy::initializeForNewIOV() { + m_iovAtInitialization = *m_mostRecentCurrentIov; + m_session = *m_mostRecentSession; + m_requests = *m_mostRecentRequests; } - ValidityInterval BasePayloadProxy::setIntervalFor(cond::Time_t time, bool load) { - if (!m_currentIov.isValidFor(time)) { - m_currentIov.clear(); - m_session.transaction().start(true); - auto it = m_iovProxy.find(time); - if (it != m_iovProxy.end()) { - m_currentIov = *it; - if (load) - loadPayload(); - } - m_session.transaction().commit(); - } - return ValidityInterval(m_currentIov.since, m_currentIov.till); - } - - bool BasePayloadProxy::isValid() const { return m_currentIov.isValid(); } - - IOVProxy BasePayloadProxy::iov() { return m_iovProxy; } - } // namespace persistency } // namespace cond diff --git a/CondCore/CondDB/test/testConnectionPool.cpp b/CondCore/CondDB/test/testConnectionPool.cpp index e2a0a6d5ad724..b031c6c6380b1 100644 --- a/CondCore/CondDB/test/testConnectionPool.cpp +++ b/CondCore/CondDB/test/testConnectionPool.cpp @@ -6,6 +6,7 @@ //Module includes #include "CondCore/CondDB/interface/ConnectionPool.h" #include "CondCore/CondDB/interface/PayloadProxy.h" +#include "CondCore/CondDB/interface/Types.h" //Entity class #include "CondFormats/RunInfo/interface/RunInfo.h" //CORAL includes @@ -80,11 +81,24 @@ void testCreateCoralSession(cond::persistency::ConnectionPool& connPool, void testCreateSession(cond::persistency::ConnectionPool& connPool, std::string const& connectionString, bool const writeCapable) { + cond::Iov_t iov; cond::persistency::Session session = connPool.createSession(connectionString, writeCapable); - cond::persistency::PayloadProxy pp; - pp.setUp(session); - pp.loadTag("RunInfo_v1_mc"); - pp.setIntervalFor(1, true); + auto requests = std::make_shared>(); + cond::persistency::PayloadProxy pp(&iov, &session, &requests); + + session.transaction().start(true); + cond::persistency::IOVProxy iovProxy = session.readIov("RunInfo_v1_mc"); + session.transaction().commit(); + + session.transaction().start(true); + auto it = iovProxy.find(1); + if (it != iovProxy.end()) { + iov = *it; + } + session.transaction().commit(); + + pp.initializeForNewIOV(); + pp.make(); std::cout << "run number: " << pp().m_run << std::endl; } diff --git a/CondCore/CondDB/test/testFrontier.cpp b/CondCore/CondDB/test/testFrontier.cpp index 9ae4f08383e4f..4c577fbd094bf 100644 --- a/CondCore/CondDB/test/testFrontier.cpp +++ b/CondCore/CondDB/test/testFrontier.cpp @@ -4,7 +4,6 @@ #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" // #include "CondCore/CondDB/interface/ConnectionPool.h" -#include "CondCore/CondDB/interface/PayloadProxy.h" // #include "MyTestData.h" // diff --git a/CondCore/CondDB/test/testPayloadProxy.cpp b/CondCore/CondDB/test/testPayloadProxy.cpp index c244954b4eb67..f9820402b62d3 100644 --- a/CondCore/CondDB/test/testPayloadProxy.cpp +++ b/CondCore/CondDB/test/testPayloadProxy.cpp @@ -13,6 +13,19 @@ using namespace cond::persistency; +cond::ValidityInterval setIntervalFor(cond::persistency::Session& session, + cond::persistency::IOVProxy& iovProxy, + cond::Iov_t& iov, + cond::Time_t time) { + session.transaction().start(true); + auto it = iovProxy.find(time); + if (it != iovProxy.end()) { + iov = *it; + } + session.transaction().commit(); + return cond::ValidityInterval(iov.since, iov.till); +} + int main(int argc, char** argv) { edmplugin::PluginManager::Config config; edmplugin::PluginManager::configure(edmplugin::standard::config()); @@ -62,27 +75,44 @@ int main(int argc, char** argv) { std::cout << "# iov changes committed!..." << std::endl; ::sleep(2); - PayloadProxy pp0; - pp0.setUp(session); - PayloadProxy pp1; - pp1.setUp(session); + cond::Iov_t iov0; + auto requests0 = std::make_shared>(); + PayloadProxy pp0(&iov0, &session, &requests0); + + cond::Iov_t iov1; + auto requests1 = std::make_shared>(); + PayloadProxy pp1(&iov1, &session, &requests1); + + session.transaction().start(true); + cond::persistency::IOVProxy iovProxy0 = session.readIov("MyNewIOV2"); + session.transaction().commit(); + + cond::ValidityInterval v1 = setIntervalFor(session, iovProxy0, iov0, 25); + pp0.initializeForNewIOV(); + pp0.make(); - pp0.loadTag("MyNewIOV2"); - cond::ValidityInterval v1 = pp0.setIntervalFor(25, true); const MyTestData& rd0 = pp0(); if (rd0 != d0) { std::cout << "ERROR: MyTestData object read different from source." << std::endl; } else { std::cout << "MyTestData instance valid from " << v1.first << " to " << v1.second << std::endl; } - cond::ValidityInterval v2 = pp0.setIntervalFor(35, true); + + cond::ValidityInterval v2 = setIntervalFor(session, iovProxy0, iov0, 35); + pp0.initializeForNewIOV(); + pp0.make(); + const MyTestData& rd1 = pp0(); if (rd1 != d0) { std::cout << "ERROR: MyTestData object read different from source." << std::endl; } else { std::cout << "MyTestData instance valid from " << v2.first << " to " << v2.second << std::endl; } - cond::ValidityInterval v3 = pp0.setIntervalFor(100000, true); + + cond::ValidityInterval v3 = setIntervalFor(session, iovProxy0, iov0, 100000); + pp0.initializeForNewIOV(); + pp0.make(); + const MyTestData& rd2 = pp0(); if (rd2 != d1) { std::cout << "ERROR: MyTestData object read different from source." << std::endl; @@ -90,20 +120,29 @@ int main(int argc, char** argv) { std::cout << "MyTestData instance valid from " << v3.first << " to " << v3.second << std::endl; } - pp1.loadTag("StringData2"); + session.transaction().start(true); + cond::persistency::IOVProxy iovProxy1 = session.readIov("StringData2"); + session.transaction().commit(); + try { - pp1.setIntervalFor(345); + setIntervalFor(session, iovProxy1, iov1, 345); } catch (cond::persistency::Exception& e) { std::cout << "Expected error: " << e.what() << std::endl; } - cond::ValidityInterval vs1 = pp1.setIntervalFor(1000000, true); + + cond::ValidityInterval vs1 = setIntervalFor(session, iovProxy1, iov1, 1000000); + pp1.initializeForNewIOV(); + pp1.make(); const std::string& rd3 = pp1(); if (rd3 != d2) { std::cout << "ERROR: std::string object read different from source." << std::endl; } else { std::cout << "std::string instance valid from " << vs1.first << " to " << vs1.second << std::endl; } - cond::ValidityInterval vs2 = pp1.setIntervalFor(3000000, true); + + cond::ValidityInterval vs2 = setIntervalFor(session, iovProxy1, iov1, 3000000); + pp1.initializeForNewIOV(); + pp1.make(); const std::string& rd4 = pp1(); if (rd4 != d3) { std::cout << "ERROR: std::string object read different from source." << std::endl; @@ -111,15 +150,19 @@ int main(int argc, char** argv) { std::cout << "std::string instance valid from " << vs2.first << " to " << vs2.second << std::endl; } - PayloadProxy pp2; - pp2.setUp(session); - pp2.loadTag("StringData3"); + cond::Iov_t iov2; + auto requests2 = std::make_shared>(); + PayloadProxy pp2(&iov2, &session, &requests2); + + session.transaction().start(true); + cond::persistency::IOVProxy iovProxy2 = session.readIov("StringData3"); + session.transaction().commit(); + try { - pp2.setIntervalFor(4294967296); + setIntervalFor(session, iovProxy2, iov2, 4294967296); } catch (cond::persistency::Exception& e) { std::cout << "Expected error: " << e.what() << std::endl; } - } catch (const std::exception& e) { std::cout << "ERROR: " << e.what() << std::endl; return -1; diff --git a/CondCore/ESSources/interface/DataProxy.h b/CondCore/ESSources/interface/DataProxy.h index 897dc8921efb6..c2a1751270af0 100644 --- a/CondCore/ESSources/interface/DataProxy.h +++ b/CondCore/ESSources/interface/DataProxy.h @@ -1,5 +1,7 @@ #ifndef CondCore_ESSources_DataProxy_H #define CondCore_ESSources_DataProxy_H + +#include //#include #include #include @@ -7,7 +9,10 @@ // user include files #include "FWCore/Framework/interface/DataProxyTemplate.h" +#include "CondCore/CondDB/interface/IOVProxy.h" #include "CondCore/CondDB/interface/PayloadProxy.h" +#include "CondCore/CondDB/interface/Time.h" +#include "CondCore/CondDB/interface/Types.h" // expose a cond::PayloadProxy as a eventsetup::DataProxy namespace cond { @@ -17,13 +22,10 @@ namespace cond { }; } // namespace cond -template > +template > class DataProxy : public edm::eventsetup::DataProxyTemplate { public: - typedef DataProxy self; - typedef std::shared_ptr > DataP; - - explicit DataProxy(std::shared_ptr > pdata) : m_data(pdata) {} + explicit DataProxy(std::shared_ptr> pdata) : m_data(pdata) {} //virtual ~DataProxy(); // ---------- const member functions --------------------- @@ -42,14 +44,17 @@ class DataProxy : public edm::eventsetup::DataProxyTemplate { // don't, preserve data for future access // m_data->invalidateCache(); } - void invalidateTransientCache() override { m_data->invalidateTransientCache(); } + void invalidateTransientCache() override {} private: //DataProxy(); // stop default const DataProxy& operator=(const DataProxy&) = delete; // stop default + + void initializeForNewIOV() override { m_data->initializeForNewIOV(); } + // ---------- member data -------------------------------- - std::shared_ptr > m_data; + std::shared_ptr> m_data; Initializer m_initializer; }; @@ -67,57 +72,60 @@ namespace cond { typedef std::pair Args; virtual edm::eventsetup::TypeTag type() const = 0; - virtual ProxyP proxy() const = 0; - virtual edmProxyP edmProxy() const = 0; + virtual ProxyP proxy(unsigned int iovIndex) const = 0; + virtual edmProxyP edmProxy(unsigned int iovIndex) const = 0; DataProxyWrapperBase(); - explicit DataProxyWrapperBase(std::string const& il); // late initialize (to allow to load ALL library first) - virtual void lateInit(cond::persistency::Session& session, + virtual void lateInit(persistency::Session& session, const std::string& tag, const boost::posix_time::ptime& snapshotTime, std::string const& il, std::string const& cs) = 0; + virtual void initConcurrentIOVs(unsigned int nConcurrentIOVs) = 0; + void addInfo(std::string const& il, std::string const& cs, std::string const& tag); virtual ~DataProxyWrapperBase(); - std::string const& label() const { return m_label; } + std::string const& label() const { return m_label; } std::string const& connString() const { return m_connString; } std::string const& tag() const { return m_tag; } + persistency::IOVProxy& iovProxy() { return m_iovProxy; } + persistency::IOVProxy const& iovProxy() const { return m_iovProxy; } + Iov_t const& currentIov() const { return m_currentIov; } + persistency::Session& session() { return m_session; } + persistency::Session const& session() const { return m_session; } + std::shared_ptr> const& requests() const { return m_requests; } + + void setSession(persistency::Session const& v) { m_session = v; } + + void loadTag(std::string const& tag); + void loadTag(std::string const& tag, boost::posix_time::ptime const& snapshotTime); + void reload(); + + ValidityInterval setIntervalFor(Time_t target); + TimeType timeType() const { return m_iovProxy.timeType(); } private: std::string m_label; std::string m_connString; std::string m_tag; + persistency::IOVProxy m_iovProxy; + Iov_t m_currentIov; + persistency::Session m_session; + std::shared_ptr> m_requests; }; } // namespace cond /* bridge between the cond world and eventsetup world * keep them separated! */ -template > +template > class DataProxyWrapper : public cond::DataProxyWrapperBase { public: typedef ::DataProxy DataProxy; - typedef cond::persistency::PayloadProxy PayProxy; - typedef std::shared_ptr DataP; - - DataProxyWrapper(cond::persistency::Session& session, - const std::string& tag, - const std::string& ilabel, - const char* source = nullptr) - : cond::DataProxyWrapperBase(ilabel), - m_source(source ? source : ""), - //'errorPolicy set to true: PayloadProxy should catch and re-throw ORA exceptions' still needed? - m_proxy(new PayProxy(source)), - m_edmProxy(new DataProxy(m_proxy)) { - m_proxy->setUp(session); - //NOTE: We do this so that the type 'DataT' will get registered - // when the plugin is dynamically loaded - m_type = edm::eventsetup::DataKey::makeTypeTag(); - } // constructor from plugin... explicit DataProxyWrapper(const char* source = nullptr) : m_source(source ? source : "") { @@ -127,27 +135,49 @@ class DataProxyWrapper : public cond::DataProxyWrapperBase { } // late initialize (to allow to load ALL library first) - void lateInit(cond::persistency::Session& session, + void lateInit(cond::persistency::Session& iSession, const std::string& tag, const boost::posix_time::ptime& snapshotTime, std::string const& il, std::string const& cs) override { - m_proxy.reset(new PayProxy(m_source.empty() ? (const char*)nullptr : m_source.c_str())); - m_proxy->setUp(session); - m_proxy->loadTag(tag, snapshotTime); - m_edmProxy.reset(new DataProxy(m_proxy)); + setSession(iSession); + // set the IOVProxy + loadTag(tag, snapshotTime); + // Only make the first PayloadProxy object now because we don't know yet + // how many we will need. + m_proxies.push_back(std::make_shared>( + ¤tIov(), &session(), &requests(), m_source.empty() ? (const char*)nullptr : m_source.c_str())); + m_edmProxies.push_back(std::make_shared(m_proxies[0])); addInfo(il, cs, tag); } + void initConcurrentIOVs(unsigned int nConcurrentIOVs) override { + // Create additional PayloadProxy objects if we are allowing + // multiple IOVs to run concurrently. + if (m_proxies.size() != nConcurrentIOVs) { + assert(m_proxies.size() == 1); + for (unsigned int i = 1; i < nConcurrentIOVs; ++i) { + m_proxies.push_back(std::make_shared>( + ¤tIov(), &session(), &requests(), m_source.empty() ? (const char*)nullptr : m_source.c_str())); + m_edmProxies.push_back(std::make_shared(m_proxies[i])); + // This does nothing except in the special case of a KeyList PayloadProxy. + // They all need to have copies of the same IOVProxy object. + m_proxies[i]->initKeyList(*m_proxies[0]); + } + assert(m_proxies.size() == nConcurrentIOVs); + } + assert(m_proxies.size() == m_edmProxies.size()); + } + edm::eventsetup::TypeTag type() const override { return m_type; } - ProxyP proxy() const override { return m_proxy; } - edmProxyP edmProxy() const override { return m_edmProxy; } + ProxyP proxy(unsigned int iovIndex) const override { return m_proxies.at(iovIndex); } + edmProxyP edmProxy(unsigned int iovIndex) const override { return m_edmProxies.at(iovIndex); } private: std::string m_source; edm::eventsetup::TypeTag m_type; - std::shared_ptr > m_proxy; - edmProxyP m_edmProxy; + std::vector>> m_proxies; + std::vector m_edmProxies; }; #endif /* CONDCORE_PLUGINSYSTEM_DATAPROXY_H */ diff --git a/CondCore/ESSources/plugins/CondDBESSource.cc b/CondCore/ESSources/plugins/CondDBESSource.cc index 092cd7c748529..701d5054df043 100644 --- a/CondCore/ESSources/plugins/CondDBESSource.cc +++ b/CondCore/ESSources/plugins/CondDBESSource.cc @@ -52,7 +52,7 @@ namespace { cond::persistency::IOVProxy get(std::string name) const override { CondDBESSource::ProxyMap::const_iterator p = m_proxies.find(name); if (p != m_proxies.end()) - return (*p).second->proxy()->iov(); + return (*p).second->iovProxy(); return cond::persistency::IOVProxy(); } @@ -78,7 +78,7 @@ namespace { ; //if ( proxy.proxy()->stats.nLoad>0) { out << "Time look up, payloadIds:" << std::endl; - const auto& pids = proxy.proxy()->requests(); + const auto& pids = *proxy.requests(); for (auto id : pids) out << " " << id.since << " - " << id.till << " : " << id.payloadId << std::endl; } @@ -263,7 +263,7 @@ CondDBESSource::CondDBESSource(const edm::ParameterSet& iConfig) ProxyMap::iterator b = m_proxies.begin(); ProxyMap::iterator e = m_proxies.end(); for (; b != e; b++) { - (*b).second->proxy()->loadMore(visitor); + (*b).second->proxy(0)->loadMore(visitor); /// required by eventsetup EventSetupRecordKey recordKey(EventSetupRecordKey::TypeTag::findType((*b).first)); @@ -396,7 +396,7 @@ void CondDBESSource::setIntervalFor(const EventSetupRecordKey& iKey, << ", timestamp: " << iTime.time().value() << "; from CondDBESSource::setIntervalFor"; - timetype = (*pmIter).second->proxy()->timeType(); + timetype = (*pmIter).second->timeType(); cond::Time_t abtime = cond::time::fromIOVSyncValue(iTime, timetype); userTime = (0 == abtime); @@ -453,8 +453,8 @@ void CondDBESSource::setIntervalFor(const EventSetupRecordKey& iKey, << "\" from IOV tag \"" << tcIter->second.tagName() << "\" to be consumed by " << iTime.eventID() << ", timestamp: " << iTime.time().value() << "; from CondDBESSource::setIntervalFor"; - pmIter->second->proxy()->setUp(iSess->second.first); - pmIter->second->proxy()->reload(); + pmIter->second->session() = iSess->second.first; + pmIter->second->reload(); //if( isSizeIncreased ) //edm::LogInfo( "CondDBESSource" ) << "After reconnecting, an increased size of the IOV sequence labeled by tag \"" << tcIter->second.tag // << "\" was found; from CondDBESSource::setIntervalFor"; @@ -466,7 +466,7 @@ void CondDBESSource::setIntervalFor(const EventSetupRecordKey& iKey, << pmIter->second->label() << "\" to be consumed by " << iTime.eventID() << ", timestamp: " << iTime.time().value() << "; from CondDBESSource::setIntervalFor"; - pmIter->second->proxy()->reload(); + pmIter->second->reload(); //if( isSizeIncreased ) // edm::LogInfo( "CondDBESSource" ) << "After refreshing, an increased size of the IOV sequence labeled by tag \"" << tcIter->second.tag // << "\" was found; from CondDBESSource::setIntervalFor"; @@ -485,7 +485,7 @@ void CondDBESSource::setIntervalFor(const EventSetupRecordKey& iKey, */ //query the IOVSequence - cond::ValidityInterval validity = (*pmIter).second->proxy()->setIntervalFor(abtime); + cond::ValidityInterval validity = (*pmIter).second->setIntervalFor(abtime); edm::LogInfo("CondDBESSource") << "Validity coming from IOV sequence for record \"" << recordname << "\" and label \"" << pmIter->second->label() << "\": (" << validity.first << ", " @@ -528,7 +528,7 @@ void CondDBESSource::setIntervalFor(const EventSetupRecordKey& iKey, //required by EventSetup System edm::eventsetup::DataProxyProvider::KeyedProxiesVector CondDBESSource::registerProxies( - const EventSetupRecordKey& iRecordKey, unsigned int /* iovIndex */) { + const EventSetupRecordKey& iRecordKey, unsigned int iovIndex) { KeyedProxiesVector keyedProxiesVector; std::string recordname = iRecordKey.name(); @@ -545,12 +545,23 @@ edm::eventsetup::DataProxyProvider::KeyedProxiesVector CondDBESSource::registerP if (nullptr != (*p).second.get()) { edm::eventsetup::TypeTag type = (*p).second->type(); DataKey key(type, edm::eventsetup::IdTags((*p).second->label().c_str())); - keyedProxiesVector.emplace_back(key, (*p).second->edmProxy()); + keyedProxiesVector.emplace_back(key, (*p).second->edmProxy(iovIndex)); } } return keyedProxiesVector; } +void CondDBESSource::initConcurrentIOVs(const EventSetupRecordKey& key, unsigned int nConcurrentIOVs) { + std::string recordname = key.name(); + ProxyMap::const_iterator b = m_proxies.lower_bound(recordname); + ProxyMap::const_iterator e = m_proxies.upper_bound(recordname); + for (ProxyMap::const_iterator p = b; p != e; ++p) { + if (p->second) { + p->second->initConcurrentIOVs(nConcurrentIOVs); + } + } +} + // Fills tag collection from the given globaltag void CondDBESSource::fillTagCollectionFromGT(const std::string& connectionString, const std::string& prefix, diff --git a/CondCore/ESSources/plugins/CondDBESSource.h b/CondCore/ESSources/plugins/CondDBESSource.h index c76ed4cec02af..5bcbe953bc3eb 100644 --- a/CondCore/ESSources/plugins/CondDBESSource.h +++ b/CondCore/ESSources/plugins/CondDBESSource.h @@ -10,6 +10,33 @@ // // Author: Zhen Xie // + +// Some comments on concurrency. There are 3 relevant things the Framework is +// doing that prevent concurrency issues. This happens automatically and +// CondDBESSource can rely on the Framework taking care of this. +// +// 1. There is a recursive global mutex which is locked while calls to +// DataProxy::make and setIntervalFor are executing that allows only +// 1 thread to be running one of those functions at a time. (There +// is some discussion about replacing this mutex with lockfree concurrency +// mechanisms someday in the future, although this would be done in such +// a way as to provide similar protection against data races.) +// +// 2. Calls are sequenced that a call to setIntervalFor is made, then +// all related calls to DataProxy::initializeForNewIOV are made before +// another call to setIntervalFor is made. It is configurable how many +// IOVs can be running concurrently. The Framework will not call +// initializeForNewIOV or start running a new IOV unless the +// number of active IOVs is less than that configured number. +// +// 3. Independent of the above two items, after a call is made to +// DataProxy::initializeForNewIOV for a particular +// EventSetupRecordKey and iovIndex, all calls to DataProxy::make +// associated with that whose data is requested will be completed +// and processing of luminosity blocks associated with that will +// be completed before another call to DataProxy::initializeForNewIOV +// is made for that EventSetupRecordKey and iovIndex. + // system include files #include #include @@ -47,6 +74,10 @@ class CondDBESSource : public edm::eventsetup::DataProxyProvider, public edm::Ev KeyedProxiesVector registerProxies(const EventSetupRecordKey&, unsigned int iovIndex) override; + void initConcurrentIOVs(const EventSetupRecordKey& key, unsigned int nConcurrentIOVs) override; + + bool isConcurrentFinder() const override { return true; } + private: // ----------member data --------------------------- diff --git a/CondCore/ESSources/src/ProxyFactory.cc b/CondCore/ESSources/src/ProxyFactory.cc index 07d3a3b0a6543..feb0d5460f44f 100644 --- a/CondCore/ESSources/src/ProxyFactory.cc +++ b/CondCore/ESSources/src/ProxyFactory.cc @@ -18,8 +18,6 @@ cond::DataProxyWrapperBase::DataProxyWrapperBase() {} -cond::DataProxyWrapperBase::DataProxyWrapperBase(std::string const& il) : m_label(il) {} - cond::DataProxyWrapperBase::~DataProxyWrapperBase() {} void cond::DataProxyWrapperBase::addInfo(std::string const& il, std::string const& cs, std::string const& tag) { @@ -28,6 +26,41 @@ void cond::DataProxyWrapperBase::addInfo(std::string const& il, std::string cons m_tag = tag; } +void cond::DataProxyWrapperBase::loadTag(std::string const& tag) { + m_session.transaction().start(true); + m_iovProxy = m_session.readIov(tag); + m_session.transaction().commit(); + m_currentIov.clear(); + m_requests = std::make_shared>(); +} + +void cond::DataProxyWrapperBase::loadTag(std::string const& tag, boost::posix_time::ptime const& snapshotTime) { + m_session.transaction().start(true); + m_iovProxy = m_session.readIov(tag, snapshotTime); + m_session.transaction().commit(); + m_currentIov.clear(); + m_requests = std::make_shared>(); +} + +void cond::DataProxyWrapperBase::reload() { + std::string tag = m_iovProxy.tag(); + if (!tag.empty()) + loadTag(tag); +} + +cond::ValidityInterval cond::DataProxyWrapperBase::setIntervalFor(Time_t time) { + if (!m_currentIov.isValidFor(time)) { + m_currentIov.clear(); + m_session.transaction().start(true); + auto it = m_iovProxy.find(time); + if (it != m_iovProxy.end()) { + m_currentIov = *it; + } + m_session.transaction().commit(); + } + return cond::ValidityInterval(m_currentIov.since, m_currentIov.till); +} + EDM_REGISTER_PLUGINFACTORY(cond::ProxyFactory, cond::pluginCategory()); namespace cond { diff --git a/CondCore/ESSources/test/BuildFile.xml b/CondCore/ESSources/test/BuildFile.xml index 8d51b29b99c60..a12e39cc7a769 100644 --- a/CondCore/ESSources/test/BuildFile.xml +++ b/CondCore/ESSources/test/BuildFile.xml @@ -2,6 +2,7 @@ + @@ -14,5 +15,10 @@ - - + + + + + + + diff --git a/CondCore/ESSources/test/TestConcurrentIOVsCondCore.sh b/CondCore/ESSources/test/TestConcurrentIOVsCondCore.sh new file mode 100755 index 0000000000000..5f2799daea453 --- /dev/null +++ b/CondCore/ESSources/test/TestConcurrentIOVsCondCore.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +function die { echo $1: status $2 ; exit $2; } + +pushd ${LOCAL_TMP_DIR} + +echo cmsRun TestConcurrentIOVsCondCore_cfg.py +cmsRun --parameter-set ${LOCAL_TEST_DIR}/TestConcurrentIOVsCondCore_cfg.py > TestConcurrentIOVsCondCore.log || die 'Failed in TestConcurrentIOVsCondCore_cfg.py' $? +diff ${LOCAL_TEST_DIR}/unit_test_outputs/TestConcurrentIOVsCondCore.log TestConcurrentIOVsCondCore.log || die "comparing TestConcurrentIOVsCondCore.log" $? + +popd diff --git a/CondCore/ESSources/test/TestConcurrentIOVsCondCore_cfg.py b/CondCore/ESSources/test/TestConcurrentIOVsCondCore_cfg.py new file mode 100644 index 0000000000000..c6aed33355cdc --- /dev/null +++ b/CondCore/ESSources/test/TestConcurrentIOVsCondCore_cfg.py @@ -0,0 +1,78 @@ +# This configuration tests CondDBESSource and the EventSetup +# system. It causes it to read BeamSpot data objects from +# the database. The global tag and run number are selected +# to access this data in a run which is known to have +# multiple IOVs in the same run. This is a very simple job +# with empty input and one event per luminosity block. +# The analyzer gets this BeamSpot object and prints +# values from it to standard out. This is compared to +# a reference file of known expected files. If the +# correct data is not read and written to output then +# the unit test fails. The additional wrinkle here is that +# the analyzer puts in a "busy wait" (intentional does +# some calculation that uses CPU for a while). It does +# this for each event that is the first event of a +# new IOV. That forces multiple IOVs to be running +# concurrently. Further the delay decreases as we move +# forward so the data gets are not occurring in the same +# order as the lumis are being input. The purpose of +# all this is to test that CondDBESSource and the +# EventSetup system can process IOVs concurrently +# and deliver the same data objects as when processing +# one IOV at a time. + +import FWCore.ParameterSet.Config as cms + +process = cms.Process("TEST") + +#process.Tracer = cms.Service("Tracer") + +process.options = dict( + numberOfThreads = 4, + numberOfStreams = 4, + numberOfConcurrentRuns = 1, + numberOfConcurrentLuminosityBlocks = 4, + eventSetup = dict( + numberOfConcurrentIOVs = 4 + ) +) + +process.load("FWCore.MessageService.MessageLogger_cfi") +#process.MessageLogger.cerr.threshold = 'INFO' +#process.MessageLogger.cerr.INFO.limit = 1000000 + +process.source = cms.Source("EmptySource", + firstRun = cms.untracked.uint32(132598), + firstLuminosityBlock = cms.untracked.uint32(1), + firstEvent = cms.untracked.uint32(1), + numberEventsInRun = cms.untracked.uint32(1000000), + numberEventsInLuminosityBlock = cms.untracked.uint32(1) +) + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(200) +) + +process.GlobalTag = cms.ESSource("PoolDBESSource", + DBParameters = cms.PSet( + authenticationPath = cms.untracked.string(''), + authenticationSystem = cms.untracked.int32(0), + messageLevel = cms.untracked.int32(0), + security = cms.untracked.string('') + ), + DumpStat = cms.untracked.bool(False), + ReconnectEachRun = cms.untracked.bool(False), + RefreshAlways = cms.untracked.bool(False), + RefreshEachRun = cms.untracked.bool(False), + RefreshOpenIOVs = cms.untracked.bool(False), + connect = cms.string('frontier://FrontierProd/CMS_CONDITIONS'), + globaltag = cms.string('110X_dataRun2_v5'), + pfnPostfix = cms.untracked.string(''), + pfnPrefix = cms.untracked.string(''), + snapshotTime = cms.string(''), + toGet = cms.VPSet() +) + +process.test = cms.EDAnalyzer("TestConcurrentIOVsCondCore") + +process.p = cms.Path(process.test) diff --git a/CondCore/ESSources/test/TestCondCoreESSources.cpp b/CondCore/ESSources/test/TestCondCoreESSources.cpp new file mode 100644 index 0000000000000..b2991bd18ae57 --- /dev/null +++ b/CondCore/ESSources/test/TestCondCoreESSources.cpp @@ -0,0 +1,3 @@ +#include "FWCore/Utilities/interface/TestHelper.h" + +RUNTEST() diff --git a/CondCore/ESSources/test/stubs/TestConcurrentIOVsCondCore.cc b/CondCore/ESSources/test/stubs/TestConcurrentIOVsCondCore.cc new file mode 100644 index 0000000000000..4e1a172927079 --- /dev/null +++ b/CondCore/ESSources/test/stubs/TestConcurrentIOVsCondCore.cc @@ -0,0 +1,201 @@ + +/*---------------------------------------------------------------------- + +Global EDAnalyzer for testing concurrent IOVs in the CondCore subsystem. + +This module is written to run by the configuration +CondCore/ESSources/test/TestConcurrentIOVsCondCore_cfg.py only. +See that configuration for more comments and description. + +----------------------------------------------------------------------*/ + +#include "CondFormats/BeamSpotObjects/interface/BeamSpotObjects.h" +#include "CondFormats/DataRecord/interface/BeamSpotObjectsRcd.h" +#include "FWCore/Framework/interface/global/EDAnalyzer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "FWCore/Utilities/interface/thread_safety_macros.h" + +#include +#include + +namespace edmtest { + + constexpr unsigned nLumisToTest = 200; + + class TestConcurrentIOVsCondCore : public edm::global::EDAnalyzer<> { + public: + explicit TestConcurrentIOVsCondCore(edm::ParameterSet const&); + + void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const override; + + void endJob() override; + + void busyWait(char const* msg, unsigned int iterations) const; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + + private: + class BeamSpotTestObject { + public: + unsigned int lumi_; + double x_ = 0; + double y_ = 0; + double z_ = 0; + unsigned int start_ = 0; + unsigned int end_ = 0; + }; + + const double pi_; + + edm::ESGetToken const esTokenBeamSpotObjects_; + + // This can be mutable because it is designed particularly to + // be used in one unit test where there is one event per lumi + // and the vector is accessed by lumi number and does not change + // size. + CMS_THREAD_SAFE mutable std::vector testObjects_; + }; + + TestConcurrentIOVsCondCore::TestConcurrentIOVsCondCore(edm::ParameterSet const&) + : pi_(std::acos(-1)), + esTokenBeamSpotObjects_{esConsumes(edm::ESInputTag("", ""))}, + testObjects_(nLumisToTest) {} + + void TestConcurrentIOVsCondCore::analyze(edm::StreamID, + edm::Event const& event, + edm::EventSetup const& eventSetup) const { + unsigned int lumi = event.eventAuxiliary().luminosityBlock(); + + // These hard coded lumi numbers come from prior knowledge of + // the IOV ranges in the database. They are intentionally + // selected to force multiple IOVs to run concurrently. + // There is a wait each time the IOV changes so the first + // event of each IOV will take a long time to process. + // The number of iterations varies just to make things + // interesting and make early IOVs finish faster than + // earlier ones in many cases. + if (lumi == 1) { + busyWait("TestConcurrentIOVsCondCore::analyze", 30 * 200 * 1000); + } else if (lumi == 5) { + busyWait("TestConcurrentIOVsCondCore::analyze", 29 * 200 * 1000); + } else if (lumi == 6) { + busyWait("TestConcurrentIOVsCondCore::analyze", 28 * 200 * 1000); + } else if (lumi == 7) { + busyWait("TestConcurrentIOVsCondCore::analyze", 27 * 200 * 1000); + } else if (lumi == 11) { + busyWait("TestConcurrentIOVsCondCore::analyze", 26 * 200 * 1000); + } else if (lumi == 15) { + busyWait("TestConcurrentIOVsCondCore::analyze", 25 * 200 * 1000); + } else if (lumi == 16) { + busyWait("TestConcurrentIOVsCondCore::analyze", 24 * 200 * 1000); + } else if (lumi == 20) { + busyWait("TestConcurrentIOVsCondCore::analyze", 23 * 200 * 1000); + } else if (lumi == 21) { + busyWait("TestConcurrentIOVsCondCore::analyze", 22 * 200 * 1000); + } else if (lumi == 25) { + busyWait("TestConcurrentIOVsCondCore::analyze", 21 * 200 * 1000); + } else if (lumi == 30) { + busyWait("TestConcurrentIOVsCondCore::analyze", 20 * 200 * 1000); + } else if (lumi == 35) { + busyWait("TestConcurrentIOVsCondCore::analyze", 19 * 200 * 1000); + } else if (lumi == 40) { + busyWait("TestConcurrentIOVsCondCore::analyze", 18 * 200 * 1000); + } else if (lumi == 46) { + busyWait("TestConcurrentIOVsCondCore::analyze", 17 * 200 * 1000); + } else if (lumi == 48) { + busyWait("TestConcurrentIOVsCondCore::analyze", 16 * 200 * 1000); + } else if (lumi == 49) { + busyWait("TestConcurrentIOVsCondCore::analyze", 15 * 200 * 1000); + } else if (lumi == 50) { + busyWait("TestConcurrentIOVsCondCore::analyze", 14 * 200 * 1000); + } else if (lumi == 79) { + busyWait("TestConcurrentIOVsCondCore::analyze", 13 * 200 * 1000); + } else if (lumi == 90) { + busyWait("TestConcurrentIOVsCondCore::analyze", 12 * 200 * 1000); + } else if (lumi == 94) { + busyWait("TestConcurrentIOVsCondCore::analyze", 11 * 200 * 1000); + } else if (lumi == 99) { + busyWait("TestConcurrentIOVsCondCore::analyze", 10 * 200 * 1000); + } else if (lumi == 104) { + busyWait("TestConcurrentIOVsCondCore::analyze", 9 * 200 * 1000); + } else if (lumi == 113) { + busyWait("TestConcurrentIOVsCondCore::analyze", 8 * 200 * 1000); + } else if (lumi == 114) { + busyWait("TestConcurrentIOVsCondCore::analyze", 7 * 200 * 1000); + } else if (lumi == 118) { + busyWait("TestConcurrentIOVsCondCore::analyze", 6 * 200 * 1000); + } else if (lumi == 123) { + busyWait("TestConcurrentIOVsCondCore::analyze", 5 * 200 * 1000); + } else if (lumi == 128) { + busyWait("TestConcurrentIOVsCondCore::analyze", 4 * 200 * 1000); + } else if (lumi == 130) { + busyWait("TestConcurrentIOVsCondCore::analyze", 3 * 200 * 1000); + } else if (lumi == 132) { + busyWait("TestConcurrentIOVsCondCore::analyze", 10 * 200 * 1000); + } else if (lumi == 133) { + busyWait("TestConcurrentIOVsCondCore::analyze", 9 * 200 * 1000); + } else if (lumi == 134) { + busyWait("TestConcurrentIOVsCondCore::analyze", 8 * 200 * 1000); + } else if (lumi == 161) { + busyWait("TestConcurrentIOVsCondCore::analyze", 7 * 200 * 1000); + } else if (lumi == 165) { + busyWait("TestConcurrentIOVsCondCore::analyze", 6 * 200 * 1000); + } else if (lumi == 170) { + busyWait("TestConcurrentIOVsCondCore::analyze", 5 * 200 * 1000); + } + + edm::ESHandle beamSpotObjects = eventSetup.getHandle(esTokenBeamSpotObjects_); + BeamSpotObjectsRcd beamSpotObjectsRcd = eventSetup.get(); + edm::ValidityInterval iov = beamSpotObjectsRcd.validityInterval(); + + if (lumi < nLumisToTest) { + BeamSpotTestObject& testObject = testObjects_[lumi]; + testObject.lumi_ = lumi; + testObject.x_ = beamSpotObjects->GetX(); + testObject.y_ = beamSpotObjects->GetY(); + testObject.z_ = beamSpotObjects->GetZ(); + testObject.start_ = iov.first().luminosityBlockNumber(); + testObject.end_ = iov.last().luminosityBlockNumber(); + } + edm::LogAbsolute("TestConcurrentIOVsCondCore::busyWait") + << "TestConcurrentIOVsCondCore::analyze finishing lumi " << lumi << std::endl; + } + + void TestConcurrentIOVsCondCore::endJob() { + // This creates output that can be compared to a reference file. + // The original reference file was created using a version + // of the code before concurrent IOVs were implemented. + for (auto const& object : testObjects_) { + std::cout << "lumi = " << object.lumi_ << " position: (" << object.x_ << ", " << object.y_ << ", " << object.z_ + << ") iov = " << object.start_ << ":" << object.end_ << std::endl; + } + } + + void TestConcurrentIOVsCondCore::busyWait(char const* msg, unsigned int iterations) const { + // This is just doing meaningless work trying to use up time. + // Print it out and use cos so the compiler doesn't optimize it away. + edm::LogAbsolute("TestConcurrentIOVsCondCore::busyWait") << "Start TestConcurrentIOVsCondCore::busyWait " << msg; + double sum = 0.; + const double stepSize = pi_ / iterations; + for (unsigned int i = 0; i < iterations; ++i) { + sum += stepSize * cos(i * stepSize); + } + edm::LogAbsolute("TestConcurrentIOVsCondCore::busyWait") + << "Stop TestConcurrentIOVsCondCore::busyWait " << msg << " " << sum; + } + + void TestConcurrentIOVsCondCore::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + descriptions.addDefault(desc); + } + + DEFINE_FWK_MODULE(TestConcurrentIOVsCondCore); +} // namespace edmtest diff --git a/CondCore/ESSources/test/unit_test_outputs/TestConcurrentIOVsCondCore.log b/CondCore/ESSources/test/unit_test_outputs/TestConcurrentIOVsCondCore.log new file mode 100644 index 0000000000000..48d24132c926e --- /dev/null +++ b/CondCore/ESSources/test/unit_test_outputs/TestConcurrentIOVsCondCore.log @@ -0,0 +1,200 @@ +lumi = 0 position: (0, 0, 0) iov = 0:0 +lumi = 1 position: (0.0955994, -0.00165444, -0.00329325) iov = 1:4 +lumi = 2 position: (0.0955994, -0.00165444, -0.00329325) iov = 1:4 +lumi = 3 position: (0.0955994, -0.00165444, -0.00329325) iov = 1:4 +lumi = 4 position: (0.0955994, -0.00165444, -0.00329325) iov = 1:4 +lumi = 5 position: (0.0952701, -0.00313997, 0.029564) iov = 5:5 +lumi = 6 position: (0.0942696, -0.0126343, -0.469606) iov = 6:6 +lumi = 7 position: (0.0957372, -0.0156572, 0.0554159) iov = 7:10 +lumi = 8 position: (0.0957372, -0.0156572, 0.0554159) iov = 7:10 +lumi = 9 position: (0.0957372, -0.0156572, 0.0554159) iov = 7:10 +lumi = 10 position: (0.0957372, -0.0156572, 0.0554159) iov = 7:10 +lumi = 11 position: (0.0954237, -0.0116948, 0.0645144) iov = 11:14 +lumi = 12 position: (0.0954237, -0.0116948, 0.0645144) iov = 11:14 +lumi = 13 position: (0.0954237, -0.0116948, 0.0645144) iov = 11:14 +lumi = 14 position: (0.0954237, -0.0116948, 0.0645144) iov = 11:14 +lumi = 15 position: (0.0965168, -0.011715, -0.14604) iov = 15:15 +lumi = 16 position: (0.0953658, -0.00805389, -0.0479192) iov = 16:19 +lumi = 17 position: (0.0953658, -0.00805389, -0.0479192) iov = 16:19 +lumi = 18 position: (0.0953658, -0.00805389, -0.0479192) iov = 16:19 +lumi = 19 position: (0.0953658, -0.00805389, -0.0479192) iov = 16:19 +lumi = 20 position: (0.0945376, -0.00768498, -0.0978725) iov = 20:20 +lumi = 21 position: (0.0954137, -0.00500304, 0.0284693) iov = 21:24 +lumi = 22 position: (0.0954137, -0.00500304, 0.0284693) iov = 21:24 +lumi = 23 position: (0.0954137, -0.00500304, 0.0284693) iov = 21:24 +lumi = 24 position: (0.0954137, -0.00500304, 0.0284693) iov = 21:24 +lumi = 25 position: (0.0954439, -0.00239208, -0.039515) iov = 25:29 +lumi = 26 position: (0.0954439, -0.00239208, -0.039515) iov = 25:29 +lumi = 27 position: (0.0954439, -0.00239208, -0.039515) iov = 25:29 +lumi = 28 position: (0.0954439, -0.00239208, -0.039515) iov = 25:29 +lumi = 29 position: (0.0954439, -0.00239208, -0.039515) iov = 25:29 +lumi = 30 position: (0.0957408, 0.00087035, -0.13502) iov = 30:34 +lumi = 31 position: (0.0957408, 0.00087035, -0.13502) iov = 30:34 +lumi = 32 position: (0.0957408, 0.00087035, -0.13502) iov = 30:34 +lumi = 33 position: (0.0957408, 0.00087035, -0.13502) iov = 30:34 +lumi = 34 position: (0.0957408, 0.00087035, -0.13502) iov = 30:34 +lumi = 35 position: (0.0957318, 0.00422218, -0.144317) iov = 35:39 +lumi = 36 position: (0.0957318, 0.00422218, -0.144317) iov = 35:39 +lumi = 37 position: (0.0957318, 0.00422218, -0.144317) iov = 35:39 +lumi = 38 position: (0.0957318, 0.00422218, -0.144317) iov = 35:39 +lumi = 39 position: (0.0957318, 0.00422218, -0.144317) iov = 35:39 +lumi = 40 position: (0.0959216, 0.00894535, 0.043018) iov = 40:45 +lumi = 41 position: (0.0959216, 0.00894535, 0.043018) iov = 40:45 +lumi = 42 position: (0.0959216, 0.00894535, 0.043018) iov = 40:45 +lumi = 43 position: (0.0959216, 0.00894535, 0.043018) iov = 40:45 +lumi = 44 position: (0.0959216, 0.00894535, 0.043018) iov = 40:45 +lumi = 45 position: (0.0959216, 0.00894535, 0.043018) iov = 40:45 +lumi = 46 position: (0.0959074, 0.013607, 0.0172612) iov = 46:47 +lumi = 47 position: (0.0959074, 0.013607, 0.0172612) iov = 46:47 +lumi = 48 position: (0.0961742, 0.0128366, 0.305298) iov = 48:48 +lumi = 49 position: (0.0953185, 0.0108404, -0.0343426) iov = 49:49 +lumi = 50 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 51 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 52 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 53 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 54 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 55 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 56 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 57 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 58 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 59 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 60 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 61 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 62 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 63 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 64 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 65 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 66 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 67 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 68 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 69 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 70 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 71 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 72 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 73 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 74 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 75 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 76 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 77 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 78 position: (0.0956241, -0.00210906, -0.00912867) iov = 50:78 +lumi = 79 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 80 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 81 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 82 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 83 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 84 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 85 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 86 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 87 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 88 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 89 position: (0.096016, -0.0032159, -0.110516) iov = 79:89 +lumi = 90 position: (0.0956896, -0.0159884, 0.278345) iov = 90:93 +lumi = 91 position: (0.0956896, -0.0159884, 0.278345) iov = 90:93 +lumi = 92 position: (0.0956896, -0.0159884, 0.278345) iov = 90:93 +lumi = 93 position: (0.0956896, -0.0159884, 0.278345) iov = 90:93 +lumi = 94 position: (0.0962257, -0.0125421, 0.233333) iov = 94:98 +lumi = 95 position: (0.0962257, -0.0125421, 0.233333) iov = 94:98 +lumi = 96 position: (0.0962257, -0.0125421, 0.233333) iov = 94:98 +lumi = 97 position: (0.0962257, -0.0125421, 0.233333) iov = 94:98 +lumi = 98 position: (0.0962257, -0.0125421, 0.233333) iov = 94:98 +lumi = 99 position: (0.095594, -0.00945652, 0.0350855) iov = 99:103 +lumi = 100 position: (0.095594, -0.00945652, 0.0350855) iov = 99:103 +lumi = 101 position: (0.095594, -0.00945652, 0.0350855) iov = 99:103 +lumi = 102 position: (0.095594, -0.00945652, 0.0350855) iov = 99:103 +lumi = 103 position: (0.095594, -0.00945652, 0.0350855) iov = 99:103 +lumi = 104 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 105 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 106 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 107 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 108 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 109 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 110 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 111 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 112 position: (0.0956994, -0.00421605, 0.0488305) iov = 104:112 +lumi = 113 position: (0.0958566, -0.00180124, 0.0617757) iov = 113:113 +lumi = 114 position: (0.0958873, 0.000926586, 0.0450041) iov = 114:117 +lumi = 115 position: (0.0958873, 0.000926586, 0.0450041) iov = 114:117 +lumi = 116 position: (0.0958873, 0.000926586, 0.0450041) iov = 114:117 +lumi = 117 position: (0.0958873, 0.000926586, 0.0450041) iov = 114:117 +lumi = 118 position: (0.0962392, 0.00318299, 0.0308925) iov = 118:122 +lumi = 119 position: (0.0962392, 0.00318299, 0.0308925) iov = 118:122 +lumi = 120 position: (0.0962392, 0.00318299, 0.0308925) iov = 118:122 +lumi = 121 position: (0.0962392, 0.00318299, 0.0308925) iov = 118:122 +lumi = 122 position: (0.0962392, 0.00318299, 0.0308925) iov = 118:122 +lumi = 123 position: (0.0959617, 0.00738629, 0.203399) iov = 123:127 +lumi = 124 position: (0.0959617, 0.00738629, 0.203399) iov = 123:127 +lumi = 125 position: (0.0959617, 0.00738629, 0.203399) iov = 123:127 +lumi = 126 position: (0.0959617, 0.00738629, 0.203399) iov = 123:127 +lumi = 127 position: (0.0959617, 0.00738629, 0.203399) iov = 123:127 +lumi = 128 position: (0.0954344, 0.0104093, 0.0554359) iov = 128:129 +lumi = 129 position: (0.0954344, 0.0104093, 0.0554359) iov = 128:129 +lumi = 130 position: (0.0967872, 0.0120268, -0.0816242) iov = 130:131 +lumi = 131 position: (0.0967872, 0.0120268, -0.0816242) iov = 130:131 +lumi = 132 position: (0.0959849, 0.0115498, 0.397611) iov = 132:132 +lumi = 133 position: (0.0959939, 0.00287967, -0.00843624) iov = 133:133 +lumi = 134 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 135 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 136 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 137 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 138 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 139 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 140 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 141 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 142 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 143 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 144 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 145 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 146 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 147 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 148 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 149 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 150 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 151 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 152 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 153 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 154 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 155 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 156 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 157 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 158 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 159 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 160 position: (0.0956742, -0.00225352, 0.0599864) iov = 134:160 +lumi = 161 position: (0.0967802, -0.00278706, 0.11287) iov = 161:164 +lumi = 162 position: (0.0967802, -0.00278706, 0.11287) iov = 161:164 +lumi = 163 position: (0.0967802, -0.00278706, 0.11287) iov = 161:164 +lumi = 164 position: (0.0967802, -0.00278706, 0.11287) iov = 161:164 +lumi = 165 position: (0.103087, -0.00154271, 0.0441158) iov = 165:169 +lumi = 166 position: (0.103087, -0.00154271, 0.0441158) iov = 165:169 +lumi = 167 position: (0.103087, -0.00154271, 0.0441158) iov = 165:169 +lumi = 168 position: (0.103087, -0.00154271, 0.0441158) iov = 165:169 +lumi = 169 position: (0.103087, -0.00154271, 0.0441158) iov = 165:169 +lumi = 170 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 171 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 172 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 173 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 174 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 175 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 176 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 177 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 178 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 179 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 180 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 181 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 182 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 183 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 184 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 185 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 186 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 187 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 188 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 189 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 190 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 191 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 192 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 193 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 194 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 195 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 196 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 197 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 198 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0 +lumi = 199 position: (0.0994363, -0.00259129, -0.0910717) iov = 170:0