From 5904636f081c8deb193b58aba791889c7cc1b93b Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Thu, 30 Jun 2016 12:38:08 +0000 Subject: [PATCH] Improv4ed implementation of conditions --- DDCond/CMakeLists.txt | 5 +- DDCond/include/DDCond/ConditionsDataLoader.h | 8 +- DDCond/include/DDCond/ConditionsIOVPool.h | 20 +- DDCond/include/DDCond/ConditionsInterna.h | 68 ++++-- DDCond/include/DDCond/ConditionsListener.h | 62 ++++++ DDCond/include/DDCond/ConditionsManager.h | 34 ++- DDCond/include/DDCond/ConditionsPool.h | 60 ++++-- DDCond/include/DDCond/ConditionsTest.h | 73 +++++++ DDCond/src/ConditionsDataLoader.cpp | 4 +- DDCond/src/ConditionsIOVPool.cpp | 66 +++--- DDCond/src/ConditionsInterna.cpp | 198 +++++++++++++----- DDCond/src/ConditionsListener.cpp | 26 +++ DDCond/src/ConditionsManager.cpp | 63 +++++- DDCond/src/ConditionsPool.cpp | 46 +++- DDCond/src/ConditionsTest.cpp | 12 +- .../src/{ => plugins}/ConditionsExample.cpp | 69 +++--- .../{ => plugins}/ConditionsLinearPool.cpp | 149 ++++++++----- .../plugins/ConditionsManagerInstaller.cpp | 39 ++++ .../{ => plugins}/ConditionsMultiLoader.cpp | 120 ++++++----- DDCond/src/{ => plugins}/ConditionsParser.cpp | 4 +- DDCond/src/plugins/ConditionsPlugins.cpp | 137 ++++++++++++ DDCond/src/plugins/ConditionsUpdate.cpp | 15 ++ .../src/{ => plugins}/ConditionsXmlLoader.cpp | 49 +++-- DDCore/include/DD4hep/Conditions.h | 51 ++++- DDCore/include/DD4hep/InstanceCount.h | 14 ++ DDCore/include/DD4hep/LCDD.h | 16 +- DDCore/include/DD4hep/LCDDLoad.h | 26 ++- DDCore/include/DD4hep/Operators.h | 68 ++++++ DDCore/include/DD4hep/PluginCreators.h | 4 +- DDCore/include/DD4hep/Primitives.h | 6 +- DDCore/include/DD4hep/Readout.h | 2 + .../include/DD4hep/objects/BasicGrammar_inl.h | 18 +- .../DD4hep/objects/ConditionsInterna.h | 52 +++-- DDCore/include/XML/UriReader.h | 42 +++- DDCore/src/Conditions.cpp | 118 ++++++++++- DDCore/src/ConditionsInterna.cpp | 50 ++++- DDCore/src/Evaluator/setStdMath.cpp | 122 +++++++---- DDCore/src/LCDDImp.cpp | 9 +- DDCore/src/LCDDImp.h | 5 + DDCore/src/LCDDLoad.cpp | 14 +- DDCore/src/Readout.cpp | 22 +- DDCore/src/XML/DocumentHandler.cpp | 2 +- DDCore/src/XML/UriReader.cpp | 25 +++ DDCore/src/plugins/Compact2Objects.cpp | 56 +++-- DDCore/src/plugins/StandardPlugins.cpp | 79 +++---- UtilityApps/src/dd4hep_python.cpp | 51 ----- 46 files changed, 1624 insertions(+), 555 deletions(-) create mode 100644 DDCond/include/DDCond/ConditionsListener.h create mode 100644 DDCond/include/DDCond/ConditionsTest.h create mode 100644 DDCond/src/ConditionsListener.cpp rename DDCond/src/{ => plugins}/ConditionsExample.cpp (88%) rename DDCond/src/{ => plugins}/ConditionsLinearPool.cpp (66%) create mode 100644 DDCond/src/plugins/ConditionsManagerInstaller.cpp rename DDCond/src/{ => plugins}/ConditionsMultiLoader.cpp (59%) rename DDCond/src/{ => plugins}/ConditionsParser.cpp (99%) create mode 100644 DDCond/src/plugins/ConditionsPlugins.cpp create mode 100644 DDCond/src/plugins/ConditionsUpdate.cpp rename DDCond/src/{ => plugins}/ConditionsXmlLoader.cpp (83%) create mode 100644 DDCore/include/DD4hep/Operators.h delete mode 100644 UtilityApps/src/dd4hep_python.cpp diff --git a/DDCond/CMakeLists.txt b/DDCond/CMakeLists.txt index d27c519a6..0b3c2e2de 100644 --- a/DDCond/CMakeLists.txt +++ b/DDCond/CMakeLists.txt @@ -15,4 +15,7 @@ dd4hep_package( DDCond INSTALL_INCLUDES include/DDCond) #---DDCond library -------------------------------------------------------------- -dd4hep_add_plugin ( DDCond SOURCES src/*.cpp ) +dd4hep_add_package_library(DDCond SOURCES src/*.cpp ) + +#---DDCond components ----------------------------------------------------------- +dd4hep_add_plugin ( DDCondPlugins SOURCES src/plugins/*.cpp ) diff --git a/DDCond/include/DDCond/ConditionsDataLoader.h b/DDCond/include/DDCond/ConditionsDataLoader.h index 2b6bcd2dd..78948d20f 100644 --- a/DDCond/include/DDCond/ConditionsDataLoader.h +++ b/DDCond/include/DDCond/ConditionsDataLoader.h @@ -44,7 +44,8 @@ namespace DD4hep { */ class ConditionsDataLoader : public NamedObject, public PropertyConfigurable { public: - typedef std::vector<std::string> Sources; + typedef std::pair<std::string, IOV> Source; + typedef std::vector<Source> Sources; typedef ConditionsDataLoader base_t; protected: @@ -67,7 +68,7 @@ namespace DD4hep { /// Default destructor virtual ~ConditionsDataLoader(); /// Add data source definition to loader - void addSource(const std::string& source); + void addSource(const std::string& source, const IOV& iov); /// Load a condition set given a Detector Element and the conditions name according to their validity virtual size_t load(DetElement det, const std::string& cond, @@ -78,6 +79,9 @@ namespace DD4hep { const std::string& cond, const IOV& req_validity, RangeConditions& conditions) = 0; + virtual size_t update(const IOV& req_validity, + RangeConditions& conditions, + IOV& conditions_validity) = 0; }; } /* End namespace Conditions */ diff --git a/DDCond/include/DDCond/ConditionsIOVPool.h b/DDCond/include/DDCond/ConditionsIOVPool.h index 764b56607..7319c39de 100644 --- a/DDCond/include/DDCond/ConditionsIOVPool.h +++ b/DDCond/include/DDCond/ConditionsIOVPool.h @@ -41,13 +41,18 @@ namespace DD4hep { class ConditionsIOVPool { public: typedef ConditionsPool* Entry; - typedef std::map<std::pair<int,int>, Entry > Entries; + typedef std::map<IOV::Key, Entry > Entries; + typedef std::set<int> Keys; + Entries entries; + Keys keys; + Keys traced_keys; public: /// Default constructor ConditionsIOVPool(); /// Default destructor virtual ~ConditionsIOVPool(); + bool addKey(Condition c); /// Retrieve a condition set given a Detector Element and the conditions name according to their validity void __find(DetElement detector, const std::string& condition_name, @@ -59,12 +64,13 @@ namespace DD4hep { const IOV& req_validity, RangeConditions& result); /// Select all ACTIVE conditions, which do no longer match the IOV requirement - void __select_expired(const IOV& required_validity, - RangeConditions& result); - void __update_expired(ConditionsDataLoader& loader, - ConditionsPool& pool, - RangeConditions& expired, - const IOV& required_validity); + void select(const IOV& required_validity, + RangeConditions& valid, + RangeConditions& expired, + IOV& conditions_validity); + /// Remove all key based pools with an age beyon the minimum age. + /** @return Number of conditions cleaned up and removed. */ + int clean(int max_age); }; } /* End namespace Conditions */ diff --git a/DDCond/include/DDCond/ConditionsInterna.h b/DDCond/include/DDCond/ConditionsInterna.h index 6ca9ab592..90f775f50 100644 --- a/DDCond/include/DDCond/ConditionsInterna.h +++ b/DDCond/include/DDCond/ConditionsInterna.h @@ -35,6 +35,7 @@ namespace DD4hep { class Entry; class ConditionsPool; class ConditionsIOVPool; + class ConditionsListener; class ConditionsDataLoader; /// Conditions internal namespace declaration @@ -57,25 +58,28 @@ namespace DD4hep { * \ingroup DD4HEP_CONDITIONS */ class ConditionsManagerObject : public NamedObject, public PropertyConfigurable { - public: - friend class ConditionsDataLoader; + friend class DD4hep::Conditions::ConditionsPool; + friend class DD4hep::Conditions::ConditionsDataLoader; - typedef dd4hep_ptr<ConditionsDataLoader> Loader; - typedef std::vector<IOVType> IOVTypes; - typedef std::vector<ConditionsIOVPool*> TypedConditionPool; + public: + typedef dd4hep_ptr<ConditionsDataLoader> Loader; + typedef std::vector<IOVType> IOVTypes; + typedef std::vector<ConditionsIOVPool*> TypedConditionPool; typedef std::map<IOV::Key, ReplacementPool*> ReplacementCache; - typedef std::vector<ReplacementPool*> FreePools; + typedef std::vector<ReplacementPool*> FreePools; + typedef std::pair<ConditionsListener*,void*> Listener; + typedef std::set<Listener> Listeners; public: /// Property: maximal number of IOV types to be handled - int m_maxIOVTypes; + int m_maxIOVTypes; /// Property: ConditionsPool constructor type (default: empty. MUST BE SET!) - std::string m_poolType; + std::string m_poolType; /// Property: UpdatePool constructor type (default: DD4hep_ConditionsLinearUpdatePool) - std::string m_updateType; - /// Property: ReplacementPool constructor type (default: DD4hep_ConditionsLinearReplacementPool) - std::string m_replType; + std::string m_updateType; + /// Property: UserPool constructor type (default: DD4hep_ConditionsLinearUserPool) + std::string m_userType; /// Property: Conditions loader type (default: "multi" -> DD4hep_Conditions_multi_Loader) std::string m_loaderType; @@ -85,6 +89,10 @@ namespace DD4hep { IOVTypes m_iovTypes; /// Managed pool of typed conditions idexed by IOV-type and IOV key TypedConditionPool m_pool; + /// Conditions listeners on registration of new conditions + Listeners m_onRegister; + /// Conditions listeners on de-registration of new conditions + Listeners m_onRemove; /// Lock to protect the update/delayed conditions pool dd4hep_mutex_t m_updateLock; /// Lock to protect the pool of all known conditions @@ -125,6 +133,14 @@ namespace DD4hep { /// Push registered set of conditions to the corresponding detector elements void __push_immediate(RangeConditions& rc); + void registerCallee(Listeners& listeners, const Listener& callee, bool add); + + /// Listener invocation when a condition is registered to the cache + void onRegister(Condition condition); + + /// Listener invocation when a condition is deregistered from the cache + void onRemove(Condition condition); + public: /// Set a single conditions value to be managed. /// Requires EXTERNALLY held lock on update pool! @@ -139,41 +155,51 @@ namespace DD4hep { void initialize(); + /// (Un)Registration of conditions listeners with callback when a new condition is registered + void callOnRegister(const Listener& callee, bool add); + /// (Un)Registration of conditions listeners with callback when a condition is unregistered + void callOnRemove(const Listener& callee, bool add); + /// Register new IOV type if it does not (yet) exist. /** Returns (false,pointer) if IOV existed and * (true,pointer) if new IOV was registered to the manager. */ std::pair<bool, const IOVType*> registerIOVType(size_t iov_type, const std::string& iov_name); + /// Access IOV by its type + const IOVTypes& iovTypes () const { return m_iovTypes; } + /// Access IOV by its type const IOVType* iovType (size_t iov_type) const; /// Access IOV by its name const IOVType* iovType (const std::string& iov_name) const; + /// Create IOV from string + void fromString(const std::string& iov_str, IOV& iov); + /// Register IOV using new string data ConditionsPool* registerIOV(const std::string& data); + /// Register IOV with type and key ConditionsPool* registerIOV(const IOVType& typ, IOV::Key key); + /// Register new condition with the conditions store. Unlocked version, not multi-threaded + bool registerUnlocked(ConditionsPool* pool, Condition cond); /// Prepare all updates to the clients with the defined IOV - void prepare(const IOV& required_validity); + long prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool); /// Enable all updates to the clients with the defined IOV - void enable(const IOV& required_validity); - - /// Validate the conditions set and age all unused conditions - void validate(const IOV& iov); - - /// Age conditions, which are no longer used and to be removed eventually - void age(); + long enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool); /// Clean conditions, which are above the age limit. - void clean(); + /** @return Number of conditions cleaned up and removed */ + int clean(const IOVType* typ, int max_age); /// Full cleanup of all managed conditions. - void clear(); + /** @return pair<Number of pools cleared, Number of conditions cleaned up and removed> */ + std::pair<int,int> clear(); /// Push all pending updates to the conditions store. /** Note: diff --git a/DDCond/include/DDCond/ConditionsListener.h b/DDCond/include/DDCond/ConditionsListener.h new file mode 100644 index 000000000..13fc81772 --- /dev/null +++ b/DDCond/include/DDCond/ConditionsListener.h @@ -0,0 +1,62 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DD4HEP_CONDITIONS_CONDITIONSLISTENER_H +#define DD4HEP_CONDITIONS_CONDITIONSLISTENER_H + +// Framework include files +#include "DD4hep/Conditions.h" + +// C/C++ include files + +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { + + /// Namespace for the geometry part of the AIDA detector description toolkit + namespace Conditions { + + /// Forward declarations + class IOV; + class IOVType; + class ConditionsPool; + + /// Base class to be implemented by objects to listen on condition callbacks + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + class ConditionsListener { + public: + /// Default constructor + ConditionsListener(); + /// Default destructor + virtual ~ConditionsListener(); + /// ConditionsListener dummy implementation: onRegister new IOV type + virtual void onRegisterIOVType(const IOVType* /* type */, void* /* param */) { } + /// ConditionsListener dummy implementation: onRegister new condition + virtual void onRegisterCondition(Condition /* cond */, void* /* param */) { } + /// ConditionsListener dummy implementation: onRegister new conditions pool + virtual void onRegisterPool(ConditionsPool* /* pool */, void* /* param */) { } + + /// ConditionsListener dummy implementation: onRemove a condition + virtual void onRemoveCondition(Condition /* cond */, void* /* param */) { } + /// ConditionsListener dummy implementation: onRemove a conditions pool + virtual void onRemovePool(ConditionsPool* /* pool */, void* /* param */) { } + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ + +#endif /* DD4HEP_CONDITIONS_CONDITIONSLISTENER_H */ diff --git a/DDCond/include/DDCond/ConditionsManager.h b/DDCond/include/DDCond/ConditionsManager.h index 99ecf36bb..db58d9e47 100644 --- a/DDCond/include/DDCond/ConditionsManager.h +++ b/DDCond/include/DDCond/ConditionsManager.h @@ -15,6 +15,7 @@ #define DDCOND_CONDITIONSMANAGER_H // Framework include files +#include "DD4hep/Memory.h" #include "DD4hep/Conditions.h" #include "DD4hep/ComponentProperties.h" @@ -26,6 +27,8 @@ namespace DD4hep { // Forward declarations class Entry; + class ConditionsPool; + class ConditionsIOVPool; class ConditionsDataLoader; /// Conditions internal namespace @@ -45,9 +48,9 @@ namespace DD4hep { /// Standard object type typedef Interna::ConditionsManagerObject Object; typedef ConditionsDataLoader Loader; - typedef std::vector<IOVType*> IOVTypes; - typedef std::map<DetElement,Container> DetectorConditions; + typedef std::vector<IOVType> IOVTypes; typedef std::map<IOVType*,Container> TypeConditions; + typedef std::map<DetElement,Container> DetectorConditions; public: @@ -95,11 +98,29 @@ namespace DD4hep { /// Access the availible/known IOV types const IOVTypes& iovTypes() const; + /// Access the used/registered IOV types + const std::vector<const IOVType*> iovTypesUsed() const; + + /// Access conditions pool by iov type + ConditionsIOVPool* iovPool(const IOVType& type) const; + + /// Create IOV from string + void fromString(const std::string& iov_str, IOV& iov); + /// Register new IOV type if it does not (yet) exist. /** Returns (false,pointer) if IOV existed and * (true,pointer) if new IOV was registered to the manager. */ std::pair<bool, const IOVType*> registerIOVType(size_t iov_type, const std::string& iov_name); + + /// Register IOV with type and key + ConditionsPool* registerIOV(const IOVType& typ, IOV::Key key); + + /// Register new condition with the conditions store. Unlocked version, not multi-threaded + bool registerUnlocked(const IOVType* type, IOV::Key key, Condition cond); + + /// Register new condition with the conditions store. Unlocked version, not multi-threaded + bool registerUnlocked(ConditionsPool* pool, Condition cond); /// Access IOV by its type const IOVType* iovType (size_t iov_type) const; @@ -113,11 +134,8 @@ namespace DD4hep { /// Unlock the internal data structures. This enables calls to "register", etc. void unlock(); - /// Age conditions, which are no longer used and to be removed eventually - void age(); - /// Clean conditions, which are above the age limit. - void clean(); + void clean(const IOVType* typ, int max_age); /// Full cleanup of all managed conditions. void clear(); @@ -129,10 +147,10 @@ namespace DD4hep { void pushUpdates(); /// Prepare all updates to the clients with the defined IOV - void prepare(const IOV& required_validity); + long prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool); /// Enable all updates to the clients with the defined IOV - void enable(const IOV& required_validity); + long enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool); /// Retrieve a condition given a Detector Element and the conditions name Condition get(DetElement detector, diff --git a/DDCond/include/DDCond/ConditionsPool.h b/DDCond/include/DDCond/ConditionsPool.h index ab2e3ac3d..9d824916e 100644 --- a/DDCond/include/DDCond/ConditionsPool.h +++ b/DDCond/include/DDCond/ConditionsPool.h @@ -16,9 +16,9 @@ // Framework include files #include "DD4hep/Mutex.h" +#include "DD4hep/Detector.h" #include "DD4hep/Conditions.h" -#include "DD4hep/NamedObject.h" -#include "DD4hep/objects/ConditionsInterna.h" +#include "DDCond/ConditionsManager.h" /// Namespace for the AIDA detector description toolkit namespace DD4hep { @@ -46,18 +46,27 @@ namespace DD4hep { * \ingroup DD4HEP_CONDITIONS */ class ConditionsPool : public NamedObject { - + protected: + /// Handle to conditions manager object + ConditionsManager m_manager; + public: - enum { AGE_NONE = 0, - AGE_ANY = 9999999, + enum { AGE_NONE = 0, + AGE_ANY = 9999999, AGE_EXPIRED = 12345678 }; - + enum { NO_POOL_TYPE = 0, + UPDATE_POOL_TYPE = 1, + USER_POOL_TYPE = 2 + }; + /// IOV type of the conditions hosted by this pool const IOVType* iovType; + /// The IOV of the conditions hosted IOV* iov; - /// Temporary buffer - ReplacementPool* updates; + /// Aging value int age_value; + /// Pool type (regular, user, ipdate,...) + int pool_type; protected: @@ -69,16 +78,17 @@ namespace DD4hep { */ virtual Condition create(ConditionsPool* pool, const Entry* cond); - /// Check if detector and name match - bool match(const DetElement::Object* det, int hash, const Condition::Object* c) const { - return det == c->detector.ptr() && hash == c->hash; - } - public: /// Default constructor - ConditionsPool(); + ConditionsPool(ConditionsManager mgr); /// Default destructor. Note: pool must be cleared by the subclass! virtual ~ConditionsPool(); + /// Print pool basics + void print(const std::string& opt) const; + /// Listener invocation when a condition is registered to the cache + void onRegister(Condition condition); + /// Listener invocation when a condition is deregistered from the cache + void onRemove(Condition condition); /// Register a new condition to this pool virtual void insert(Condition cond) = 0; /// Register a new condition to this pool. May overload for performance reasons. @@ -93,8 +103,12 @@ namespace DD4hep { virtual void select(DetElement det, const std::string& cond_name, RangeConditions& result) = 0; /// Select all conditions contained virtual void select_all(RangeConditions& result) = 0; + /// Select all conditions contained + virtual void select_all(ConditionsPool& selection_pool) = 0; /// Select the conditons, used also by the DetElement of the condition virtual void select_used(RangeConditions& result) = 0; + /// Total entry count + virtual int count() const = 0; }; /// Interface for conditions pool optimized to host conditions updates. @@ -111,9 +125,11 @@ namespace DD4hep { public: /// Default constructor - UpdatePool(); + UpdatePool(ConditionsManager mgr); /// Default destructor. virtual ~UpdatePool(); + /// Pool type identifier + static int poolType() { return UPDATE_POOL_TYPE; } /// Adopt all entries sorted by IOV. Entries will be removed from the pool virtual void popEntries(UpdateEntries& entries) = 0; /// Register a new condition to this pool @@ -130,14 +146,18 @@ namespace DD4hep { * \author M.Frank * \version 1.0 */ - class ReplacementPool : public ConditionsPool { + class UserPool : public ConditionsPool { public: /// Default constructor - ReplacementPool(); + UserPool(ConditionsManager mgr); /// Default destructor. - virtual ~ReplacementPool(); - /// Pop conditions. May overloade for performance reasons! - virtual void popEntries(RangeConditions& entries) = 0; + virtual ~UserPool(); + /// Pool type identifier + static int poolType() { return USER_POOL_TYPE; } + /// Access the interval of validity for this user pool + virtual const IOV& validity() const = 0; + /// Update interval of validity for this user pool (should only be called by ConditionsManager) + virtual void setValidity(const IOV& value) = 0; }; } /* End namespace Conditions */ diff --git a/DDCond/include/DDCond/ConditionsTest.h b/DDCond/include/DDCond/ConditionsTest.h new file mode 100644 index 000000000..b6d519ae2 --- /dev/null +++ b/DDCond/include/DDCond/ConditionsTest.h @@ -0,0 +1,73 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DDCOND_CONDITIONSTEST_H +#define DDCOND_CONDITIONSTEST_H + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Conditions.h" +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/objects/ConditionsInterna.h" + +#include "DDCond/ConditionsManager.h" +#include "DDCond/ConditionsIOVPool.h" +#include "DDCond/ConditionsInterna.h" + +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { + + /// Namespace for the geometry part of the AIDA detector description toolkit + namespace Conditions { + + /// Namespace for test environments in DDCond + namespace Test { + + using Geometry::LCDD; + using Geometry::Position; + using Geometry::DetElement; + + struct TestEnv { + LCDD& lcdd; + DetElement detector; + ConditionsManager manager; + Handle<ConditionsDataLoader> loader; + const IOVType* epoch; + const IOVType* run; + + TestEnv(LCDD& _lcdd, const std::string& detector_name); + /// Find daughter element of the detector object + DetElement daughter(const std::string& sub_path) const; + + void add_xml_data_source(const std::string& file, const std::string& iov); + void dump_conditions_pools(); + static void dump_detector_element(DetElement elt); + static void dump_conditions_tree(DetElement elt); + }; + + template <typename T> void print_condition(Condition condition); + template <typename T> void print_bound_value(Condition condition, const char* norm=0); + template <typename T> void print_conditions(const RangeConditions& rc); + void check_discrete_condition(Condition c, const IOV& iov); + + template<typename T> const T& access_val(Condition c) { + if ( !c->is_bound() ) { + c.bind<T>(); + } + return c.get<T>(); + } + } + } +} +#endif // DDCOND_CONDITIONSTEST_H diff --git a/DDCond/src/ConditionsDataLoader.cpp b/DDCond/src/ConditionsDataLoader.cpp index ca0ba6679..e9c9b1562 100644 --- a/DDCond/src/ConditionsDataLoader.cpp +++ b/DDCond/src/ConditionsDataLoader.cpp @@ -35,8 +35,8 @@ ConditionsDataLoader::~ConditionsDataLoader() { } /// Add data source definition to loader -void ConditionsDataLoader::addSource(const string& source) { - m_sources.push_back(source); +void ConditionsDataLoader::addSource(const string& source, const IOV& iov) { + m_sources.push_back(make_pair(source,iov)); } /// Queue update to manager. diff --git a/DDCond/src/ConditionsIOVPool.cpp b/DDCond/src/ConditionsIOVPool.cpp index b732e3924..5c057c314 100644 --- a/DDCond/src/ConditionsIOVPool.cpp +++ b/DDCond/src/ConditionsIOVPool.cpp @@ -16,6 +16,7 @@ #include "DD4hep/Printout.h" #include "DD4hep/InstanceCount.h" #include "DDCond/ConditionsIOVPool.h" +#include "DD4hep/objects/ConditionsInterna.h" #include "DDCond/ConditionsDataLoader.h" using namespace DD4hep; @@ -31,13 +32,21 @@ ConditionsIOVPool::~ConditionsIOVPool() { InstanceCount::decrement(this); } +bool ConditionsIOVPool::addKey(Condition c) { + // TODO: Should be: det.path()+'#'+c->name; instead of c->comment + int hash = c->hash; + c->flags |= Interna::ConditionObject::ACTIVE; + keys.insert(hash); + return true; +} + void ConditionsIOVPool::__find(DetElement detector, const std::string& condition_name, const IOV& req_validity, RangeConditions& result) { if ( !entries.empty() ) { - const IOV::Key req_key = req_validity.key(); // 8 bytes => better copy! + const IOV::Key req_key = req_validity.key(); // 16 bytes => better copy! for(Entries::const_iterator i=entries.begin(); i!=entries.end(); ++i) { if ( IOV::key_contains_range((*i).first, req_key) ) { (*i).second->select(detector, condition_name, result); @@ -66,46 +75,45 @@ void ConditionsIOVPool::__find_range(DetElement detector, } } +/// Remove all key based pools with an age beyon the minimum age +int ConditionsIOVPool::clean(int max_age) { + Entries rest; + int count = 0; + for(Entries::const_iterator i=entries.begin(); i!=entries.end(); ++i) { + ConditionsPool* pool = (*i).second; + if ( pool->age_value >= max_age ) { + count += pool->count(); + pool->print("Remove"); + delete pool; + } + else + rest.insert(make_pair(pool->iov->keyData,pool)); + } + entries = rest; + return count; +} + /// Select all ACTIVE conditions, which do no longer match the IOV requirement -void ConditionsIOVPool::__select_expired(const IOV& required_validity, RangeConditions& result) { +void ConditionsIOVPool::select(const IOV& required_validity, + RangeConditions& valid, + RangeConditions& expired, + IOV& conditions_validity) +{ if ( !entries.empty() ) { - const IOV::Key req_key = required_validity.key(); // 8 bytes => better copy! + const IOV::Key req_key = required_validity.key(); // 16 bytes => better copy! for(Entries::const_iterator i=entries.begin(); i!=entries.end(); ++i) { ConditionsPool* pool = (*i).second; if ( !IOV::key_contains_range((*i).first, req_key) ) { if ( pool->age_value == ConditionsPool::AGE_NONE ) { // Now check the content: - pool->select_used(result); + pool->select_used(expired); } ++pool->age_value; continue; } + conditions_validity.iov_intersection((*i).first); + pool->select_used(valid); pool->age_value = 0; } } } - -/// Select all ACTIVE conditions, which do no longer match the IOV requirement -void ConditionsIOVPool::__update_expired(ConditionsDataLoader& loader, - ConditionsPool& new_pool, - RangeConditions& updates, - const IOV& required_validity) { - - RangeConditions upda; - for(RangeConditions::const_iterator i=updates.begin(); i!=updates.end(); ++i) { - Condition::Object* condition = (*i).ptr(); - Condition c = new_pool.exists(condition); - if ( c.isValid() ) { - upda.push_back(c); - continue; - } - size_t items = loader.load(condition->detector,condition->name,required_validity,upda); - if ( items < 1 ) { - // Error: no such condition - except("ConditionsManager","+++ update_expired: Cannot update condition %s.%s [%s] to iov:%s.", - condition->detector.path().c_str(), condition->name.c_str(), - condition->iov->str().c_str(), required_validity.str().c_str()); - } - } - updates = upda; -} diff --git a/DDCond/src/ConditionsInterna.cpp b/DDCond/src/ConditionsInterna.cpp index 140893c53..cb516d200 100644 --- a/DDCond/src/ConditionsInterna.cpp +++ b/DDCond/src/ConditionsInterna.cpp @@ -31,6 +31,7 @@ #include "DDCond/ConditionsManager.h" #include "DDCond/ConditionsDataLoader.h" #include "DDCond/ConditionsInterna.h" +#include "DDCond/ConditionsListener.h" using namespace std; using namespace DD4hep; @@ -118,7 +119,7 @@ namespace { const IOV::Key& k = (*i)->iov->key(); if ( k.first <= test.first+1 && k.second >= test.first ) test.first = k.second; if ( k.first+1 <= test.second && k.second >= test.second ) test.second = k.first; - //printout(INFO,"Test","IOV: %d,%d --> %d,%d",k.first,k.second, test.first, test.second); + //printout(INFO,"Test","IOV: %ld,%ld --> %ld,%ld",k.first,k.second, test.first, test.second); if ( test.first >= test.second ) return true; } if ( test.first <= iov.keyData.first && test.second >= iov.keyData.second ) return false; @@ -135,6 +136,14 @@ namespace { } } + template <typename PMF> + void __callListeners(const ConditionsManagerObject::Listeners& listeners, PMF pmf, Condition& cond) { + for(ConditionsManagerObject::Listeners::const_iterator i=listeners.begin(); i!=listeners.end(); ++i) { + const ConditionsManagerObject::Listener& listener = *i; + (listener.first->*pmf)(cond, listener.second); + } + } + /// Helper class to be injected into the world object to allow loading from DetElements directly..... struct lcdd_cond_loader : public ConditionsLoader { ConditionsManager m_manager; @@ -145,21 +154,8 @@ namespace { return m_manager->get(element, key, iov); } }; - - int install_cond_mgr (Geometry::LCDD& lcdd, int /* argc */, char** /* argv */) { - typedef Interna::ConditionsManagerObject ConditionsManagerObject; - Handle<ConditionsManagerObject> mgr(lcdd.extension<ConditionsManagerObject>(false)); - if ( !mgr.isValid() ) { - ConditionsManager mgr_handle(lcdd); - lcdd.addExtension<ConditionsManagerObject>(mgr_handle.ptr()); - printout(INFO,"ConditionsManager","+++ Successfully installed conditions manager instance."); - } - return 1; - } } -DECLARE_APPLY(DD4hepConditionsManagerInstaller,install_cond_mgr) - /// Standard constructor ConditionsManagerObject::ConditionsManagerObject(LCDD& lcdd) : NamedObject(), m_lcdd(lcdd), m_iovTypes(), m_pool(), @@ -171,8 +167,8 @@ ConditionsManagerObject::ConditionsManagerObject(LCDD& lcdd) declareProperty("MaxIOVTypes", m_maxIOVTypes=32); declareProperty("PoolType", m_poolType = ""); declareProperty("UpdatePoolType", m_updateType = "DD4hep_ConditionsLinearUpdatePool"); - declareProperty("ReplacementPoolType", m_replType = "DD4hep_ConditionsLinearReplacementPool"); - declareProperty("LoaderType", m_loaderType = "multi"); + declareProperty("UserPoolType", m_userType = "DD4hep_ConditionsLinearUserPool"); + declareProperty("LoaderType", m_loaderType = "multi"); m_iovTypes.resize(m_maxIOVTypes,IOVType()); m_pool.resize(m_maxIOVTypes,0); } @@ -186,10 +182,10 @@ ConditionsManagerObject::~ConditionsManagerObject() { void ConditionsManagerObject::initialize() { if ( !m_updatePool.get() ) { string typ = "DD4hep_Conditions_"+m_loaderType+"_Loader"; - char* argv[] = {(char*)"ConditionsDataLoader", (char*)this, 0}; - m_loader.adopt(createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv)); - - m_updatePool.adopt(createPlugin<UpdatePool>(m_updateType,m_lcdd)); + const void* argv_loader[] = {"ConditionsDataLoader", this, 0}; + const void* argv_pool[] = {this, 0}; + m_loader.adopt(createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv_loader)); + m_updatePool.adopt(createPlugin<UpdatePool>(m_updateType,m_lcdd,1,argv_pool)); if ( !m_updatePool.get() ) { except("ConditionsManager","+++ The update pool of type %s cannot be created. [%s]", m_updateType.c_str(),Errors::noSys().c_str()); @@ -202,6 +198,35 @@ void ConditionsManagerObject::initialize() { } } +void ConditionsManagerObject::registerCallee(Listeners& listeners, const Listener& callee, bool add) { + if ( add ) { + listeners.insert(callee); + return; + } + Listeners::iterator i=listeners.find(callee); + if ( i != listeners.end() ) listeners.erase(i); +} + +/// (Un)Registration of conditions listeners with callback when a new condition is registered +void ConditionsManagerObject::callOnRegister(const Listener& callee, bool add) { + registerCallee(m_onRegister, callee, add); +} + +/// (Un)Registration of conditions listeners with callback when a condition is de-registered +void ConditionsManagerObject::callOnRemove(const Listener& callee, bool add) { + registerCallee(m_onRemove, callee, add); +} + +/// Call this when a condition is registered to the cache +void ConditionsManagerObject::onRegister(Condition condition) { + __callListeners(m_onRegister, &ConditionsListener::onRegisterCondition, condition); +} + +/// Call this when a condition is deregistered from the cache +void ConditionsManagerObject::onRemove(Condition condition) { + __callListeners(m_onRemove, &ConditionsListener::onRemoveCondition, condition); +} + /// Register new IOV type if it does not (yet) exist. pair<bool, const IOVType*> ConditionsManagerObject::registerIOVType(size_t iov_type, const string& iov_name) { if ( iov_type<m_iovTypes.size() ) { @@ -243,8 +268,8 @@ const IOVType* ConditionsManagerObject::iovType (const string& iov_name) const return 0; } -/// Register IOV using new string data -ConditionsPool* ConditionsManagerObject::registerIOV(const string& data) { +/// Create IOV from string +void ConditionsManagerObject::fromString(const std::string& data, IOV& iov) { size_t id1 = data.find(','); size_t id2 = data.find('#'); if ( id2 == string::npos ) { @@ -254,9 +279,9 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const string& data) { IOV::Key key; int nents = 0; if ( id1 != string::npos ) - nents = ::sscanf(data.c_str(),"%d,%d#",&key.first,&key.second) == 2 ? 2 : 0; + nents = ::sscanf(data.c_str(),"%ld,%ld#",&key.first,&key.second) == 2 ? 2 : 0; else { - nents = ::sscanf(data.c_str(),"%d#",&key.first) == 1 ? 1 : 0; + nents = ::sscanf(data.c_str(),"%ld#",&key.first) == 1 ? 1 : 0; key.second = key.first; } if ( nents == 0 ) { @@ -272,13 +297,23 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const string& data) { except("ConditionsManager","+++ Unknown IOV type requested from data: %s. [%s]", data.c_str(),Errors::invalidArg().c_str()); } + iov.type = typ->type; + iov.iovType = typ; + iov.set(key); +} + +/// Register IOV using new string data +ConditionsPool* ConditionsManagerObject::registerIOV(const string& data) { + IOV iov(0); + // Convert string to IOV + fromString(data, iov); // IOV read and checked. Now register it. - return registerIOV(*typ, key); + // The validity of iov->iovType is already ensured in 'fromString' + return registerIOV(*iov.iovType, iov.keyData); } /// Register IOV with type and key ConditionsPool* ConditionsManagerObject::registerIOV(const IOVType& typ, IOV::Key key) { - // IOV read and checked. Now register it, but always locked! ConditionsIOVPool* pool = m_pool[typ.type]; dd4hep_lock_t lock(m_poolLock); @@ -289,7 +324,8 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const IOVType& typ, IOV::Ke if ( i != pool->entries.end() ) { return (*i).second; } - ConditionsPool* cond_pool = createPlugin<ConditionsPool>(m_poolType,m_lcdd); + const void* argv_pool[] = {this, 0}; + ConditionsPool* cond_pool = createPlugin<ConditionsPool>(m_poolType,m_lcdd,1,argv_pool); IOV* iov = new IOV(&typ); iov->type = typ.type; iov->keyData = key; @@ -298,6 +334,26 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const IOVType& typ, IOV::Ke return cond_pool; } +/// Register new condition with the conditions store. Unlocked version, not multi-threaded +bool ConditionsManagerObject::registerUnlocked(ConditionsPool* pool, Condition cond) { + if ( pool && cond.isValid() ) { + ConditionsIOVPool* iov_pool = m_pool[pool->iov->type]; + iov_pool->addKey(cond); + cond->pool = pool; + cond->iov = pool->iov; + pool->insert(cond); + __callListeners(m_onRegister, &ConditionsListener::onRegisterCondition, cond); + return true; + } + else if ( !pool ) + except("ConditionsManager","+++ Unknown Conditions pool to register entry. [%s]", + Errors::invalidArg().c_str()); + else if ( !cond.isValid() ) + except("ConditionsManager","+++ Invalid condition objects may not be registered. [%s]", + Errors::invalidArg().c_str()); + return false; +} + /// Set a single conditions value to be managed. /// Requires external lock on update pool! Condition ConditionsManagerObject::__queue_update(Entry* e) { @@ -314,19 +370,28 @@ Condition ConditionsManagerObject::__queue_update(Entry* e) { return Condition(); } -/// Age conditions, which are no longer used and to be removed eventually -void ConditionsManagerObject::age() { - //call_member_func(m_pool, &ConditionsPool::age); -} - /// Clean conditions, which are above the age limit. -void ConditionsManagerObject::clean() { - //call_member_func(m_pool, &ConditionsPool::clean); +int ConditionsManagerObject::clean(const IOVType* typ, int max_age) { + int count = 0; + dd4hep_lock_t lock(m_updateLock); + ConditionsIOVPool* pool = m_pool[typ->type]; + if ( pool ) { + count += pool->clean(max_age); + } + return count; } /// Full cleanup of all managed conditions. -void ConditionsManagerObject::clear() { - //call_member_func(m_pool, &ConditionsPool::clear); +pair<int,int> ConditionsManagerObject::clear() { + pair<int,int> count(0,0); + for( TypedConditionPool::iterator i=m_pool.begin(); i != m_pool.end(); ++i) { + ConditionsIOVPool* p = *i; + if ( p ) { + ++count.first; + count.second += p->clean(0); + } + } + return count; } /// Push all pending updates to the conditions store @@ -353,36 +418,50 @@ void ConditionsManagerObject::pushUpdates() { } /// Prepare all updates to the clients with the defined IOV -void ConditionsManagerObject::prepare(const IOV& required_validity) { +long ConditionsManagerObject::prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& up) { const IOVType* typ = check_iov_type<Discrete>(this, &required_validity); if ( typ ) { - ConditionsPool* cp = 0; + RangeConditions valid, expired; ConditionsIOVPool* pool = m_pool[typ->type]; - if ( pool ) {{ - dd4hep_lock_t lock(m_poolLock); - cp = registerIOV(*typ, required_validity.key()); - if ( !cp->updates ) - cp->updates = createPlugin<ReplacementPool>(m_replType,m_lcdd); - } - /// First push any pending updates and register them to pending pools... - pushUpdates(); - RangeConditions updates; - pool->__select_expired(required_validity, updates); - pool->__update_expired(*m_loader, *cp, updates, required_validity); - cp->updates->insert(updates); + if ( 0 == up.get() || up->pool_type != ConditionsPool::USER_POOL_TYPE ) { + const void* argv_pool[] = {this, 0}; + ConditionsPool* cp = createPlugin<ConditionsPool>(m_userType,m_lcdd,1,argv_pool); + up.adopt(cp); } - return; + UserPool *user_pool = (UserPool*)up.get(); + if ( user_pool->pool_type != UserPool::poolType() ) { + except("ConditionsManager","+++ Unknown User POOL type:%d", + user_pool->pool_type, Errors::invalidArg().c_str()); + } + /// First push any pending updates and register them to pending pools... + IOV pool_iov(typ); + pool_iov.reset(); + pool_iov.invert(); + + pushUpdates(); + pool->select(required_validity, valid, expired, pool_iov); + user_pool->clear(); + user_pool->insert(valid); + long num_expired = (long)expired.size(); + if ( num_expired > 0 ) { + m_loader->update(required_validity, expired, pool_iov); + user_pool->insert(expired); + } + user_pool->setValidity(pool_iov); + return num_expired; } except("ConditionsManager","+++ Unknown IOV type requested to enable conditions. [%s]", Errors::invalidArg().c_str()); + return -1; } /// Enable all updates to the clients with the defined IOV -void ConditionsManagerObject::enable(const IOV& required_validity) { +long ConditionsManagerObject::enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool) { if ( !locked ) { ConditionsIOVPool* pool = m_pool[required_validity.type]; if ( pool ) { - ReplacementPool* rep_pool = 0; +#if 0 + UserPool* rep_pool = 0; pushUpdates(); { dd4hep_lock_t lock(m_poolLock); @@ -396,13 +475,15 @@ void ConditionsManagerObject::enable(const IOV& required_validity) { RangeConditions entries; rep_pool->popEntries(entries); __push_immediate(entries); - return; +#endif + return 0; } except("ConditionsManager","+++ Unknown IOV type requested to enable conditions. [%s]", Errors::invalidArg().c_str()); } except("ConditionsManager","+++ Cannot enable new conditions for IOV:%s in locked state! [%s]", required_validity.str().c_str(), Errors::invalidArg().c_str()); + return 0; } /// Register a new managed condition @@ -425,9 +506,12 @@ void ConditionsManagerObject::registerCondition(Condition c) { (*it).second->insert(c); return; } - ConditionsPool* cp = createPlugin<ConditionsPool>(m_poolType,m_lcdd); + const void* argv_pool[] = {this, 0}; + ConditionsPool* cp = createPlugin<ConditionsPool>(m_poolType,m_lcdd,1,argv_pool); pool->entries.insert(make_pair(iov->keyData,cp)); + pool->addKey(c); cp->insert(c); + onRegister(c); } return; } @@ -439,8 +523,8 @@ bool ConditionsManagerObject::__find(DetElement det, const std::string& cond, const IOV& req_validity, RangeConditions& conditions) { - ConditionsIOVPool* p = 0; { + ConditionsIOVPool* p = 0; dd4hep_lock_t locked_action(m_poolLock); p = m_pool[req_validity.type]; // Existence already checked by caller! p->__find(det, cond, req_validity, conditions); @@ -458,8 +542,8 @@ bool ConditionsManagerObject::__find_range(DetElement det, const IOV& req_validity, RangeConditions& conditions) { - ConditionsIOVPool* p = 0; { + ConditionsIOVPool* p = 0; dd4hep_lock_t locked_action(m_poolLock); p = m_pool[req_validity.type]; // Existence alread checked by caller! p->__find_range(det, cond, req_validity, conditions); diff --git a/DDCond/src/ConditionsListener.cpp b/DDCond/src/ConditionsListener.cpp new file mode 100644 index 000000000..fe1b92e32 --- /dev/null +++ b/DDCond/src/ConditionsListener.cpp @@ -0,0 +1,26 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DDCond/ConditionsListener.h" + +using namespace DD4hep::Conditions; + +/// Default constructor +ConditionsListener::ConditionsListener() { +} + +/// Default destructor +ConditionsListener::~ConditionsListener() { +} diff --git a/DDCond/src/ConditionsManager.cpp b/DDCond/src/ConditionsManager.cpp index 488797a58..2b8733843 100644 --- a/DDCond/src/ConditionsManager.cpp +++ b/DDCond/src/ConditionsManager.cpp @@ -20,6 +20,7 @@ #include "DDCond/ConditionsInterna.h" #include "DDCond/ConditionsManager.h" +#include "DDCond/ConditionsPool.h" using namespace std; using namespace DD4hep; @@ -48,7 +49,6 @@ ConditionsManager::ConditionsManager(LCDD& lcdd) { /// Default destructor ConditionsManager::~ConditionsManager() { - access()->clear(); } /// Access to the property manager @@ -71,7 +71,22 @@ pair<bool, const IOVType*> ConditionsManager::registerIOVType(size_t iov_type, const string& iov_name) { return access()->registerIOVType(iov_type, iov_name); } - + +/// Access the availible/known IOV types +const ConditionsManager::IOVTypes& ConditionsManager::iovTypes() const { + return access()->iovTypes(); +} + +/// Access the used/registered IOV types +const vector<const IOVType*> ConditionsManager::iovTypesUsed() const { + Object* obj = access(); + vector<const IOVType*> result; + const IOVTypes& types = obj->iovTypes(); + for(IOVTypes::const_iterator i=types.begin(); i!=types.end(); ++i) + if ( int((*i).type) != IOVType::UNKNOWN_IOV ) result.push_back(&(*i)); + return result; +} + /// Access IOV by its type const IOVType* ConditionsManager::iovType (size_t iov_type) const { return access()->iovType(iov_type); @@ -82,14 +97,40 @@ const IOVType* ConditionsManager::iovType (const string& iov_name) const { return access()->iovType(iov_name); } -/// Age conditions, which are no longer used and to be removed eventually -void ConditionsManager::age() { - access()->age(); +/// Access conditions pool by iov type +ConditionsIOVPool* ConditionsManager::iovPool(const IOVType& type) const { + Object* obj = access(); + if ( int(type.type) != IOVType::UNKNOWN_IOV && type.type < obj->m_pool.size() ) { + ConditionsIOVPool* pool = obj->m_pool[type.type]; + if ( pool ) { + return pool; + } + } + except("ConditionsManager","+++ Attempt to access invalid iov pool of type:%d. [%s]", + type.type, Errors::linkRange().c_str()); + return 0; +} + +/// Create IOV from string +void ConditionsManager::fromString(const string& iov_str, IOV& iov) { + access()->fromString(iov_str, iov); +} + +/// Register new condition with the conditions store. Unlocked version, not multi-threaded +bool ConditionsManager::registerUnlocked(const IOVType* type, IOV::Key key, Condition cond) { + Object* obj = access(); + ConditionsPool* pool = obj->registerIOV(*type, key); + return obj->registerUnlocked(pool, cond); +} + +/// Register new condition with the conditions store. Unlocked version, not multi-threaded +bool ConditionsManager::registerUnlocked(ConditionsPool* pool, Condition cond) { + return access()->registerUnlocked(pool, cond); } /// Clean conditions, which are above the age limit. -void ConditionsManager::clean() { - access()->clean(); +void ConditionsManager::clean(const IOVType* typ, int max_age) { + access()->clean(typ, max_age); } /// Full cleanup of all managed conditions. @@ -133,13 +174,13 @@ void ConditionsManager::unlock() { } /// Enable all updates to the clients with the defined IOV -void ConditionsManager::enable(const IOV& required_validity) { - access()->enable(required_validity); +long ConditionsManager::enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool) { + return access()->enable(required_validity, user_pool); } /// Prepare all updates to the clients with the defined new IOV. Changes are not yet applied -void ConditionsManager::prepare(const IOV& required_validity) { - access()->prepare(required_validity); +long ConditionsManager::prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool) { + return access()->prepare(required_validity, user_pool); } /// Retrieve a condition given the conditions path = <Detector Element path>.<conditions name> diff --git a/DDCond/src/ConditionsPool.cpp b/DDCond/src/ConditionsPool.cpp index ebed15f67..4e726197f 100644 --- a/DDCond/src/ConditionsPool.cpp +++ b/DDCond/src/ConditionsPool.cpp @@ -14,27 +14,30 @@ // Framework include files #include "DD4hep/Handle.inl" +#include "DD4hep/Printout.h" #include "DD4hep/InstanceCount.h" #include "DD4hep/objects/ConditionsInterna.h" #include "DDCond/ConditionsPool.h" #include "DDCond/ConditionsEntry.h" +#include "DDCond/ConditionsInterna.h" using std::string; +using namespace DD4hep; using namespace DD4hep::Conditions; DD4HEP_INSTANTIATE_HANDLE_NAMED(ConditionsPool); /// Default constructor -ConditionsPool::ConditionsPool() - : NamedObject(), iovType(0), iov(0), updates(0), age_value(AGE_NONE) +ConditionsPool::ConditionsPool(ConditionsManager mgr) + : NamedObject(), m_manager(mgr), + iovType(0), iov(0), age_value(AGE_NONE), pool_type(NO_POOL_TYPE) { InstanceCount::increment(this); } /// Default destructor ConditionsPool::~ConditionsPool() { - DD4hep::deletePtr(updates); // Should, but cannot clear here, since clear is a virtual overload. InstanceCount::decrement(this); } @@ -55,9 +58,39 @@ Condition ConditionsPool::create(ConditionsPool* pool, const Entry* entry) { return c; } +/// Print pool basics +void ConditionsPool::print(const string& opt) const { + const IOVType* iov_type = iov->iovType; + if ( iov_type->name == "epoch" ) { + time_t since = iov->key().first; + time_t until = iov->key().second; + char c_since[64], c_until[64]; + struct tm time_buff; + ::strftime(c_since,sizeof(c_since),"%d-%m-%Y %H:%M:%S",::gmtime_r(&since,&time_buff)); + ::strftime(c_until,sizeof(c_until),"%d-%m-%Y %H:%M:%S",::gmtime_r(&until,&time_buff)); + printout(INFO,"Conditions","+++ %s Conditions for pool with IOV: %s(%d) age:%3d [%4d entries] [%s -> %s] ", + opt.c_str(), iov_type->name.c_str(), iov_type->type, age_value, count(), c_since, c_until); + } + else { + printout(INFO,"Example","+++ %s Conditions for pool with IOV: %-32s age:%3d [%4d entries]", + opt.c_str(), iov->str().c_str(), age_value, count()); + } +} + +/// Listener invocation when a condition is registered to the cache +void ConditionsPool::onRegister(Condition condition) { + m_manager.ptr()->onRegister(condition); +} + +/// Listener invocation when a condition is deregistered from the cache +void ConditionsPool::onRemove(Condition condition) { + m_manager.ptr()->onRemove(condition); +} + /// Default constructor -UpdatePool::UpdatePool() : ConditionsPool() +UpdatePool::UpdatePool(ConditionsManager mgr) : ConditionsPool(mgr) { + pool_type = UPDATE_POOL_TYPE; } /// Default destructor @@ -65,9 +98,10 @@ UpdatePool::~UpdatePool() { } /// Default constructor -ReplacementPool::ReplacementPool() : ConditionsPool() { +UserPool::UserPool(ConditionsManager mgr) : ConditionsPool(mgr) { + pool_type = USER_POOL_TYPE; } /// Default destructor. -ReplacementPool::~ReplacementPool() { +UserPool::~UserPool() { } diff --git a/DDCond/src/ConditionsTest.cpp b/DDCond/src/ConditionsTest.cpp index d93a8c555..d017bb8f1 100644 --- a/DDCond/src/ConditionsTest.cpp +++ b/DDCond/src/ConditionsTest.cpp @@ -14,7 +14,8 @@ // Framework include files #include "DD4hep/DetectorTools.h" -#include "ConditionsTest.h" +#include "DDCond/ConditionsTest.h" +#include "DD4hep/objects/ConditionsInterna.h" // C/C++ include files #include <vector> @@ -178,7 +179,7 @@ Test::TestEnv::TestEnv(LCDD& _lcdd, const string& detector_name) manager["LoaderType"] = "multi"; manager["PoolType"] = "DD4hep_ConditionsLinearPool"; manager["UpdatePoolType"] = "DD4hep_ConditionsLinearUpdatePool"; - manager["ReplacementPoolType"] = "DD4hep_ConditionsLinearReplacementPool"; + manager["UserPoolType"] = "DD4hep_ConditionsLinearUserPool"; manager->initialize(); detector = lcdd.detector(detector_name); if ( detector.isValid() ) { @@ -200,12 +201,13 @@ DetElement Test::TestEnv::daughter(const string& sub_path) const { return DD4hep::Geometry::DetectorTools::findDaughterElement(detector,sub_path); } -void Test::TestEnv::add_xml_data_source(const string& file) { +void Test::TestEnv::add_xml_data_source(const string& file, const string& iov_str) { string source = "xml:"+string(::getenv("DD4hepINSTALL"))+file; - this->loader->addSource(source); + IOV iov(0); + this->manager->fromString(iov_str, iov); + this->loader->addSource(source, iov); } - void Test::TestEnv::dump_conditions_pools() { typedef RangeConditions _R; diff --git a/DDCond/src/ConditionsExample.cpp b/DDCond/src/plugins/ConditionsExample.cpp similarity index 88% rename from DDCond/src/ConditionsExample.cpp rename to DDCond/src/plugins/ConditionsExample.cpp index 9b3cc3482..b78f049ae 100644 --- a/DDCond/src/ConditionsExample.cpp +++ b/DDCond/src/plugins/ConditionsExample.cpp @@ -13,7 +13,7 @@ //========================================================================== // Framework include files -#include "ConditionsTest.h" +#include "DDCond/ConditionsTest.h" using namespace std; using namespace DD4hep; @@ -64,16 +64,15 @@ namespace { } void print_tpc_discrete_conditions(Test::TestEnv& env, int epoch_min, int epoch_max, int run_min, int run_max) { + dd4hep_ptr<ConditionsPool> pool_run, pool_epoch; IOV iov_epoch(env.epoch), iov_run(env.run); - iov_epoch.keyData.first = epoch_min; - iov_epoch.keyData.second = epoch_max; - iov_run.keyData.first = run_min; - iov_run.keyData.second = run_max; - - env.manager.prepare(iov_run); - env.manager.enable(iov_run); - env.manager.prepare(iov_epoch); - env.manager.enable(iov_epoch); + iov_epoch.set(epoch_min, epoch_max); + iov_run.set(run_min, run_max); + + env.manager.prepare(iov_run, pool_run); + env.manager.enable(iov_run, pool_run); + env.manager.prepare(iov_epoch, pool_epoch); + env.manager.enable(iov_epoch, pool_epoch); print_tpc_discrete_conditions(env, iov_epoch, iov_run); } @@ -86,8 +85,7 @@ namespace { void print_tpc_range_conditions(Test::TestEnv& env, int run_min, int run_max) { RangeConditions cond; IOV iov_run(env.run); - iov_run.keyData.first = run_min; - iov_run.keyData.second = run_max; + iov_run.set(run_min, run_max); try { cond = env.manager.getRange(env.detector,"TPC_A_align",iov_run); Test::print_conditions<void>(cond); @@ -108,17 +106,17 @@ namespace { printout(INFO,"Example1","+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); Test::TestEnv env(lcdd, "TPC"); - env.add_xml_data_source("/examples/Conditions/xml/TPC.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml"); + env.add_xml_data_source("/examples/Conditions/xml/TPC.xml","1396887257,1396887257#epoch"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml","563543#run"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml","234567#run"); print_tpc_discrete_conditions(env); env.dump_conditions_pools(); print_tpc_range_conditions(env,234567,563543); // Should fail ! print_tpc_range_conditions(env,123456,563543); // Should fail ! - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml","0,999999#run"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml","123456#run"); print_tpc_range_conditions(env,123456,900000); // Now it should succeed return 1; } @@ -141,37 +139,36 @@ namespace { printout(INFO,"Example1","+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); Test::TestEnv env(lcdd, "TPC"); - env.add_xml_data_source("/examples/Conditions/xml/TPC.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml"); - env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml"); + env.add_xml_data_source("/examples/Conditions/xml/TPC.xml","1396887257,1396887257#epoch"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml","563543#run"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml","234567#run"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml","0,999999#run"); + env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml","123456#run"); IOV iov_epoch(env.epoch), iov_run(env.run); - iov_epoch.keyData.first = 1396887257; - iov_epoch.keyData.second = 1396887257; - iov_run.keyData.first = 563543; - iov_run.keyData.second = 563543; - - env.manager.prepare(iov_run); - env.manager.enable(iov_run); - env.manager.prepare(iov_epoch); - env.manager.enable(iov_epoch); + dd4hep_ptr<ConditionsPool> pool_run, pool_epoch; + iov_epoch.set(1396887257); + iov_run.set(563543); + + env.manager.prepare(iov_run, pool_run); + env.manager.enable(iov_run, pool_run); + env.manager.prepare(iov_epoch, pool_epoch); + env.manager.enable(iov_epoch, pool_epoch); print_tpc_epoch_conditions(env, iov_epoch); print_tpc_run_conditions(env, iov_run, true); printout(INFO,"Example1","==================================================================="); printout(INFO,"Example1","==================================================================="); - iov_run.keyData.first = iov_run.keyData.second = 123456; - env.manager.prepare(iov_run); - iov_run.keyData.first = iov_run.keyData.second = 563543; + iov_run.set(123456); + env.manager.prepare(iov_run, pool_run); + iov_run.set(563543); print_tpc_run_conditions(env, iov_run, false); printout(INFO,"Example1","==================================================================="); printout(INFO,"Example1","==================================================================="); - iov_run.keyData.first = iov_run.keyData.second = 123456; - env.manager.enable(iov_run); + iov_run.set(123456); + env.manager.enable(iov_run, pool_run); print_tpc_run_conditions(env, iov_run, true); return 1; } diff --git a/DDCond/src/ConditionsLinearPool.cpp b/DDCond/src/plugins/ConditionsLinearPool.cpp similarity index 66% rename from DDCond/src/ConditionsLinearPool.cpp rename to DDCond/src/plugins/ConditionsLinearPool.cpp index f3650360c..97f5ef50f 100644 --- a/DDCond/src/ConditionsLinearPool.cpp +++ b/DDCond/src/plugins/ConditionsLinearPool.cpp @@ -15,7 +15,10 @@ #define DDCOND_CONDITIONSLINEARPOOL_H // Framework include files +#include "DD4hep/objects/DetectorInterna.h" +#include "DD4hep/objects/ConditionsInterna.h" #include "DDCond/ConditionsPool.h" +#include "DDCond/ConditionsInterna.h" // C/C++ include files #include <list> @@ -31,44 +34,57 @@ namespace DD4hep { * * \author M.Frank * \version 1.0 - * \ingroup DD4HEP_GEOMETRY * \ingroup DD4HEP_CONDITIONS */ template<typename MAPPING, typename BASE> class ConditionsLinearPool : public BASE { protected: + typedef BASE Base; typedef MAPPING Mapping; - Mapping m_conditions; - + Mapping m_conditions; public: /// Default constructor - ConditionsLinearPool(); + ConditionsLinearPool(ConditionsManager mgr); /// Default destructor virtual ~ConditionsLinearPool(); + /// Total entry count + virtual int count() const { + return (int)m_conditions.size(); + } + /// Check if detector and name match + bool __match(const DetElement::Object* det, int hash, const Condition::Object* c) const { + return det == c->detector.ptr() && hash == c->hash; + } + /// Register a new condition to this pool virtual void insert(Condition condition) { - m_conditions.insert(m_conditions.end(),condition.ptr()); + Condition::Object* c = condition.access(); + m_conditions.insert(m_conditions.end(),c); } /// Register a new condition to this pool. May overload for performance reasons. virtual void insert(RangeConditions& new_entries) { - for(RangeConditions::iterator i=new_entries.begin(); i!=new_entries.end(); ++i) - m_conditions.insert(m_conditions.end(),(*i).ptr()); + for(RangeConditions::iterator i=new_entries.begin(); i!=new_entries.end(); ++i) { + Condition::Object* c = (*i).access(); + m_conditions.insert(m_conditions.end(),c); + } } /// Register a new condition to this pool virtual Condition insertEntry(ConditionsPool* pool, Entry* cond) { - MAPPING& m = this->ConditionsLinearPool<MAPPING,BASE>::m_conditions; Condition c = this->create(pool, cond); - m.insert(m.end(),c.ptr()); + this->insert(c); return c; } /// Full cleanup of all managed conditions. virtual void clear() { - for_each(m_conditions.begin(), m_conditions.end(), DD4hep::deleteObject<Condition::Object>); + for(typename Mapping::iterator i=m_conditions.begin(); i != m_conditions.end(); ++i) + this->ConditionsPool::onRemove(*i); + for(typename Mapping::iterator i=m_conditions.begin(); i != m_conditions.end(); ++i) + DD4hep::deleteObject<Condition::Object>(*i); m_conditions.clear(); } @@ -78,7 +94,7 @@ namespace DD4hep { int hash = DD4hep::hash32(cond_name); DetElement::Object* ptr = det.ptr(); for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i) - if ( this->ConditionsPool::match(ptr,hash,(*i)) ) return *i; + if ( __match(ptr,hash,(*i)) ) return *i; } return Condition(); } @@ -88,7 +104,7 @@ namespace DD4hep { int hash = DD4hep::hash32(test->name); DetElement::Object* ptr = test->detector.ptr(); for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i) { - if ( this->ConditionsPool::match(ptr,hash,(*i)) ) return *i; + if ( __match(ptr,hash,(*i)) ) return *i; } return Condition(); } @@ -99,7 +115,7 @@ namespace DD4hep { int hash = DD4hep::hash32(cond_name); DetElement::Object* ptr = det.ptr(); for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i) - if ( this->ConditionsPool::match(ptr,hash,(*i)) ) result.push_back(*i); + if ( __match(ptr,hash,(*i)) ) result.push_back(*i); } } @@ -127,6 +143,13 @@ namespace DD4hep { result.push_back(*i); } + /// Select the conditons, used also by the DetElement of the condition + virtual void select_all(ConditionsPool& selection_pool) { + for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i) { + selection_pool.insert(*i); + } + } + /// Select the conditions matching the DetElement and the conditions name virtual void select_range(DetElement det, const std::string& cond_name, @@ -139,7 +162,7 @@ namespace DD4hep { int hash = DD4hep::hash32(cond_name); DetElement::Object* ptr = det.ptr(); for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i) { - if ( this->ConditionsPool::match(ptr,hash,(*i)) ) { + if ( __match(ptr,hash,(*i)) ) { const IOV* _iov = (*i)->iov; unsigned int typ = _iov->iovType ? _iov->iovType->type : _iov->type; if ( req_typ == typ ) { @@ -157,42 +180,65 @@ namespace DD4hep { } } } - }; - - template<typename MAPPING> class ConditionsLinearReplacementPool - : public ConditionsLinearPool<MAPPING,ReplacementPool> + /// Class implementing the conditions user pool for a given IOV type + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + template<typename MAPPING> class ConditionsLinearUserPool + : public ConditionsLinearPool<MAPPING,UserPool> { + IOV m_iov; public: /// Default constructor - ConditionsLinearReplacementPool() : ConditionsLinearPool<MAPPING,ReplacementPool>() {} + ConditionsLinearUserPool(ConditionsManager mgr) + : ConditionsLinearPool<MAPPING,UserPool>(mgr), m_iov(0) + { + this->ConditionsPool::iov = &m_iov; + this->ConditionsPool::iovType = 0; + } /// Default destructor - virtual ~ConditionsLinearReplacementPool() {} - /// Full cleanup of all managed conditions. - virtual void clear() { - this->ConditionsLinearPool<MAPPING,ReplacementPool>::m_conditions.clear(); + virtual ~ConditionsLinearUserPool() {} + + /// Access the interval of validity for this user pool + virtual const IOV& validity() const { + return this->m_iov; + } + /// Update interval of validity for this user pool (should only be called by ConditionsManager) + virtual void setValidity(const IOV& value) { + this->m_iov = value; + this->ConditionsPool::iovType = m_iov.iovType; } - /// Pop conditions. May overloade for performance reasons! - virtual void popEntries(RangeConditions& entries) { - MAPPING& m = this->ConditionsLinearPool<MAPPING,ReplacementPool>::m_conditions; - if ( !m.empty() ) { - for(typename MAPPING::iterator i=m.begin(); i!=m.end(); ++i) - entries.push_back((*i)); - m.clear(); - } + /// Full cleanup of all managed conditions. + virtual void clear() { + m_iov = IOV(0); + this->ConditionsLinearPool<MAPPING,UserPool>::m_conditions.clear(); } }; + /// Class implementing the conditions update pool for a given IOV type + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ template<typename MAPPING> class ConditionsLinearUpdatePool : public ConditionsLinearPool<MAPPING,UpdatePool> { public: /// Default constructor - ConditionsLinearUpdatePool() : ConditionsLinearPool<MAPPING,UpdatePool>() {} + ConditionsLinearUpdatePool(ConditionsManager mgr) + : ConditionsLinearPool<MAPPING,UpdatePool>(mgr) + { + } /// Default destructor virtual ~ConditionsLinearUpdatePool() {} @@ -231,15 +277,14 @@ namespace DD4hep { // Framework include files //#include "DDCond/ConditionsLinearPool.h" +#include "DD4hep/Printout.h" #include "DD4hep/InstanceCount.h" -#include "DD4hep/objects/DetectorInterna.h" -#include "DD4hep/objects/ConditionsInterna.h" using namespace DD4hep::Conditions; /// Default constructor template<typename MAPPING, typename BASE> -ConditionsLinearPool<MAPPING,BASE>::ConditionsLinearPool() : BASE() { +ConditionsLinearPool<MAPPING,BASE>::ConditionsLinearPool(ConditionsManager mgr) : BASE(mgr) { InstanceCount::increment(this); } @@ -252,21 +297,29 @@ ConditionsLinearPool<MAPPING,BASE>::~ConditionsLinearPool() { #include "DD4hep/Factories.h" namespace { - void* create_vector_pool(DD4hep::Geometry::LCDD&, int, char**) - { return new ConditionsLinearPool<std::vector<Condition::Object*> , ConditionsPool>(); } - void* create_list_pool(DD4hep::Geometry::LCDD&, int, char**) - { return new ConditionsLinearPool<std::list<Condition::Object*> , ConditionsPool>(); } - void* create_replacement_pool(DD4hep::Geometry::LCDD&, int, char**) { - ReplacementPool* pool = new ConditionsLinearReplacementPool<std::vector<Condition::Object*> >(); + ConditionsManager _mgr(int argc, char** argv) { + if ( argc > 0 ) { + ConditionsManager::Object* m = (ConditionsManager::Object*)argv[0]; + return m; + } + DD4hep::except("ConditionsLinearPool","++ Insufficient arguments: arg[0] = ConditionManager!"); + return ConditionsManager(0); + } + void* create_vector_pool(DD4hep::Geometry::LCDD&, int argc, char** argv) + { return new ConditionsLinearPool<std::vector<Condition::Object*> , ConditionsPool>(_mgr(argc,argv)); } + void* create_list_pool(DD4hep::Geometry::LCDD&, int argc, char** argv) + { return new ConditionsLinearPool<std::list<Condition::Object*> , ConditionsPool>(_mgr(argc,argv)); } + void* create_user_pool(DD4hep::Geometry::LCDD&, int argc, char** argv) { + UserPool* pool = new ConditionsLinearUserPool<std::vector<Condition::Object*> >(_mgr(argc,argv)); return pool; } - void* create_update_pool(DD4hep::Geometry::LCDD&, int, char**) { - UpdatePool* pool = new ConditionsLinearUpdatePool<std::vector<Condition::Object*> >(); + void* create_update_pool(DD4hep::Geometry::LCDD&, int argc, char** argv) { + UpdatePool* pool = new ConditionsLinearUpdatePool<std::vector<Condition::Object*> >(_mgr(argc,argv)); return pool; } } -DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearPool, create_vector_pool) -DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearListPool, create_list_pool) -DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearVectorPool,create_vector_pool) -DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearReplacementPool, create_replacement_pool) -DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearUpdatePool, create_update_pool) +DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearPool, create_vector_pool) +DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearListPool, create_list_pool) +DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearVectorPool, create_vector_pool) +DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearUserPool, create_user_pool) +DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearUpdatePool, create_update_pool) diff --git a/DDCond/src/plugins/ConditionsManagerInstaller.cpp b/DDCond/src/plugins/ConditionsManagerInstaller.cpp new file mode 100644 index 000000000..5463d660b --- /dev/null +++ b/DDCond/src/plugins/ConditionsManagerInstaller.cpp @@ -0,0 +1,39 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Plugins.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Factories.h" +#include "DDCond/ConditionsManager.h" +#include "DDCond/ConditionsInterna.h" + +namespace { + using namespace DD4hep; + using namespace DD4hep::Conditions; + + int install_cond_mgr (Geometry::LCDD& lcdd, int /* argc */, char** /* argv */) { + typedef Interna::ConditionsManagerObject ConditionsManagerObject; + Handle<ConditionsManagerObject> mgr(lcdd.extension<ConditionsManagerObject>(false)); + if ( !mgr.isValid() ) { + ConditionsManager mgr_handle(lcdd); + lcdd.addExtension<ConditionsManagerObject>(mgr_handle.ptr()); + printout(INFO,"ConditionsManager","+++ Successfully installed conditions manager instance."); + } + return 1; + } +} + +DECLARE_APPLY(DD4hepConditionsManagerInstaller,install_cond_mgr) diff --git a/DDCond/src/ConditionsMultiLoader.cpp b/DDCond/src/plugins/ConditionsMultiLoader.cpp similarity index 59% rename from DDCond/src/ConditionsMultiLoader.cpp rename to DDCond/src/plugins/ConditionsMultiLoader.cpp index fff24204b..9931ea7c8 100644 --- a/DDCond/src/ConditionsMultiLoader.cpp +++ b/DDCond/src/plugins/ConditionsMultiLoader.cpp @@ -55,11 +55,11 @@ namespace DD4hep { const std::string& cond, const IOV& req_validity, RangeConditions& conditions); - size_t load_source(const std::string& nam, - DetElement det, - const std::string& cond, - const IOV& req_validity, - RangeConditions& conditions); + /// Update a range of conditions according to the required IOV + virtual size_t update(const IOV& req_validity, + RangeConditions& conditions, + IOV& conditions_validity); + ConditionsDataLoader* load_source(const std::string& nam,const IOV& req_validity); }; } /* End namespace Geometry */ } /* End namespace DD4hep */ @@ -70,6 +70,7 @@ namespace DD4hep { #include "DD4hep/Printout.h" #include "DD4hep/Factories.h" #include "DD4hep/PluginCreators.h" +#include "DD4hep/objects/ConditionsInterna.h" // Forward declartions using std::string; @@ -94,40 +95,36 @@ ConditionsMultiLoader::ConditionsMultiLoader(LCDD& lcdd, ConditionsManager mgr, ConditionsMultiLoader::~ConditionsMultiLoader() { } -size_t ConditionsMultiLoader::load_source(const std::string& nam, - DetElement det, - const std::string& cond, - const IOV& req_validity, - RangeConditions& conditions) +ConditionsDataLoader* ConditionsMultiLoader::load_source(const std::string& nam,const IOV& req_validity) { - size_t idx = nam.find(':'); - if ( idx == string::npos ) { - except("ConditionsMultiLoader","Invalid data source specification: "+nam); - } - string ident = nam.substr(0,idx); - Loaders::iterator ild = m_loaders.find(ident); - ConditionsDataLoader* loader = 0; - if ( ild == m_loaders.end() ) { - string typ = "DD4hep_Conditions_"+ident+"_Loader"; - string fac = ident+"_ConditionsDataLoader"; - char* argv[] = {(char*)fac.c_str(), (char*)m_mgr.ptr(), 0}; - loader = createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv); - if ( !loader ) { - except("ConditionsMultiLoader", - "Failed to create conditions loader of type: "+typ+" to read:"+nam); + OpenSources::iterator iop = m_openSources.find(nam); + if ( iop == m_openSources.end() ) { + size_t idx = nam.find(':'); + if ( idx == string::npos ) { + except("ConditionsMultiLoader","Invalid data source specification: "+nam); } + string ident = nam.substr(0,idx); + Loaders::iterator ild = m_loaders.find(ident); + ConditionsDataLoader* loader = 0; + if ( ild == m_loaders.end() ) { + string typ = "DD4hep_Conditions_"+ident+"_Loader"; + string fac = ident+"_ConditionsDataLoader"; + const void* argv[] = {fac.c_str(), m_mgr.ptr(), 0}; + loader = createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv); + if ( !loader ) { + except("ConditionsMultiLoader", + "Failed to create conditions loader of type: "+typ+" to read:"+nam); + } + } + else { + loader = (*ild).second; + } + loader->addSource(nam.substr(idx+1),req_validity); + m_loaders[ident] = loader; + m_openSources[nam] = loader; + return loader; } - else { - loader = (*ild).second; - } - loader->addSource(nam.substr(idx+1)); - m_loaders[ident] = loader; - m_openSources[nam] = loader; - size_t items = loader->load(det, cond, req_validity, conditions); - if ( items > 0 ) { - return items; - } - return 0; + return (*iop).second; } /// Load a condition set given a Detector Element and the conditions name according to their validity @@ -138,13 +135,14 @@ size_t ConditionsMultiLoader::load_range(DetElement det, size_t len = conditions.size(); // No better idea: Must chack all sources to find the required condition for(Sources::const_iterator i=m_sources.begin(); i != m_sources.end(); ++i) { - const string& nam = *i; - OpenSources::iterator iop = m_openSources.find(nam); - if ( iop == m_openSources.end() ) { - load_source(nam, det, cond, req_validity, conditions); - continue; + const IOV& iov = (*i).second; + if ( iov.type == req_validity.type ) { + if ( IOV::key_partially_contained(iov.keyData,req_validity.keyData) ) { + const string& nam = (*i).first; + ConditionsDataLoader* loader = load_source(nam, req_validity); + loader->load(det, cond, req_validity, conditions); + } } - (*iop).second->load(det, cond, req_validity, conditions); } return conditions.size() - len; } @@ -157,18 +155,36 @@ size_t ConditionsMultiLoader::load(DetElement det, size_t len = conditions.size(); // No better idea: Must chack all sources to find the required condition for(Sources::const_iterator i=m_sources.begin(); i != m_sources.end(); ++i) { - const string& nam = *i; - size_t items = 0; - OpenSources::iterator iop = m_openSources.find(nam); - if ( iop == m_openSources.end() ) { - items = load_source(nam, det, cond, req_validity, conditions); - if ( items > 0 ) { - return items; + const IOV& iov = (*i).second; + if ( iov.type == req_validity.type ) { + if ( IOV::key_partially_contained(iov.keyData,req_validity.keyData) ) { + const string& nam = (*i).first; + ConditionsDataLoader* loader = load_source(nam, req_validity); + loader->load(det, cond, req_validity, conditions); } - continue; } - items = (*iop).second->load(det, cond, req_validity, conditions); - if ( items > 0 ) return items; } return conditions.size() - len; } + +/// Update a range of conditions according to the required IOV +size_t ConditionsMultiLoader::update(const IOV& req_iov, + RangeConditions& updates, + IOV& conditions_validity) { + RangeConditions upda; + for(RangeConditions::const_iterator i=updates.begin(); i!=updates.end(); ++i) { + Condition::Object* cond = (*i).ptr(); + size_t items = load(cond->detector,cond->name,req_iov,upda); + if ( items < 1 ) { + // Error: no such condition + except("ConditionsManager", + "+++ update_expired: Cannot update condition %s.%s [%s] to iov:%s.", + cond->detector.path().c_str(), cond->name.c_str(), + cond->iov->str().c_str(), req_iov.str().c_str()); + } + } + updates = upda; + for(RangeConditions::const_iterator i=updates.begin(); i!=updates.end(); ++i) + conditions_validity.iov_intersection((*i).iov()); + return updates.size(); +} diff --git a/DDCond/src/ConditionsParser.cpp b/DDCond/src/plugins/ConditionsParser.cpp similarity index 99% rename from DDCond/src/ConditionsParser.cpp rename to DDCond/src/plugins/ConditionsParser.cpp index 3b066781e..3ae79d99a 100644 --- a/DDCond/src/ConditionsParser.cpp +++ b/DDCond/src/plugins/ConditionsParser.cpp @@ -1,4 +1,4 @@ -// $Id: $ +// $Id$ //========================================================================== // AIDA Detector description implementation for LCD //-------------------------------------------------------------------------- @@ -67,7 +67,7 @@ namespace DD4hep { } ConversionArg* _getArgs(void* param) { - ConversionArg* arg = (ConversionArg*)param; + ConversionArg* arg = static_cast<ConversionArg*>(param); return arg; } /// Helper: Extract the required detector element from the parsing information diff --git a/DDCond/src/plugins/ConditionsPlugins.cpp b/DDCond/src/plugins/ConditionsPlugins.cpp new file mode 100644 index 000000000..f18aab69c --- /dev/null +++ b/DDCond/src/plugins/ConditionsPlugins.cpp @@ -0,0 +1,137 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Conditions.h" +#include "DD4hep/DetFactoryHelper.h" + +#include "DDCond/ConditionsManager.h" +#include "DDCond/ConditionsIOVPool.h" +#include "DDCond/ConditionsInterna.h" +#include "DDCond/ConditionsPool.h" +#include "DDCond/ConditionsInterna.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Conditions; +using Geometry::LCDD; +using Geometry::Position; +using Geometry::DetElement; + +namespace { + + int ddcond_dump_conditions_functor(lcdd_t& lcdd, bool print_conditions) { + typedef std::vector<const IOVType*> _T; + typedef ConditionsIOVPool::Entries _E; + typedef RangeConditions _R; + ConditionsManager manager = ConditionsManager::from(lcdd); + + const _T types = manager.iovTypesUsed(); + for( _T::const_iterator i = types.begin(); i != types.end(); ++i ) { + const IOVType* type = *i; + if ( type ) { + ConditionsIOVPool* pool = manager.iovPool(*type); + if ( pool ) { + const _E& e = pool->entries; + printout(INFO,"CondPoolDump","+++ ConditionsIOVPool for type %s [%d IOV entries]", + type->str().c_str(), int(e.size())); + for (_E::const_iterator j=e.begin(); j != e.end(); ++j) { + ConditionsPool* cp = (*j).second; + cp->print(""); + if ( print_conditions ) { + _R rc; + cp->select_all(rc); + //print_conditions<void>(rc); + } + } + } + } + } + printout(INFO,"Example","SUCCESS: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + printout(INFO,"Example","SUCCESS: +++ Conditions pools successfully dumped"); + printout(INFO,"Example","SUCCESS: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + return 1; + } + + int ddcond_dump_pools(LCDD& lcdd, int /* argc */, char** /* argv */) { + return ddcond_dump_conditions_functor(lcdd,false); + } + int ddcond_dump_conditions(LCDD& lcdd, int /* argc */, char** /* argv */) { + return ddcond_dump_conditions_functor(lcdd,true); + } +} + +DECLARE_APPLY(DD4hepDDCondPoolDump,ddcond_dump_pools) +DECLARE_APPLY(DD4hepDDCondConditionsDump,ddcond_dump_conditions) + +namespace { + /// Plugin entry point. + static long synchronize_conditions(lcdd_t& lcdd, int argc, char** argv) { + if ( argc > 0 ) { + string iov_type = argv[0]; + IOV::Key::first_type iov_key = *(IOV::Key::first_type*)argv[1]; + ConditionsManager manager = ConditionsManager::from(lcdd); + const IOVType* epoch = manager.iovType(iov_type); + dd4hep_ptr<ConditionsPool> user_pool; + IOV iov(epoch); + + iov.set(iov_key); + long num_expired = manager.prepare(iov, user_pool); + if ( iov_type == "epoch" ) { + char c_evt[64]; + struct tm evt; + ::gmtime_r(&iov_key, &evt); + ::strftime(c_evt,sizeof(c_evt),"%T %F",&evt); + printout(INFO,"Conditions", + "+++ ConditionsUpdate: Updated %ld conditions... event time: %s", + num_expired, c_evt); + } + else { + printout(INFO,"Conditions", + "+++ ConditionsUpdate: Updated %ld conditions... key[%s]: %ld", + num_expired, iov_type.c_str(), iov_key); + } + manager.enable(iov, user_pool); + user_pool->print("User pool"); + manager.clean(epoch, 20); + user_pool->clear(); + return 1; + } + except("DDDB","+++ Failed update DDDB conditions. No event time argument given!"); + return 0; + } +} +DECLARE_APPLY(DD4hep_ConditionsSynchronize,synchronize_conditions) + +namespace { + /// Plugin entry point. + static long clean_conditions(lcdd_t& lcdd, int argc, char** argv) { + if ( argc > 0 ) { + string iov_type = argv[0]; + int max_age = *(int*)argv[1]; + printout(INFO,"Conditions", + "+++ ConditionsUpdate: Cleaning conditions... type:%s max age:%d", + iov_type.c_str(), max_age); + ConditionsManager manager = ConditionsManager::from(lcdd); + const IOVType* epoch = manager.iovType(iov_type); + manager.clean(epoch, max_age); + return 1; + } + except("DDDB","+++ Failed cleaning conditions. Insufficient arguments!"); + return 0; + } +} +DECLARE_APPLY(DD4hep_ConditionsClean,clean_conditions) diff --git a/DDCond/src/plugins/ConditionsUpdate.cpp b/DDCond/src/plugins/ConditionsUpdate.cpp new file mode 100644 index 000000000..4937051bb --- /dev/null +++ b/DDCond/src/plugins/ConditionsUpdate.cpp @@ -0,0 +1,15 @@ +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// \author Markus Frank +// \date 2016-02-02 +// \version 1.0 +// +//========================================================================== +// $Id$ + diff --git a/DDCond/src/ConditionsXmlLoader.cpp b/DDCond/src/plugins/ConditionsXmlLoader.cpp similarity index 83% rename from DDCond/src/ConditionsXmlLoader.cpp rename to DDCond/src/plugins/ConditionsXmlLoader.cpp index 06febf215..55ac34bb6 100644 --- a/DDCond/src/ConditionsXmlLoader.cpp +++ b/DDCond/src/plugins/ConditionsXmlLoader.cpp @@ -54,6 +54,10 @@ namespace DD4hep { const std::string& cond, const IOV& req_validity, RangeConditions& conditions); + /// Update a range of conditions according to the required IOV + virtual size_t update(const IOV& req_validity, + RangeConditions& conditions, + Conditions::IOV& iov_intersection); }; } /* End namespace Geometry */ @@ -65,6 +69,8 @@ namespace DD4hep { #include "DD4hep/Printout.h" #include "DD4hep/Factories.h" #include "DD4hep/PluginCreators.h" +#include "DD4hep/objects/ConditionsInterna.h" + #include "XML/XMLElements.h" #include "XML/DocumentHandler.h" #include "DDCond/ConditionsInterna.h" @@ -138,21 +144,21 @@ size_t ConditionsXmlLoader::load(DetElement det, { size_t len = conditions.size(); if ( m_buffer.empty() && !m_sources.empty() ) { - return load_source(*(m_sources.begin()), det, cond, req_validity, conditions); + return load_source(m_sources.begin()->first, det, cond, req_validity, conditions); } for (Buffer::iterator j=m_buffer.begin(); j!=m_buffer.end(); ++j) { Condition condition = *j; - if ( det == condition->detector && cond == condition->name ) { - if ( req_validity.contains(*condition->iov) ) { - conditions.push_back(condition); - m_buffer.erase(j); - return conditions.size()-len; + if ( det == condition->detector ) { + const IOV* iov = condition->iov; + if ( IOV::partial_match(req_validity,*iov) ) { + if ( cond == condition->name ) { + conditions.push_back(condition); + m_buffer.erase(j); + return conditions.size()-len; + } } } } - if ( !m_sources.empty() ) { - return load_source(*(m_sources.begin()), det, cond, req_validity, conditions); - } return conditions.size()-len; } @@ -163,20 +169,17 @@ size_t ConditionsXmlLoader::load_range(DetElement det, { size_t len = conditions.size(); while ( !m_sources.empty() ) { - load_source(*(m_sources.begin()), det, cond, req_validity, conditions); + load_source(m_sources.begin()->first, det, cond, req_validity, conditions); } std::vector<Condition> keep; - for (size_t j=0; j<m_buffer.size(); ++j) { - Condition condition = m_buffer[j]; - if ( det == condition->detector && cond == condition->name ) { + for (Buffer::iterator j=m_buffer.begin(); j!=m_buffer.end(); ++j) { + Condition condition = *j; + if ( det == condition->detector ) { const IOV* iov = condition->iov; - if ( IOV::same_type(req_validity,*iov) ) { - if ( IOV::key_is_contained(req_validity.key(),iov->key()) || - IOV::key_overlaps_lower_end(req_validity.key(),iov->key()) || - IOV::key_overlaps_higher_end(req_validity.key(),iov->key()) ) { - conditions.push_back(condition); - continue; - } + if ( IOV::partial_match(req_validity,*iov) ) { + if ( cond == condition->name ) { + conditions.push_back(condition); + } } } keep.push_back(condition); @@ -184,3 +187,9 @@ size_t ConditionsXmlLoader::load_range(DetElement det, m_buffer = keep; return conditions.size()-len; } + +/// Update a range of conditions according to the required IOV +size_t ConditionsXmlLoader::update(const IOV&,RangeConditions&, IOV&) { + except("ConditionsXmlLoader","+++ update: Invalid call!"); + return 0; +} diff --git a/DDCore/include/DD4hep/Conditions.h b/DDCore/include/DD4hep/Conditions.h index 8af4b3f06..f61150c78 100644 --- a/DDCore/include/DD4hep/Conditions.h +++ b/DDCore/include/DD4hep/Conditions.h @@ -73,13 +73,11 @@ namespace DD4hep { class IOV { friend class Condition; private: - /// No IOC copies! - explicit IOV(const IOV&) {} /// Initializing constructor: Does not set reference to IOVType ! explicit IOV(); public: /// Key definition - typedef std::pair<int,int> Key; + typedef std::pair<long,long> Key; const IOVType* iovType; Key keyData; @@ -89,6 +87,11 @@ namespace DD4hep { /// Initializing constructor explicit IOV(const IOVType* typ); + /// Copy constructor + explicit IOV(const IOV& copy); + /// Copy constructor + explicit IOV(const IOVType* typ, const Key& key); + /// Standard Destructor ~IOV(); /// Move the data content: 'from' will be reset to NULL @@ -101,6 +104,26 @@ namespace DD4hep { bool is_discrete() const { return keyData.first == keyData.second; } /// Get the local key of the IOV Key key() const { return keyData; } + + /// Set discrete IOV value + void set(const Key& value); + /// Set discrete IOV value + void set(Key::first_type value); + /// Set range IOV value + void set(Key::first_type val_1, Key::second_type val_2); + /// Set keys to unphysical values (LONG_MAX, LONG_MIN) + void reset(); + /// Invert the key values (first=second and second=first) + void invert(); + /// Set the intersection of this IOV with the argument IOV + void iov_intersection(const IOV& comparator); + /// Set the intersection of this IOV with the argument IOV + void iov_intersection(const IOV::Key& comparator); + /// Set the union of this IOV with the argument IOV + void iov_union(const IOV& comparator); + /// Set the union of this IOV with the argument IOV + void iov_union(const IOV::Key& comparator); + /// Check for validity containment /** Check if the caller 'iov' is of the same type and the range * is fully conained by the caller. @@ -124,6 +147,20 @@ namespace DD4hep { /// Check if IOV 'test' has an overlap on the upper interval edge with IOV 'key' static bool key_overlaps_higher_end(const Key& key, const Key& test) { return key.second >= test.first && key.second <= test.second; } + /// Check if IOV 'test' has an overlap on the upper interval edge with IOV 'key' + static bool key_partially_contained(const Key& key, const Key& test) + { + return + (test.first <= key.first && key.second >= test.second) || // test fully contained in key + (test.first <= key.first && key.first <= test.second) || // test overlaps left edge of key + (test.first <= key.second && key.second <= test.second); // test overlaps right edge of key + } + /// Check if IOV 'test' is of same type and is fully contained in iov + static bool full_match(const IOV& iov, const IOV& test) + { return same_type(iov,test) && key_is_contained(iov.keyData,test.keyData); } + /// Check if IOV 'test' is of same type and is at least partially contained in iov + static bool partial_match(const IOV& iov, const IOV& test) + { return same_type(iov,test) && key_partially_contained(iov.keyData,test.keyData); } }; @@ -155,9 +192,11 @@ namespace DD4hep { public: /// Create data block from string representation - void fromString(const std::string& rep); + bool fromString(const std::string& rep); /// Create string representation of the data block - std::string str(); + std::string str() const; + /// Access type id of the condition + const std::type_info& typeInfo() const; /// Check if object is already bound.... bool is_bound() const { return 0 != pointer; } /// Generic getter. Specify the exact type, not a polymorph type @@ -238,7 +277,7 @@ namespace DD4hep { * Note: The type definition is possible exactly once. * Any further rebindings MUST match the identical type. */ - template <typename T> Condition& bind(); + template <typename T> T& bind(); /// Generic getter. Specify the exact type, not a polymorph type template <typename T> T& get(); /// Generic getter (const version). Specify the exact type, not a polymorph type diff --git a/DDCore/include/DD4hep/InstanceCount.h b/DDCore/include/DD4hep/InstanceCount.h index 3f74373e2..9fda7e87e 100644 --- a/DDCore/include/DD4hep/InstanceCount.h +++ b/DDCore/include/DD4hep/InstanceCount.h @@ -135,5 +135,19 @@ namespace DD4hep { static void doTracing(bool value); }; + /// Helper class to count call stack depths of certain functions + /** + * Small class to count re-entrancy calls + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP + */ + template <typename T> struct Increment { + static int& counter() { static int cnt=0; return cnt; } + Increment() { ++counter(); } + ~Increment() { --counter(); } + }; + } /* End namespace DD4hep */ #endif /* DD4HEP_GEOMETRY_INSTANCECOUNT_H */ diff --git a/DDCore/include/DD4hep/LCDD.h b/DDCore/include/DD4hep/LCDD.h index 1dc401f82..2abdc39da 100644 --- a/DDCore/include/DD4hep/LCDD.h +++ b/DDCore/include/DD4hep/LCDD.h @@ -54,7 +54,6 @@ namespace DD4hep { return vs ; } - // Foward declarations class NamedObject; @@ -68,6 +67,11 @@ namespace DD4hep { BUILD_NONE = 0, BUILD_DEFAULT = 1, BUILD_SIMU = BUILD_DEFAULT, BUILD_RECO, BUILD_DISPLAY, BUILD_ENVELOPE }; + /// Namespace for the AIDA detector description toolkit supporting XML utilities + namespace XML { + class UriReader; + } + /// Namespace for the geometry part of the AIDA detector description toolkit namespace Geometry { @@ -88,6 +92,7 @@ namespace DD4hep { class LCDD { public: /// Type definition of a map of named handles + typedef XML::UriReader UriReader; typedef Handle<NamedObject> NamedHandle; typedef std::map<std::string, NamedHandle > HandleMap; typedef std::map<std::string, std::string> PropertyValues; @@ -278,11 +283,16 @@ namespace DD4hep { /// Add a field component by named reference to the detector description virtual LCDD& addField(const Ref_t& field) = 0; - /// Read compact geometry description or alignment file + /// Deprecated call (use fromXML): Read compact geometry description or alignment file virtual void fromCompact(const std::string& fname, LCDDBuildType type = BUILD_DEFAULT) = 0; /// Read any geometry description or alignment file virtual void fromXML(const std::string& fname, LCDDBuildType type = BUILD_DEFAULT) = 0; - /// + /// Read any geometry description or alignment file with external XML entity resolution + virtual void fromXML(const std::string& fname, + UriReader* entity_resolver, + LCDDBuildType type = BUILD_DEFAULT) = 0; + + /// Stupid legacy method virtual void dump() const = 0; /// Manipulate geometry using facroy converter virtual long apply(const char* factory, int argc, char** argv) = 0; diff --git a/DDCore/include/DD4hep/LCDDLoad.h b/DDCore/include/DD4hep/LCDDLoad.h index 5979065b0..ba0fdbb97 100644 --- a/DDCore/include/DD4hep/LCDDLoad.h +++ b/DDCore/include/DD4hep/LCDDLoad.h @@ -20,13 +20,19 @@ // C/C++ include files #include <stdexcept> -/* - * DD4hep namespace declaration - */ +/// Namespace for the AIDA detector description toolkit namespace DD4hep { - namespace XML { class Handle_t; } - namespace Geometry { class LCDD; } + /// Namespace for the AIDA detector description toolkit supporting XML utilities + namespace XML { + class Handle_t; + class UriReader; + } + + /// Namespace for the geometry part of the AIDA detector description toolkit + namespace Geometry { + class LCDD; + } /// Data implementation class of the LCDD interface /** @class LCDDLoad LCDDLoad.h DD4hep/LCDDLoad.h @@ -37,6 +43,7 @@ namespace DD4hep { class LCDDLoad { public: friend class Geometry::LCDD; + protected: /// Reference to the LCDD instance Geometry::LCDD* m_lcdd; @@ -44,11 +51,12 @@ namespace DD4hep { LCDDLoad(Geometry::LCDD* lcdd); /// Default destructor virtual ~LCDDLoad(); + public: - /// Adopt all data from source structure. - virtual void processXML(const std::string& fname); - /// Adopt all data from source structure. - virtual void processXML(const XML::Handle_t& base, const std::string& fname); + /// Process XML unit and adopt all data from source structure. + virtual void processXML(const std::string& fname, XML::UriReader* entity_resolver=0); + /// Process XML unit and adopt all data from source structure. + virtual void processXML(const XML::Handle_t& base, const std::string& fname, XML::UriReader* entity_resolver=0); /// Process a given DOM (sub-) tree virtual void processXMLElement(const std::string& msg_source, const XML::Handle_t& root); /// Process a given DOM (sub-) tree diff --git a/DDCore/include/DD4hep/Operators.h b/DDCore/include/DD4hep/Operators.h new file mode 100644 index 000000000..ee4185097 --- /dev/null +++ b/DDCore/include/DD4hep/Operators.h @@ -0,0 +1,68 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +#ifndef DD4HEP_DD4HEP_OPERATORS_H +#define DD4HEP_DD4HEP_OPERATORS_H + +// C/C++ include files +#include <string> + +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { + + /// Helper functor to select elements by name (using name() member method) + template <typename T> class ByName { + private: + /// Assignment operator + template <typename Q> ByName<T>& operator=(const ByName<Q>& copy) { return *this; } + public: + /// Reference name + const std::string& name; + /// Standard constructor + ByName(const std::string& nam) : name(nam) {} + /// Copy constructor + ByName(const ByName& copy) : name(copy.name) {} + /// Operator to select from object containers + bool operator()(const T& entry) const { return entry.name() == name; } + /// Operator to select from pointer containers + bool operator()(const T* entry) const { return entry->name() == name; } + }; + template <typename T> ByName<T> byName(const std::string& n) { return ByName<T>(n); } + template <typename T> ByName<T> byName(const T* o) { return ByName<T>(o->name()); } + template <typename T> ByName<T> byName(const T& o) { return ByName<T>(o.name()); } + + /// Helper functor to select elements by name (using name member variable) + template <typename T> class ByNameAttr { + private: + /// Assignment operator + template <typename Q> ByNameAttr<T>& operator=(const ByNameAttr<Q>& copy) { return *this; } + public: + /// Reference name + const std::string& name; + /// Standard constructor + ByNameAttr(const std::string& nam) : name(nam) {} + /// Copy constructor + ByNameAttr(const ByNameAttr& copy) : name(copy.name) {} + /// Operator to select from object containers + bool operator()(const T& entry) const { return entry.name == name; } + /// Operator to select from pointer containers + bool operator()(const T* entry) const { return entry->name == name; } + }; + + template <typename T> ByNameAttr<T> byNameAttr(const std::string& nam) { return ByNameAttr<T>(nam); } + template <typename T> ByNameAttr<T> byNameAttr(const T* o) { return ByNameAttr<T>(o->name); } + template <typename T> ByNameAttr<T> byNameAttr(const T& o) { return ByNameAttr<T>(o.name); } + +} // End namespace DD4hep +#endif // DD4HEP_DD4HEP_OPERATORS_H diff --git a/DDCore/include/DD4hep/PluginCreators.h b/DDCore/include/DD4hep/PluginCreators.h index 68aef2dd3..a925ebc4b 100644 --- a/DDCore/include/DD4hep/PluginCreators.h +++ b/DDCore/include/DD4hep/PluginCreators.h @@ -53,10 +53,10 @@ namespace DD4hep { return (plugin_t*)createPlugin(factory, lcdd, arg, __cast::cast); } /// Handler for factories of type: ConstructionFactory with casted return type - template <typename T> T* createPlugin(const std::string& factory, Geometry::LCDD& lcdd, int argc, char** argv) { + template <typename T> T* createPlugin(const std::string& factory, Geometry::LCDD& lcdd, int argc, const void** argv) { typedef T plugin_t; struct __cast{ static void* cast(void* p) { return &dynamic_cast<plugin_t&>(*(plugin_t*)p); } }; - return (plugin_t*)createPlugin(factory, lcdd, argc, argv, __cast::cast); + return (plugin_t*)createPlugin(factory, lcdd, argc, (char**)argv, __cast::cast); } } /* End namespace DD4hep */ diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h index ab58d895c..fb9c21060 100644 --- a/DDCore/include/DD4hep/Primitives.h +++ b/DDCore/include/DD4hep/Primitives.h @@ -278,7 +278,7 @@ namespace DD4hep { DestroyObject<typename M::mapped_type>()(p.second); } void operator()() const { - for_each(object.begin(),object.end(),(*this)); + if ( !object.empty() ) for_each(object.begin(),object.end(),(*this)); } }; template <typename M> DestroyObjects<M> destroyObjects(M& m) { @@ -302,7 +302,7 @@ namespace DD4hep { DestroyObject<typename M::key_type>()(p.first); } void operator()() const { - for_each(object.begin(),object.end(),(*this)); + if ( !object.empty() ) for_each(object.begin(),object.end(),(*this)); } }; template <typename M> DestroyFirst<M> destroyFirst(M& m) { @@ -340,7 +340,7 @@ namespace DD4hep { ReleaseObject<typename M::mapped_type>()(p.second); } void operator()() const { - for_each(object.begin(),object.end(),(*this)); + if ( !object.empty() ) for_each(object.begin(),object.end(),(*this)); } }; template <typename M> ReleaseObject<typename M::value_type> releaseObject(M&) { diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h index cdeba3c36..556fd5731 100644 --- a/DDCore/include/DD4hep/Readout.h +++ b/DDCore/include/DD4hep/Readout.h @@ -81,6 +81,8 @@ namespace DD4hep { std::vector<std::string> collectionNames() const; /// Access hit collections if present std::vector<const HitCollection*> collections() const; + /// Access number of hit collections + size_t numCollections() const; /// Assign IDDescription to readout structure void setIDDescriptor(const Ref_t& spec) const; /// Access IDDescription structure diff --git a/DDCore/include/DD4hep/objects/BasicGrammar_inl.h b/DDCore/include/DD4hep/objects/BasicGrammar_inl.h index 8210f2fb8..b996a40d3 100644 --- a/DDCore/include/DD4hep/objects/BasicGrammar_inl.h +++ b/DDCore/include/DD4hep/objects/BasicGrammar_inl.h @@ -278,21 +278,27 @@ namespace DD4hep { template<typename T> inline int eval_obj(T* p, const std::string& str) { return BasicGrammar::instance<T>().fromString(p,pre_parse_obj(str)); } + + /// User object evaluator + /// Do NOTHING version! Function present to formally satisfy code. User implementation required + template<typename T> inline int eval_none(T*, const std::string&) { + return 1; + } // Containers of objects are not handled! } // End namespace DD4hep -#define DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ -namespace DD4hep { \ +#define DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ +namespace DD4hep { \ template<> const BasicGrammar& BasicGrammar::instance<x>() { static Grammar<x> s; return s;}} -#define DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) \ - namespace DD4hep { \ +#define DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) \ + namespace DD4hep { \ template<> int Grammar<x >::evaluate(void* p, const std::string& v) const { return func ((x*)p,v); }} -#define DD4HEP_DEFINE_PARSER_GRAMMAR(x,func) \ - DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ +#define DD4HEP_DEFINE_PARSER_GRAMMAR(x,func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) #if defined(DD4HEP_HAVE_ALL_PARSERS) diff --git a/DDCore/include/DD4hep/objects/ConditionsInterna.h b/DDCore/include/DD4hep/objects/ConditionsInterna.h index f067cda6b..5cec605f5 100644 --- a/DDCore/include/DD4hep/objects/ConditionsInterna.h +++ b/DDCore/include/DD4hep/objects/ConditionsInterna.h @@ -61,7 +61,8 @@ namespace DD4hep { BOUND_DATA = 1<<2 } _DataTypes; /// Data buffer: plain data are allocated directly on this buffer - unsigned int data[16]; + /** Internal data buffer is sufficient to store any vector */ + unsigned char data[sizeof(std::vector<void*>)]; /// Destructor function -- only set if the object is valid void (*destruct)(void*); /// Constructor function -- only set if the object is valid @@ -70,19 +71,26 @@ namespace DD4hep { public: /// Data buffer type: Must be a bitmap! int type; - /// Standard initializing constructor BlockData(); + /// Copy constructor + BlockData(const BlockData& data); /// Standard Destructor ~BlockData(); + /// Assignment operator + BlockData& operator=(const BlockData& clone); /// Move the data content: 'from' will be reset to NULL - void move(BlockData& from); - /// Set data value - void bind(const BasicGrammar* grammar, + bool move(BlockData& from); + /// Bind data value + bool bind(const BasicGrammar* grammar, void (*ctor)(void*,const void*), void (*dtor)(void*)); + /// Bind data value + template <typename T> T& bind(); /// Set data value void assign(const void* ptr,const std::type_info& typ); + /// Bind grammar and assign value + template<typename T> T& set(const std::string& value); }; /// The data class behind a conditions container handle. @@ -164,6 +172,7 @@ namespace DD4hep { const IOVType* iov_type() const; /// Check if object is already bound.... bool is_bound() const { return data.is_bound(); } + bool is_traced() const { return true; } }; /// The data class behind a conditions container handle. @@ -212,7 +221,7 @@ namespace DD4hep { } /* End namespace Interna */ template <typename T> static void copyObject(void* t, const void* s) { - *((T*)t) = *((const T*)s); + new(t) T(*(const T*)s); } template <typename T> static void destructObject(void* p) { T* t = (T*)p; @@ -228,14 +237,24 @@ namespace DD4hep { if (!grammar || (grammar->type() != typeid(T))) { throw std::bad_cast(); } return *(T*)pointer; } + /// Bind data value + template <typename T> T& BlockData::bind() { + this->bind(&BasicGrammar::instance<T>(),copyObject<T>,destructObject<T>); + return *(new(this->pointer) T()); + } + /// Bind grammar and assign value + template <typename T> T& BlockData::set(const std::string& value) { + T& ret = this->bind<T>(); + if ( !value.empty() && !this->fromString(value) ) { + throw std::runtime_error("BlockData::set> Failed to bind type "+ + typeName(typeid(T))+" to condition data block."); + } + return ret; + } /// Bind the data of the conditions object to a given format. - template <typename T> Condition& Condition::bind() { + template <typename T> T& Condition::bind() { Object* o = access(); - BlockData& b = o->data; - b.bind(&BasicGrammar::instance<T>(),copyObject<T>,destructObject<T>); - new(b.pointer) T(); - if ( !o->value.empty() ) b.fromString(o->value); - return *this; + return o->data.set<T>(o->value); } /// Generic getter. Specify the exact type, not a polymorph type template <typename T> T& Condition::get() { @@ -251,11 +270,18 @@ namespace DD4hep { #define DD4HEP_DEFINE_CONDITIONS_TYPE(x) \ namespace DD4hep { namespace Conditions { \ - template Condition& Condition::bind<x>(); \ + template x& Condition::bind<x>(); \ template x& Condition::get<x>(); \ template const x& Condition::get<x>() const; \ }} +#define DD4HEP_DEFINE_EXTERNAL_CONDITIONS_TYPE(x) \ + namespace DD4hep { namespace Conditions { \ + template <> x& Condition::bind<x>(); \ + template <> x& Condition::get<x>(); \ + template <> const x& Condition::get<x>() const; \ + }} + #if defined(DD4HEP_HAVE_ALL_PARSERS) #define DD4HEP_DEFINE_CONDITIONS_CONT(x) \ DD4HEP_DEFINE_CONDITIONS_TYPE(x) \ diff --git a/DDCore/include/XML/UriReader.h b/DDCore/include/XML/UriReader.h index 3d6d3b53b..cc78156f5 100644 --- a/DDCore/include/XML/UriReader.h +++ b/DDCore/include/XML/UriReader.h @@ -34,14 +34,54 @@ namespace DD4hep { * \ingroup DD4HEP_XML */ class UriReader { + public: + struct UserContext { + UserContext() {} + virtual ~UserContext() {} + }; public: /// Default constructor UriReader() {} /// Default destructor virtual ~UriReader(); + /// Access to local context + virtual UserContext* context() { return 0; } /// Resolve a given URI to a string containing the data - virtual bool load(const std::string& system_id, std::string& data) = 0; + virtual bool load(const std::string& system_id, std::string& data); + /// Resolve a given URI to a string containing the data with context + virtual bool load(const std::string& system_id, UserContext* context, std::string& data) = 0; }; + + /// Class supporting to read data given a URI + /** + * Wrapper to read XML URI using a virtual reader instance. + * This implementation allows to externally chain an argument + * structure to the resolution function, which allows to set/retrieve + * further arguments such as e.g. conditions IOVs. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_XML + */ + class UriContextReader : public UriReader { + protected: + /// Pointer to true reader object + UriReader* m_reader; + /// Pointer to user context + UriReader::UserContext* m_context; + public: + /// Default constructor + UriContextReader(UriReader* reader, UriReader::UserContext* ctxt); + /// Default destructor + virtual ~UriContextReader(); + /// Access to local context + virtual UserContext* context() { return m_context; } + /// Resolve a given URI to a string containing the data + virtual bool load(const std::string& system_id, std::string& data); + /// Resolve a given URI to a string containing the data with context + virtual bool load(const std::string& system_id, UserContext* context, std::string& data); + }; + } /* End namespace XML */ } /* End namespace DD4hep */ #endif /* DD4HEP_XML_URIREADER_H */ diff --git a/DDCore/src/Conditions.cpp b/DDCore/src/Conditions.cpp index 8356a094f..392bdc9f2 100644 --- a/DDCore/src/Conditions.cpp +++ b/DDCore/src/Conditions.cpp @@ -19,6 +19,8 @@ #include "DD4hep/objects/DetectorInterna.h" #include "DD4hep/objects/ConditionsInterna.h" +#include <climits> + using namespace std; using namespace DD4hep::Conditions; @@ -34,14 +36,88 @@ IOV::IOV() : iovType(0), keyData(0,0), optData(0) { } /// Initializing constructor -IOV::IOV(const IOVType* typ) : iovType(typ), keyData(0,0), optData(0) { - type = typ ? typ->type : int(IOVType::UNKNOWN_IOV); +IOV::IOV(const IOVType* t) : iovType(t), keyData(0,0), optData(0) { + type = t ? t->type : int(IOVType::UNKNOWN_IOV); +} + +/// Copy constructor +IOV::IOV(const IOV& c) + : iovType(c.iovType), keyData(c.keyData), optData(c.optData), type(c.type) +{ +} + +/// Copy constructor +IOV::IOV(const IOVType* t, const Key& k) + : iovType(t), keyData(k), optData(0) +{ + type = t ? t->type : int(IOVType::UNKNOWN_IOV); } /// Standard Destructor IOV::~IOV() { } +/// Set discrete IOV value +void IOV::set(const Key& value) { + keyData = value; +} + +/// Set discrete IOV value +void IOV::set(Key::first_type value) { + keyData.first = keyData.second = value; +} + +/// Set range IOV value +void IOV::set(Key::first_type val_1, Key::second_type val_2) { + keyData.first = val_1; + keyData.second = val_2; +} + +/// Set keys to unphysical values (LONG_MAX, LONG_MIN) +void IOV::reset() { + keyData.first = LONG_MAX; + keyData.second = LONG_MIN; +} + +/// Set keys to unphysical values (LONG_MAX, LONG_MIN) +void IOV::invert() { + Key::first_type tmp = keyData.first; + keyData.first = keyData.second; + keyData.second = tmp; +} + +void IOV::iov_intersection(const IOV& validity) { + if ( !iovType ) + *this = validity; + else if ( validity.keyData.first > keyData.first ) + keyData.first = validity.keyData.first; + if ( validity.keyData.second < keyData.second ) + keyData.second = validity.keyData.second; +} + +void IOV::iov_intersection(const IOV::Key& validity) { + if ( validity.first > keyData.first ) + keyData.first = validity.first; + if ( validity.second < keyData.second ) + keyData.second = validity.second; +} + +void IOV::iov_union(const IOV& validity) { + if ( !iovType ) + *this = validity; + else if ( validity.keyData.first < keyData.first ) + keyData.first = validity.keyData.first; + if ( validity.keyData.second > keyData.second ) + keyData.second = validity.keyData.second; +} + +void IOV::iov_union(const IOV::Key& validity) { + if ( validity.first < keyData.first ) + keyData.first = validity.first; + if ( validity.second > keyData.second ) + keyData.second = validity.second; +} + /// Move the data content: 'from' will be reset to NULL void IOV::move(IOV& from) { ::memcpy(this,&from,sizeof(IOV)); @@ -54,11 +130,28 @@ void IOV::move(IOV& from) { string IOV::str() const { char text[256]; if ( iovType ) { - ::snprintf(text,sizeof(text),"%s(%d):[%d-%d]", - iovType->name.c_str(),int(iovType->type),keyData.first, keyData.second); + if ( iovType->name[0] != 'e' ) { + ::snprintf(text,sizeof(text),"%s(%d):[%ld-%ld]", + iovType->name.c_str(),int(iovType->type),keyData.first, keyData.second); + } + else if ( iovType->name == "epoch" ) { + time_t since = keyData.first; + time_t until = keyData.second; + char c_since[64], c_until[64]; + struct tm time_buff; + ::strftime(c_since,sizeof(c_since),"%d-%m-%Y %H:%M:%S",::gmtime_r(&since,&time_buff)); + ::strftime(c_until,sizeof(c_until),"%d-%m-%Y %H:%M:%S",::gmtime_r(&until,&time_buff)); + ::snprintf(text,sizeof(text),"%s(%d):[%s-%s]", + iovType->name.c_str(),iovType->type, + c_since, c_until); + } + else { + ::snprintf(text,sizeof(text),"%s(%d):[%ld-%ld]", + iovType->name.c_str(),int(iovType->type),keyData.first, keyData.second); + } } else { - ::snprintf(text,sizeof(text),"%d:[%d-%d]",type,keyData.first, keyData.second); + ::snprintf(text,sizeof(text),"%d:[%ld-%ld]",type,keyData.first, keyData.second); } return text; } @@ -82,22 +175,29 @@ Block::~Block() { } /// Create data block from string representation -void Block::fromString(const string& rep) { +bool Block::fromString(const string& rep) { if ( pointer && grammar ) { - grammar->fromString(pointer,rep); - return; + return grammar->fromString(pointer,rep); } throw runtime_error("Conditions data block is unbound. Cannot parse string representation."); } /// Create string representation of the data block -string Block::str() { +string Block::str() const { if ( pointer && grammar ) { return grammar->str(pointer); } throw runtime_error("Conditions data block is unbound. Cannot create string representation."); } +/// Access type id of the condition +const std::type_info& Block::typeInfo() const { + if ( pointer && grammar ) { + return grammar->type(); + } + throw runtime_error("Conditions data block is unbound. Cannot determine type information!"); +} + /// Initializing constructor Condition::Condition(const string& nam,const string& typ) : Handle<Object>() { Object* o = new Object(); diff --git a/DDCore/src/ConditionsInterna.cpp b/DDCore/src/ConditionsInterna.cpp index 60daa05ac..c5e91ffea 100644 --- a/DDCore/src/ConditionsInterna.cpp +++ b/DDCore/src/ConditionsInterna.cpp @@ -33,6 +33,17 @@ DD4HEP_INSTANTIATE_HANDLE_NAMED(Interna::ConditionContainer); /// Standard initializing constructor BlockData::BlockData() : Block(), destruct(0), copy(0), type(0) { + InstanceCount::increment(this); +} + +/// Copy constructor +BlockData::BlockData(const BlockData& c) + : Block(c), destruct(c.destruct), copy(c.copy), type(c.type) { + grammar = 0; + pointer = 0; + this->bind(c.grammar,c.copy,c.destruct); + this->copy(pointer,c.pointer); + InstanceCount::increment(this); } /// Standard Destructor @@ -43,10 +54,11 @@ BlockData::~BlockData() { } pointer = 0; grammar = 0; + InstanceCount::decrement(this); } -#if 0 + /// Move the data content: 'from' will be reset to NULL -void BlockData::move(BlockData& from) { +bool BlockData::move(BlockData& from) { pointer = from.pointer; grammar = from.grammar; ::memcpy(data,from.data,sizeof(data)); @@ -59,10 +71,37 @@ void BlockData::move(BlockData& from) { from.copy = 0; from.pointer = 0; from.grammar = 0; + return true; +} + +/// Copy constructor +BlockData& BlockData::operator=(const BlockData& c) { + if ( this != &c ) { + if ( this->grammar == c.grammar ) { + if ( destruct ) { + (*destruct)(pointer); + if ( (type&ALLOC_DATA) == ALLOC_DATA ) ::operator delete(pointer); + } + pointer = 0; + grammar = 0; + } + if ( this->grammar == 0 ) { + this->Block::operator=(c); + this->destruct = c.destruct; + this->copy = c.copy; + this->type = c.type; + this->grammar = 0; + this->bind(c.grammar,c.copy,c.destruct); + this->copy(pointer,c.pointer); + return *this; + } + except("Conditions","You may not bind condition data multiple times!"); + } + return *this; } -#endif + /// Set data value -void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), void (*dtor)(void*)) { +bool BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), void (*dtor)(void*)) { if ( !grammar ) { size_t len = g->sizeOf(); grammar = g; @@ -71,7 +110,7 @@ void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), voi (len > sizeof(data)) ? (pointer=::operator new(len),type=ALLOC_DATA) : (pointer=data,type=PLAIN_DATA); - return; + return true; } else if ( grammar == g ) { // We cannot ingore secondary requests for data bindings. @@ -79,6 +118,7 @@ void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), voi except("Conditions","You may not bind conditions multiple times!"); } typeinfoCheck(grammar->type(),g->type(),"Conditions data blocks may not be assigned."); + return false; } /// Set data value diff --git a/DDCore/src/Evaluator/setStdMath.cpp b/DDCore/src/Evaluator/setStdMath.cpp index fb452c518..ece8f7081 100644 --- a/DDCore/src/Evaluator/setStdMath.cpp +++ b/DDCore/src/Evaluator/setStdMath.cpp @@ -9,28 +9,45 @@ using namespace std; -static double eval_abs (double a) { return (a < 0) ? -a : a; } -static double eval_min (double a, double b) { return (a < b) ? a : b; } -static double eval_max (double a, double b) { return (a > b) ? a : b; } -static double eval_sqrt (double a) { return std::sqrt(a); } -static double eval_pow (double a, double b) { return std::pow(a,b); } -static double eval_sin (double a) { return std::sin(a); } -static double eval_cos (double a) { return std::cos(a); } -static double eval_tan (double a) { return std::tan(a); } -static double eval_asin (double a) { return std::asin(a); } -static double eval_acos (double a) { return std::acos(a); } -static double eval_atan (double a) { return std::atan(a); } -static double eval_atan2(double a, double b) { return std::atan2(a,b); } -static double eval_sinh (double a) { return std::sinh(a); } -static double eval_cosh (double a) { return std::cosh(a); } -static double eval_tanh (double a) { return std::tanh(a); } -static double eval_exp (double a) { return std::exp(a); } -static double eval_log (double a) { return std::log(a); } -static double eval_log10(double a) { return std::log10(a); } -static double eval_double(double a) { return a; } -static double eval_int (double a) { return (double)int(a); } -static double eval_nint (double a) { return std::floor(a); } -static double eval_floor(double a) { return std::floor(a); } +static double eval_abs (double a) { return (a < 0) ? -a : a; } +static double eval_fabs (double a) { return std::fabs(a); } +static double eval_fmod (double a, double b) { return std::fmod(a,b); } +static double eval_min (double a, double b) { return (a < b) ? a : b; } +static double eval_max (double a, double b) { return (a > b) ? a : b; } +static double eval_sqrt (double a) { return std::sqrt(a); } +static double eval_cbrt (double a) { return std::cbrt(a); } +static double eval_pow (double a, double b) { return std::pow(a,b); } +static double eval_sin (double a) { return std::sin(a); } +static double eval_cos (double a) { return std::cos(a); } +static double eval_tan (double a) { return std::tan(a); } +static double eval_asin (double a) { return std::asin(a); } +static double eval_acos (double a) { return std::acos(a); } +static double eval_atan (double a) { return std::atan(a); } +static double eval_atan2(double a, double b) { return std::atan2(a,b); } +static double eval_sinh (double a) { return std::sinh(a); } +static double eval_cosh (double a) { return std::cosh(a); } +static double eval_tanh (double a) { return std::tanh(a); } +static double eval_exp (double a) { return std::exp(a); } +static double eval_exp2 (double a) { return std::exp2(a); } +static double eval_exp10(double a) { return ::exp10(a); } +static double eval_expm1(double a) { return std::expm1(a); } +static double eval_log (double a) { return std::log(a); } +static double eval_logb (double a) { return std::logb(a); } +static double eval_log10(double a) { return std::log10(a); } +static double eval_log1p(double a) { return std::log1p(a); } +static double eval_hypot(double a, double b) { return std::hypot(a,b); } +static double eval_erf (double a) { return std::erf(a); } +static double eval_erfc (double a) { return std::erfc(a); } +static double eval_gamma(double a) { return ::gamma(a); } +static double eval_double(double a) { return a; } +static double eval_int (double a) { return (double)int(a); } +static double eval_nint (double a) { return std::floor(a); } +static double eval_floor(double a) { return std::floor(a); } +static double eval_round(double a) { return std::round(a); } +static double eval_ceil (double a) { return std::ceil(a); } +static double eval_isnan(double a) { return std::isnan(a); } +static double eval_isinf(double a) { return std::isinf(a); } +static double eval_nearbyint(double a) { return std::nearbyint(a); } namespace XmlTools { @@ -54,28 +71,45 @@ namespace XmlTools { // S E T S T A N D A R D F U N C T I O N S - setFunction("floor", eval_floor); - setFunction("double",eval_double); - setFunction("int", eval_int); - setFunction("nint", eval_nint); - setFunction("abs", eval_abs); - setFunction("min", eval_min); - setFunction("max", eval_max); - setFunction("sqrt", eval_sqrt); - setFunction("pow", eval_pow); - setFunction("sin", eval_sin); - setFunction("cos", eval_cos); - setFunction("tan", eval_tan); - setFunction("asin", eval_asin); - setFunction("acos", eval_acos); - setFunction("atan", eval_atan); - setFunction("atan2", eval_atan2); - setFunction("sinh", eval_sinh); - setFunction("cosh", eval_cosh); - setFunction("tanh", eval_tanh); - setFunction("exp", eval_exp); - setFunction("log", eval_log); - setFunction("log10", eval_log10); + setFunction("abs", eval_abs); + setFunction("fabs", eval_fabs); + setFunction("fmod", eval_fmod); + setFunction("min", eval_min); + setFunction("max", eval_max); + setFunction("sqrt", eval_sqrt); + setFunction("cbrt", eval_cbrt); + setFunction("pow", eval_pow); + setFunction("sin", eval_sin); + setFunction("cos", eval_cos); + setFunction("tan", eval_tan); + setFunction("asin", eval_asin); + setFunction("acos", eval_acos); + setFunction("atan", eval_atan); + setFunction("atan2", eval_atan2); + setFunction("sinh", eval_sinh); + setFunction("cosh", eval_cosh); + setFunction("tanh", eval_tanh); + setFunction("exp", eval_exp); + setFunction("exp2", eval_exp2); + setFunction("exp10", eval_exp10); + setFunction("expm1", eval_expm1); + setFunction("log", eval_log); + setFunction("logb", eval_logb); + setFunction("log10", eval_log10); + setFunction("log1p", eval_log1p); + setFunction("hypot", eval_hypot); + setFunction("erf", eval_erf); + setFunction("erfc", eval_erfc); + setFunction("gamma", eval_gamma); + setFunction("double", eval_double); + setFunction("int", eval_int); + setFunction("nint", eval_nint); + setFunction("floor", eval_floor); + setFunction("round", eval_round); + setFunction("ceil", eval_ceil); + setFunction("isnan", eval_isnan); + setFunction("isinf", eval_isinf); + setFunction("nearbyint", eval_nearbyint); } } // namespace XmlTools diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index b116a8c79..d62e5fd57 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -535,6 +535,7 @@ void LCDDImp::init() { } } +/// Read any geometry description or alignment file void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) { TypePreserve build_type_preserve(m_buildType = build_type); #if DD4HEP_USE_PYROOT @@ -543,10 +544,16 @@ void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) { cmd = "lcdd.fromXML('" + xmlfile + "')"; TPython::Exec(cmd.c_str()); #else - processXML(xmlfile); + processXML(xmlfile,0); #endif } +/// Read any geometry description or alignment file with external XML entity resolution +void LCDDImp::fromXML(const std::string& fname, UriReader* entity_resolver, LCDDBuildType build_type) { + TypePreserve build_type_preserve(m_buildType = build_type); + processXML(fname,entity_resolver); +} + void LCDDImp::dump() const { TGeoManager* mgr = m_manager; mgr->SetVisLevel(4); diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h index deea2400d..025b85669 100644 --- a/DDCore/src/LCDDImp.h +++ b/DDCore/src/LCDDImp.h @@ -81,6 +81,11 @@ namespace DD4hep { /// Read any XML file virtual void fromXML(const std::string& fname, LCDDBuildType type = BUILD_DEFAULT); + /// Read any geometry description or alignment file with external XML entity resolution + virtual void fromXML(const std::string& fname, + UriReader* entity_resolver, + LCDDBuildType type = BUILD_DEFAULT); + virtual void dump() const; /// Manipulate geometry using facroy converter diff --git a/DDCore/src/LCDDLoad.cpp b/DDCore/src/LCDDLoad.cpp index d298825a3..8936dd412 100644 --- a/DDCore/src/LCDDLoad.cpp +++ b/DDCore/src/LCDDLoad.cpp @@ -43,9 +43,10 @@ LCDDLoad::LCDDLoad(Geometry::LCDD* lcdd) : m_lcdd(lcdd) { LCDDLoad::~LCDDLoad() { } -void LCDDLoad::processXML(const string& xmlfile) { +/// Process XML unit and adopt all data from source structure. +void LCDDLoad::processXML(const string& xmlfile, XML::UriReader* entity_resolver) { try { - XML::DocumentHolder doc(XML::DocumentHandler().load(xmlfile)); + XML::DocumentHolder doc(XML::DocumentHandler().load(xmlfile,entity_resolver)); XML::Handle_t handle = doc.root(); processXMLElement(xmlfile,handle); } @@ -61,10 +62,11 @@ void LCDDLoad::processXML(const string& xmlfile) { } -void LCDDLoad::processXML(const XML::Handle_t& base, const string& xmlfile) { +/// Process XML unit and adopt all data from source structure. +void LCDDLoad::processXML(const XML::Handle_t& base, const string& xmlfile, XML::UriReader* entity_resolver) { try { XML::Strng_t xml(xmlfile); - XML::DocumentHolder doc(XML::DocumentHandler().load(base,xml)); + XML::DocumentHolder doc(XML::DocumentHandler().load(base,xml,entity_resolver)); XML::Handle_t handle = doc.root(); processXMLElement(xmlfile,handle); } @@ -79,6 +81,7 @@ void LCDDLoad::processXML(const XML::Handle_t& base, const string& xmlfile) { } } +/// Process a given DOM (sub-) tree void LCDDLoad::processXMLElement(const std::string& xmlfile, const XML::Handle_t& xml_root) { string tag = xml_root.tag(); string type = tag + "_XML_reader"; @@ -98,6 +101,7 @@ void LCDDLoad::processXMLElement(const std::string& xmlfile, const XML::Handle_t } } +/// Process a given DOM (sub-) tree void LCDDLoad::processXMLElement(const XML::Handle_t& xml_root, LCDDBuildType /* type */) { string tag = xml_root.tag(); string type = tag + "_XML_reader"; @@ -113,7 +117,7 @@ void LCDDLoad::processXMLElement(const XML::Handle_t& xml_root, LCDDBuildType /* } } result = *(long*) result; - if (result != 1) { + if (result != 1) { throw runtime_error("DD4hep: Failed to parse the XML element with tag " + tag + " with the plugin " + type); } diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp index c1b4875d8..48b7b3cc3 100644 --- a/DDCore/src/Readout.cpp +++ b/DDCore/src/Readout.cpp @@ -23,7 +23,6 @@ using namespace std; using namespace DD4hep; using namespace DD4hep::Geometry; -using dd4hep::mm; /// Copy constructor HitCollection::HitCollection(const HitCollection& c) @@ -32,7 +31,7 @@ HitCollection::HitCollection(const HitCollection& c) } /// Initializing constructor -HitCollection::HitCollection(const std::string& n, const std::string& k, long k_min, long k_max) +HitCollection::HitCollection(const string& n, const string& k, long k_min, long k_max) : name(n), key(k), key_min(k_min), key_max(k_max) { } @@ -53,9 +52,18 @@ Readout::Readout(const string& nam) { assign(new ReadoutObject(), nam, "readout"); } +/// Access number of hit collections +size_t Readout::numCollections() const { + if ( isValid() ) { + Object& ro = object<Object>(); + return ro.hits.size(); + } + throw runtime_error("DD4hep: Readout::numCollections: Cannot access object data [Invalid Handle]"); +} + /// Access names of hit collections -std::vector<std::string> Readout::collectionNames() const { - std::vector<std::string> colls; +vector<string> Readout::collectionNames() const { + vector<string> colls; if ( isValid() ) { Object& ro = object<Object>(); if ( !ro.hits.empty() ) { @@ -68,8 +76,8 @@ std::vector<std::string> Readout::collectionNames() const { } /// Access hit collections -std::vector<const HitCollection*> Readout::collections() const { - std::vector<const HitCollection*> colls; +vector<const HitCollection*> Readout::collections() const { + vector<const HitCollection*> colls; if ( isValid() ) { Object& ro = object<Object>(); if ( !ro.hits.empty() ) { @@ -78,7 +86,7 @@ std::vector<const HitCollection*> Readout::collections() const { } return colls; } - throw runtime_error("DD4hep: Readout::collectionsNames: Cannot access object data [Invalid Handle]"); + throw runtime_error("DD4hep: Readout::collections: Cannot access object data [Invalid Handle]"); } /// Assign IDDescription to readout structure diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp index 70d311711..d959d9d8b 100644 --- a/DDCore/src/XML/DocumentHandler.cpp +++ b/DDCore/src/XML/DocumentHandler.cpp @@ -479,7 +479,7 @@ Document DocumentHandler::load(const std::string& fname, UriReader* reader) cons /// Load XML file and parse it using URI resolver to read data. Document DocumentHandler::load(Handle_t base, const XmlChar* fname, UriReader* reader) const { string path = system_path(base, fname); - return load(path,0); + return load(path,reader); } /// Parse a standalong XML string into a document. diff --git a/DDCore/src/XML/UriReader.cpp b/DDCore/src/XML/UriReader.cpp index 536627b19..9a4342e04 100644 --- a/DDCore/src/XML/UriReader.cpp +++ b/DDCore/src/XML/UriReader.cpp @@ -18,3 +18,28 @@ /// Default destructor DD4hep::XML::UriReader::~UriReader() { } + +/// Resolve a given URI to a string containing the data +bool DD4hep::XML::UriReader::load(const std::string& system_id, std::string& data) { + return this->load(system_id, context(), data); +} + +/// Default constructor +DD4hep::XML::UriContextReader::UriContextReader(UriReader* reader, UriReader::UserContext* ctxt) + : m_reader(reader), m_context(ctxt) +{ +} + +/// Default destructor +DD4hep::XML::UriContextReader::~UriContextReader() { +} + +/// Resolve a given URI to a string containing the data +bool DD4hep::XML::UriContextReader::load(const std::string& system_id, std::string& data) { + return m_reader->load(system_id, context(), data); +} + +/// Resolve a given URI to a string containing the data +bool DD4hep::XML::UriContextReader::load(const std::string& system_id, UserContext* ctxt, std::string& data) { + return m_reader->load(system_id, ctxt, data); +} diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index e308ef7ae..b307fefd6 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -50,18 +50,18 @@ namespace DD4hep { struct AlignmentFile; struct DetElementInclude {}; } - template <> void Converter<Plugin>::operator()(xml_h e) const; - template <> void Converter<Constant>::operator()(xml_h e) const; - template <> void Converter<Material>::operator()(xml_h e) const; - template <> void Converter<Atom>::operator()(xml_h e) const; - template <> void Converter<VisAttr>::operator()(xml_h e) const; - template <> void Converter<AlignmentEntry>::operator()(xml_h e) const; - template <> void Converter<Region>::operator()(xml_h e) const; - template <> void Converter<Readout>::operator()(xml_h e) const; - template <> void Converter<Segmentation>::operator()(xml_h e) const; - template <> void Converter<LimitSet>::operator()(xml_h e) const; - template <> void Converter<Property>::operator()(xml_h e) const; - template <> void Converter<CartesianField>::operator()(xml_h e) const; + template <> void Converter<Plugin>::operator()(xml_h element) const; + template <> void Converter<Constant>::operator()(xml_h element) const; + template <> void Converter<Material>::operator()(xml_h element) const; + template <> void Converter<Atom>::operator()(xml_h element) const; + template <> void Converter<VisAttr>::operator()(xml_h element) const; + template <> void Converter<AlignmentEntry>::operator()(xml_h element) const; + template <> void Converter<Region>::operator()(xml_h element) const; + template <> void Converter<Readout>::operator()(xml_h element) const; + template <> void Converter<Segmentation>::operator()(xml_h element) const; + template <> void Converter<LimitSet>::operator()(xml_h element) const; + template <> void Converter<Property>::operator()(xml_h element) const; + template <> void Converter<CartesianField>::operator()(xml_h element) const; template <> void Converter<SensitiveDetector>::operator()(xml_h element) const; template <> void Converter<DetElement>::operator()(xml_h element) const; template <> void Converter<GdmlFile>::operator()(xml_h element) const; @@ -1018,15 +1018,25 @@ template <> void Converter<Compact>::operator()(xml_h element) const { } #ifdef _WIN32 -template Converter<Atom>; -template Converter<Compact>; -template Converter<Readout>; -template Converter<VisAttr>; -template Converter<Constant>; -template Converter<LimitSet>; -template Converter<Material>; -template Converter<DetElement>; -template Converter<AlignmentEntry>; -template Converter<SensitiveDetector>; -template Converter<CartesianField>; + template Converter<Plugin>; + template Converter<Constant>; + template Converter<Material>; + template Converter<Atom>; + template Converter<VisAttr>; + template Converter<AlignmentEntry>; + template Converter<Region>; + template Converter<Readout>; + template Converter<Segmentation>; + template Converter<LimitSet>; + template Converter<Property>; + template Converter<CartesianField>; + template Converter<SensitiveDetector>; + template Converter<DetElement>; + template Converter<GdmlFile>; + template Converter<XMLFile>; + template Converter<AlignmentFile>; + template Converter<Header>; + template Converter<DetElementInclude>; + template Converter<Compact>; + #endif diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp index 632edcba8..ff08b6379 100644 --- a/DDCore/src/plugins/StandardPlugins.cpp +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -211,58 +211,59 @@ static long dump_volume_tree(LCDD& lcdd, int argc, char** argv) { bool m_printVolIDs; bool m_printPositions; bool m_printSensitivesOnly; - Actor(int argc, char** argv) + Actor(int ac, char** av) : m_printVolIDs(false), m_printPositions(false), m_printSensitivesOnly(false) { - for(int i=0; i<argc; ++i) { - char c = ::tolower(argv[i][0]); - if ( c == 'v' ) m_printVolIDs = true; - else if ( c == 'p' ) m_printPositions = true; - else if ( c == 's' ) m_printSensitivesOnly = true; + for(int i=0; i<ac; ++i) { + char c = ::tolower(av[i][0]); + if ( c == 'v' ) m_printVolIDs = true; + else if ( c == 'p' ) m_printPositions = true; + else if ( c == 's' ) m_printSensitivesOnly = true; } } + long dump(TGeoNode* ideal, TGeoNode* aligned,int level, VIDs volids) const { char fmt[128]; string opt_info; PlacedVolume pv(ideal); bool sensitive = false; if ( m_printPositions || m_printVolIDs ) { - stringstream log; - if ( m_printPositions ) { - const double* trans = ideal->GetMatrix()->GetTranslation(); - ::snprintf(fmt, sizeof(fmt), "Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]); - log << fmt; - } - // Top level volume! have no volume ids - if ( m_printVolIDs && ideal && ideal->GetMotherVolume() ) { - VIDs vid = pv.volIDs(); - if ( !vid.empty() ) { - sensitive = true; - log << " VolID: "; - volids.std::vector<VID>::insert(volids.end(),vid.begin(),vid.end()); - for(VIDs::const_iterator i=volids.begin(); i!=volids.end(); ++i) { - ::snprintf(fmt, sizeof(fmt), "%s:%2d ",(*i).first.c_str(), (*i).second); - log << fmt; - } - } - } - opt_info = log.str(); + stringstream log; + if ( m_printPositions ) { + const double* trans = ideal->GetMatrix()->GetTranslation(); + ::snprintf(fmt, sizeof(fmt), "Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]); + log << fmt; + } + // Top level volume! have no volume ids + if ( m_printVolIDs && ideal && ideal->GetMotherVolume() ) { + VIDs vid = pv.volIDs(); + if ( !vid.empty() ) { + sensitive = true; + log << " VolID: "; + volids.std::vector<VID>::insert(volids.end(),vid.begin(),vid.end()); + for(VIDs::const_iterator i=volids.begin(); i!=volids.end(); ++i) { + ::snprintf(fmt, sizeof(fmt), "%s:%2d ",(*i).first.c_str(), (*i).second); + log << fmt; + } + } + } + opt_info = log.str(); } TGeoVolume* volume = ideal->GetVolume(); if ( !m_printSensitivesOnly || (m_printSensitivesOnly && sensitive) ) { - if ( ideal == aligned ) { - ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) \t[%p] %%s", - level+1,2*level+1,(void*)ideal); - } - else { - ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) Ideal:%p Aligned:%p %%s", - level+1,2*level+1,(void*)ideal,(void*)aligned); - } - printout(INFO,"+++",fmt,"", - aligned->GetName(), - volume->GetTitle(), - volume->GetShape()->IsA()->GetName(), - opt_info.c_str()); + if ( ideal == aligned ) { + ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) \t[%p] %%s", + level+1,2*level+1,(void*)ideal); + } + else { + ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) Ideal:%p Aligned:%p %%s", + level+1,2*level+1,(void*)ideal,(void*)aligned); + } + printout(INFO,"+++",fmt,"", + aligned->GetName(), + volume->GetTitle(), + volume->GetShape()->IsA()->GetName(), + opt_info.c_str()); } for (Int_t idau = 0, ndau = aligned->GetNdaughters(); idau < ndau; ++idau) { TGeoNode* ideal_daughter = ideal->GetDaughter(idau); diff --git a/UtilityApps/src/dd4hep_python.cpp b/UtilityApps/src/dd4hep_python.cpp deleted file mode 100644 index 4e1a826f2..000000000 --- a/UtilityApps/src/dd4hep_python.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// $Id$ -//========================================================================== -// AIDA Detector description implementation for LCD -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== -#include "TSystem.h" -#include "TInterpreter.h" -#include "DDG4/Python/DDPython.h" -#include <vector> - -static int load_libs(const std::vector<char*>& libs) { - for(size_t i=0; i<libs.size(); ++i) { - int ret = gSystem->Load(libs[i]); - if ( 0 != ret ) { - ::printf("+++ Failed to load library: %s [ignored]\n",libs[i]); - return ret; - } - else { - ::printf("+++ Successfully loaded library: %s\n",libs[i]); - } - } - return 0; -} - -int main(int argc, char** argv) { - std::vector<char*> args; - std::vector<char*> libs; - int first_arg = 0; - int ret; - - for(int i=first_arg; i<argc; ++i) { - if ( 0 == ::strcmp(argv[i],"-L") ) - libs.push_back(argv[++i]); - else - args.push_back(argv[i]); - } - if ( 0 == (ret=load_libs(libs)) ) { - ::printf("+++ Calling now Py_Main...\n"); - ret = DD4hep::DDPython::run_interpreter(args.size(), &args[0]); - //::printf("+++ Return code Py_Main=%d\n",ret); - } - return ret; -} -- GitLab