Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-25 09:18:57

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 #ifndef DDCOND_CONDITIONSMAPPEDUSERPOOL_H
0014 #define DDCOND_CONDITIONSMAPPEDUSERPOOL_H
0015 
0016 // Framework include files
0017 #include <DDCond/ConditionsPool.h>
0018 #include <DD4hep/ConditionsMap.h>
0019 
0020 // C/C++ include files
0021 #include <map>
0022 #include <unordered_map>
0023 
0024 /// Namespace for the AIDA detector description toolkit
0025 namespace dd4hep {
0026 
0027   /// Namespace for implementation details of the AIDA detector description toolkit
0028   namespace cond {
0029 
0030     /// Forward declarations
0031     class ConditionsDataLoader;
0032     
0033     /// Class implementing the conditions user pool for a given IOV type
0034     /**
0035      *
0036      *  Please note:
0037      *  Users should not directly interact with object instances of this type.
0038      *  Data are not thread protected and interaction may cause serious harm.
0039      *  Only the ConditionsManager implementation should interact with
0040      *  this class or any subclass to ensure data integrity.
0041      *
0042      *  \author  M.Frank
0043      *  \version 1.0
0044      *  \ingroup DD4HEP_CONDITIONS
0045      */
0046     template<typename MAPPING> 
0047     class ConditionsMappedUserPool : public UserPool    {
0048       typedef MAPPING Mapping;
0049       Mapping               m_conditions;
0050       /// IOV Pool as data source
0051       ConditionsIOVPool*    m_iovPool = 0;
0052       /// The loader to access non-existing conditions
0053       ConditionsDataLoader* m_loader = 0;
0054 
0055       /// Internal helper to find conditions
0056       Condition::Object* i_findCondition(Condition::key_type key)  const;
0057 
0058       /// Internal insertion helper
0059       bool i_insert(Condition::Object* o);
0060 
0061     public:
0062       /// Default constructor
0063       ConditionsMappedUserPool(ConditionsManager mgr, ConditionsIOVPool* pool);
0064       /// Default destructor
0065       virtual ~ConditionsMappedUserPool();
0066       /// Print pool content
0067       virtual void print(const std::string& opt)   const  override;
0068       /// Total entry count
0069       virtual size_t size()  const  override;
0070       /// Full cleanup of all managed conditions.
0071       virtual void clear()  override;
0072       /// Check a condition for existence
0073       virtual bool exists(Condition::key_type hash)  const  override;
0074       /// Check a condition for existence
0075       virtual bool exists(const ConditionKey& key)  const  override;
0076       /// Check if a condition exists in the pool and return it to the caller
0077       virtual Condition get(Condition::key_type hash)  const  override;
0078       /// Check if a condition exists in the pool and return it to the caller     
0079       virtual Condition get(const ConditionKey& key)  const  override;
0080 
0081       /// Remove condition by key from pool.
0082       virtual bool remove(Condition::key_type hash_key)  override;
0083       /// Remove condition by key from pool.
0084       virtual bool remove(const ConditionKey& key)  override;
0085       /// Do single insertion of condition including registration to the manager
0086       virtual bool registerOne(const IOV& iov, Condition cond)  override;
0087       /// Do block insertions of conditions with identical IOV including registration to the manager
0088       virtual size_t registerMany(const IOV& iov, const std::vector<Condition>& values) override;
0089       /// Register a new condition to this pool
0090       virtual bool insert(Condition cond)  override;
0091 
0092       /// ConditionsMap overload: Add a condition directly to the slice
0093       virtual bool insert(DetElement detector, Condition::itemkey_type key, Condition condition)  override;
0094       /// ConditionsMap overload: Access a condition
0095       virtual Condition get(DetElement detector, Condition::itemkey_type key)  const  override;
0096       /// No ConditionsMap overload: Access all conditions within a key range in the interval [lower,upper]
0097       virtual std::vector<Condition> get(DetElement detector,
0098                                          Condition::itemkey_type lower,
0099                                          Condition::itemkey_type upper)  const override;
0100       /// Access all conditions within the key range of a detector element
0101       virtual std::vector<Condition> get(Condition::key_type lower,
0102                                          Condition::key_type upper)  const  override;
0103 
0104       /// ConditionsMap overload: Interface to scan data content of the conditions mapping
0105       virtual void scan(const Condition::Processor& processor) const  override;
0106       /// ConditionsMap overload: Interface to scan data content of the conditions mapping
0107       virtual void scan(Condition::key_type lower,
0108                         Condition::key_type upper,
0109                         const Condition::Processor& processor) const  override;
0110       /// ConditionsMap overload: Interface to scan data content of the conditions mapping
0111       virtual void scan(DetElement detector,
0112                         Condition::itemkey_type lower,
0113                         Condition::itemkey_type upper,
0114                         const Condition::Processor& processor) const  override;
0115 
0116       /// Prepare user pool for usage (load, fill etc.) according to required IOV
0117       virtual ConditionsManager::Result prepare(const IOV&                  required,
0118                                                 ConditionsSlice&            slice,
0119                                                 ConditionUpdateUserContext* user_param)  override;
0120 
0121       /// Evaluate and register all derived conditions from the dependency list
0122       virtual size_t compute(const Dependencies&         dependencies,
0123                              ConditionUpdateUserContext* user_param,
0124                              bool                        force)  override;
0125 
0126       /// Prepare user pool for usage (load, fill etc.) according to required IOV
0127       virtual ConditionsManager::Result load   (const IOV&              required,
0128                                                 ConditionsSlice&        slice,
0129                                                 ConditionUpdateUserContext* user_param)  override;
0130       /// Prepare user pool for usage (load, fill etc.) according to required IOV
0131       virtual ConditionsManager::Result compute(const IOV&                  required,
0132                                                 ConditionsSlice&            slice,
0133                                                 ConditionUpdateUserContext* user_param)  override;
0134     };
0135 
0136   }    /* End namespace cond               */
0137 }      /* End namespace dd4hep                   */
0138 #endif /* DDCOND_CONDITIONSMAPPEDUSERPOOL_H      */
0139 
0140 //==========================================================================
0141 //  AIDA Detector description implementation 
0142 //--------------------------------------------------------------------------
0143 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0144 // All rights reserved.
0145 //
0146 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0147 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0148 //
0149 // Author     : M.Frank
0150 //
0151 //==========================================================================
0152 
0153 // Framework include files
0154 //#include <DDCond/ConditionsMappedPool.h>
0155 #include <DD4hep/Printout.h>
0156 #include <DD4hep/Factories.h>
0157 #include <DD4hep/InstanceCount.h>
0158 
0159 #include <DDCond/ConditionsIOVPool.h>
0160 #include <DDCond/ConditionsSelectors.h>
0161 #include <DDCond/ConditionsDataLoader.h>
0162 #include <DDCond/ConditionsManagerObject.h>
0163 #include <DDCond/ConditionsDependencyHandler.h>
0164 
0165 // C/C++ include files
0166 #include <mutex>
0167 
0168 using namespace dd4hep::cond;
0169 
0170 namespace {
0171 
0172   class SimplePrint : public dd4hep::Condition::Processor {
0173     /// Conditions callback for object processing
0174     virtual int process(dd4hep::Condition)  const override    { return 1; }
0175     /// Conditions callback for object processing
0176     virtual int operator()(dd4hep::Condition)  const override { return 1; }
0177     /// Conditions callback for object processing in maps
0178     virtual int operator()(const std::pair<dd4hep::Condition::key_type,dd4hep::Condition>& i)  const override  {
0179       dd4hep::Condition c = i.second;
0180       dd4hep::printout(dd4hep::INFO,"UserPool","++ %16llX/%16llX Val:%s %s",i.first, c->hash, c->value.c_str(), c.str().c_str());
0181       return 1;
0182     }
0183   };
0184   template <typename T> struct MapSelector : public dd4hep::ConditionsSelect {
0185     T& m;
0186     MapSelector(T& o) : m(o) {}
0187     bool operator()(dd4hep::Condition::Object* o)  const
0188     { return m.emplace(o->hash,o).second;    }
0189   };
0190   template <typename T> MapSelector<T> mapSelector(T& container)
0191   {  return MapSelector<T>(container);       }
0192 
0193   template <typename T> struct Inserter {
0194     T& m;
0195     dd4hep::IOV* iov;
0196     Inserter(T& o, dd4hep::IOV* i=0) : m(o), iov(i) {}
0197     void operator()(const dd4hep::Condition& c)  {
0198       dd4hep::Condition::Object* o = c.ptr();
0199       m.emplace(o->hash,o);
0200       if ( iov ) iov->iov_intersection(o->iov->key());
0201     }
0202     void operator()(const std::pair<dd4hep::Condition::key_type,dd4hep::Condition>& e) { (*this)(e.second);  }
0203   };
0204 }
0205 
0206 /// Default constructor
0207 template<typename MAPPING>
0208 ConditionsMappedUserPool<MAPPING>::ConditionsMappedUserPool(ConditionsManager mgr, ConditionsIOVPool* pool) 
0209   : UserPool(mgr), m_iovPool(pool)
0210 {
0211   InstanceCount::increment(this);
0212   if ( mgr.isValid() )  {
0213     if ( m_iovPool )  {
0214       m_iov.iovType = m_iovPool->type;
0215       m_loader = mgr->loader();
0216       if ( m_loader ) return;
0217       except("UserPool","The conditions manager is not properly setup. No conditions loader present.");
0218     }
0219     except("UserPool","FAILED to create mapped user pool. [Invalid IOV pool]");
0220   }
0221   except("UserPool","FAILED to create mapped user pool. [Invalid conditions manager]");
0222 }
0223 
0224 /// Default destructor
0225 template<typename MAPPING>
0226 ConditionsMappedUserPool<MAPPING>::~ConditionsMappedUserPool()  {
0227   clear();
0228   InstanceCount::decrement(this);
0229 }
0230 
0231 template<typename MAPPING> inline dd4hep::Condition::Object* 
0232 ConditionsMappedUserPool<MAPPING>::i_findCondition(Condition::key_type key)  const {
0233   typename MAPPING::const_iterator i=m_conditions.find(key);
0234 #if 0
0235   if ( i == m_conditions.end() )  {
0236     print("*"); // This causes CTEST to bail out, due too much output!
0237   }
0238 #endif
0239   return i != m_conditions.end() ? (*i).second : 0;
0240 }
0241 
0242 template<typename MAPPING> inline bool
0243 ConditionsMappedUserPool<MAPPING>::i_insert(Condition::Object* o)   {
0244   int ret = m_conditions.emplace(o->hash,o).second;
0245   if ( flags&PRINT_INSERT )  {
0246     printout(INFO,"UserPool","++ %s condition [%016llX]"
0247 #if defined(DD4HEP_CONDITIONS_HAVE_NAME)
0248              ": %s [%s].", ret ? "Successfully inserted" : "FAILED to insert",
0249              o->hash, o->GetName(), o->GetTitle());
0250 #else
0251     , ret ? "Successfully inserted" : "FAILED to insert", o->hash);
0252 #endif
0253   }
0254   return ret;
0255 }
0256   
0257 /// Total entry count
0258 template<typename MAPPING>
0259 size_t ConditionsMappedUserPool<MAPPING>::size()  const  {
0260   return  m_conditions.size();
0261 }
0262 
0263 /// Print pool content
0264 template<typename MAPPING>
0265 void ConditionsMappedUserPool<MAPPING>::print(const std::string& opt)   const  {
0266   const IOV* iov = &m_iov;
0267   printout(INFO,"UserPool","+++ %s Conditions for USER pool with IOV: %-32s [%4d entries]",
0268            opt.c_str(), iov->str().c_str(), size());
0269   if ( opt == "*" )  {
0270     SimplePrint prt;
0271     scan(prt);
0272   }
0273 }
0274 
0275 /// Full cleanup of all managed conditions.
0276 template<typename MAPPING>
0277 void ConditionsMappedUserPool<MAPPING>::clear()   {
0278   if ( flags&PRINT_CLEAR )  {
0279     printout(INFO,"UserPool","++ Cleared %ld conditions from pool.",m_conditions.size());
0280   }
0281   m_iov = IOV(0);
0282   m_conditions.clear();
0283 }
0284 
0285 /// Check a condition for existence
0286 template<typename MAPPING>
0287 bool ConditionsMappedUserPool<MAPPING>::exists(Condition::key_type hash)  const   {
0288   return i_findCondition(hash) != 0;
0289 }
0290 
0291 /// Check a condition for existence
0292 template<typename MAPPING>
0293 bool ConditionsMappedUserPool<MAPPING>::exists(const ConditionKey& key)  const   {
0294   return i_findCondition(key.hash) != 0;
0295 }
0296 
0297 /// Check if a condition exists in the pool and return it to the caller
0298 template<typename MAPPING>
0299 dd4hep::Condition ConditionsMappedUserPool<MAPPING>::get(Condition::key_type hash)  const   {
0300   return i_findCondition(hash);
0301 }
0302 
0303 /// Check if a condition exists in the pool and return it to the caller     
0304 template<typename MAPPING>
0305 dd4hep::Condition ConditionsMappedUserPool<MAPPING>::get(const ConditionKey& key)  const   {
0306   return i_findCondition(key.hash);
0307 }
0308 
0309 /// Do block insertions of conditions with identical IOV including registration to the manager
0310 template<typename MAPPING> bool
0311 ConditionsMappedUserPool<MAPPING>::registerOne(const IOV& iov,
0312                                                Condition cond)   {
0313   if ( iov.iovType )   {
0314     ConditionsPool* pool = m_manager.registerIOV(*iov.iovType,iov.keyData);
0315     if ( pool )   {
0316       return m_manager.registerUnlocked(*pool, cond);
0317     }
0318     except("UserPool","++ Failed to register IOV: %s",iov.str().c_str());
0319   }
0320   except("UserPool","++ Cannot register conditions with invalid IOV.");
0321   return 0;
0322 }
0323 
0324 /// Do block insertions of conditions with identical IOV including registration to the manager
0325 template<typename MAPPING> std::size_t
0326 ConditionsMappedUserPool<MAPPING>::registerMany(const IOV& iov,
0327                                                 const std::vector<Condition>& conds)   {
0328   if ( iov.iovType )   {
0329     ConditionsPool* pool = m_manager.registerIOV(*iov.iovType,iov.keyData);
0330     if ( pool )   {
0331       std::size_t result = m_manager.blockRegister(*pool, conds);
0332       if ( result == conds.size() )   {
0333         for(auto c : conds) i_insert(c.ptr());
0334         return result;
0335       }
0336       except("UserPool","++ Conditions registration was incomplete: "
0337              "registerd only  %ld out of %ld conditions.",
0338              result, conds.size());
0339     }
0340     except("UserPool","++ Failed to register IOV: %s",iov.str().c_str());
0341   }
0342   except("UserPool","++ Cannot register conditions with invalid IOV.");
0343   return 0;
0344 }
0345 
0346 /// Register a new condition to this pool
0347 template<typename MAPPING>
0348 bool ConditionsMappedUserPool<MAPPING>::insert(Condition cond)   {
0349   bool result = i_insert(cond.ptr());
0350   if ( result ) return true;
0351   except("UserPool","++ Attempt to double insert condition: %16llX Name:%s", cond->hash, cond.name());
0352   return false;
0353 }
0354 
0355 /// ConditionsMap overload: Add a condition directly to the slice
0356 template<typename MAPPING>
0357 bool ConditionsMappedUserPool<MAPPING>::insert(DetElement detector,
0358                                                unsigned int item_key,
0359                                                Condition cond)   {
0360   cond->hash = ConditionKey::KeyMaker(detector.key(),item_key).hash;
0361   return insert(cond);
0362 }
0363 
0364 /// ConditionsMap overload: Access a condition
0365 template<typename MAPPING>
0366 dd4hep::Condition ConditionsMappedUserPool<MAPPING>::get(DetElement detector, unsigned int item_key)  const  {
0367   return get(ConditionKey::KeyMaker(detector.key(), item_key).hash);
0368 }
0369   
0370 /// No ConditionsMap overload: Access all conditions within a key range in the interval [lower,upper]
0371 template<typename MAPPING> std::vector<dd4hep::Condition>
0372 ConditionsMappedUserPool<MAPPING>::get(DetElement detector,
0373                                        Condition::itemkey_type lower,
0374                                        Condition::itemkey_type upper)  const {
0375   Condition::detkey_type det_key = detector.key();
0376   return this->get(ConditionKey::KeyMaker(det_key,lower).hash,
0377                    ConditionKey::KeyMaker(det_key,upper).hash);
0378 }
0379 
0380 /// Specialization for std::map: Access all conditions within a given key range
0381 template<typename MAPPING> std::vector<dd4hep::Condition>
0382 ConditionsMappedUserPool<MAPPING>::get(Condition::key_type lower, Condition::key_type upper)   const  {
0383   std::vector<Condition> result;
0384   if ( !m_conditions.empty() )   {
0385     typename MAPPING::const_iterator first = m_conditions.lower_bound(lower);
0386     for(; first != m_conditions.end(); ++first )  {
0387       if ( (*first).first > upper ) break;
0388       result.emplace_back((*first).second);
0389     }
0390   }
0391   return result;
0392 }
0393 
0394 /// ConditionsMap overload: Interface to scan data content of the conditions mapping
0395 template<typename MAPPING>
0396 void ConditionsMappedUserPool<MAPPING>::scan(const Condition::Processor& processor) const  {
0397   for( const auto& i : m_conditions )
0398     processor(i.second);
0399 }
0400 
0401 /// ConditionsMap overload: Interface to scan data content of the conditions mapping
0402 template<typename MAPPING>
0403 void ConditionsMappedUserPool<MAPPING>::scan(DetElement detector,
0404                                              Condition::itemkey_type lower,
0405                                              Condition::itemkey_type upper,
0406                                              const Condition::Processor& processor) const
0407 {
0408   Condition::detkey_type det_key = detector.key();
0409   scan(ConditionKey::KeyMaker(det_key,lower).hash,
0410        ConditionKey::KeyMaker(det_key,upper).hash,
0411        processor);
0412 }
0413 
0414 /// ConditionsMap overload: Interface to scan data content of the conditions mapping
0415 template<typename MAPPING>
0416 void ConditionsMappedUserPool<MAPPING>::scan(Condition::key_type lower,
0417                                              Condition::key_type upper,
0418                                              const Condition::Processor& processor) const
0419 {
0420   typename MAPPING::const_iterator first = m_conditions.lower_bound(lower);
0421   for(; first != m_conditions.end() && (*first).first <= upper; ++first )
0422     processor((*first).second);
0423 }
0424 
0425 /// Remove condition by key from pool.
0426 template<typename MAPPING>
0427 bool ConditionsMappedUserPool<MAPPING>::remove(const ConditionKey& key)   {
0428   return remove(key.hash);
0429 }
0430 
0431 /// Remove condition by key from pool.
0432 template<typename MAPPING>
0433 bool ConditionsMappedUserPool<MAPPING>::remove(Condition::key_type hash_key)    {
0434   typename MAPPING::iterator i = m_conditions.find(hash_key);
0435   if ( i != m_conditions.end() ) {
0436     m_conditions.erase(i);
0437     return true;
0438   }
0439   return false;
0440 }
0441 
0442 /// Evaluate and register all derived conditions from the dependency list
0443 template<typename MAPPING>
0444 std::size_t ConditionsMappedUserPool<MAPPING>::compute(const Dependencies& deps,
0445                                                        ConditionUpdateUserContext* user_param,
0446                                                        bool force)
0447 {
0448   if ( !deps.empty() )  {
0449     Dependencies missing;
0450     // Loop over the dependencies and check if they have to be upgraded
0451     for ( const auto& i : deps )  {
0452       typename MAPPING::iterator j = m_conditions.find(i.first);
0453       if ( j != m_conditions.end() )  {
0454         if ( !force )  {
0455           Condition::Object* c = (*j).second;
0456           // Remeber: key ist first, test is second!
0457           if ( !IOV::key_is_contained(m_iov.keyData,c->iov->keyData) )  {
0458             /// This condition is no longer valid. remove it!
0459             /// It will be added again by the handler.
0460             m_conditions.erase(j);
0461             missing.emplace(i);
0462           }
0463           continue;
0464         }
0465         else  {
0466           m_conditions.erase(j);
0467         }
0468       }
0469       missing.emplace(i);
0470     }
0471     if ( !missing.empty() )  {
0472       ConditionsManagerObject* mgr(m_manager.access());
0473       ConditionsDependencyHandler handler(mgr, *this, missing, user_param);
0474       /// 1rst pass: Compute/create the missing condiions
0475       handler.compute();
0476       /// 2nd pass:  Resolve missing dependencies
0477       handler.resolve();
0478       return handler.num_callback;
0479     }
0480   }
0481   return 0;
0482 }
0483 
0484 namespace {
0485   struct COMP {
0486     typedef std::pair<dd4hep::Condition::key_type,const ConditionDependency*>             Dep;
0487     typedef std::pair<const dd4hep::Condition::key_type,dd4hep::detail::ConditionObject*> Cond;
0488     typedef std::pair<const dd4hep::Condition::key_type,ConditionsLoadInfo* >             Info;
0489     typedef std::pair<const dd4hep::Condition::key_type,dd4hep::Condition>                Cond2;
0490     
0491     bool operator()(const Dep& a,const Cond& b) const   { return a.first < b.first; }
0492     bool operator()(const Cond& a,const Dep& b) const   { return a.first < b.first; }
0493 
0494     bool operator()(const Info& a,const Cond& b) const  { return a.first < b.first; }
0495     bool operator()(const Cond& a,const Info& b) const  { return a.first < b.first; }
0496 
0497     bool operator()(const Info& a,const Cond2& b) const { return a.first < b.first; }
0498     bool operator()(const Cond2& a,const Info& b) const { return a.first < b.first; }
0499   };
0500 }
0501 
0502 template<typename MAPPING> ConditionsManager::Result
0503 ConditionsMappedUserPool<MAPPING>::prepare(const IOV&                  required, 
0504                                            ConditionsSlice&            slice,
0505                                            ConditionUpdateUserContext* user_param)
0506 {
0507   typedef std::vector<std::pair<Condition::key_type,ConditionDependency*> > CalcMissing;
0508   typedef std::vector<std::pair<Condition::key_type,ConditionsLoadInfo*> >  CondMissing;
0509   const auto& slice_cond = slice.content->conditions();
0510   const auto& slice_calc = slice.content->derived();
0511   auto&  slice_miss_cond = slice.missingConditions();
0512   auto&  slice_miss_calc = slice.missingDerivations();
0513   bool   do_load         = m_manager->doLoadConditions();
0514   bool   do_output_miss  = m_manager->doOutputUnloaded();
0515   IOV    pool_iov(required.iovType);
0516   ConditionsManager::Result result;
0517 
0518   // This is a critical operation, because we have to ensure the
0519   // IOV pools are ONLY manipulated by the current thread.
0520   // Otherwise the selection and the population are unsafe!
0521   static std::mutex lock;
0522   std::lock_guard<std::mutex> guard(lock);
0523 
0524   m_conditions.clear();
0525   slice_miss_cond.clear();
0526   slice_miss_calc.clear();
0527   pool_iov.reset().invert();
0528   m_iovPool->select(required, Operators::mapConditionsSelect(m_conditions), pool_iov);
0529   m_iov = pool_iov;
0530   CondMissing cond_missing(slice_cond.size()+m_conditions.size());
0531   CalcMissing calc_missing(slice_calc.size()+m_conditions.size());
0532 
0533   CondMissing::iterator last_cond = set_difference(begin(slice_cond),   end(slice_cond),
0534                                                    begin(m_conditions), end(m_conditions),
0535                                                    begin(cond_missing), COMP());
0536   long num_cond_miss = last_cond-begin(cond_missing);
0537   cond_missing.resize(num_cond_miss);
0538   printout((flags&PRINT_LOAD) ? INFO : DEBUG,"UserPool",
0539            "%ld conditions out of %ld conditions are MISSING.",
0540            num_cond_miss, slice_cond.size());
0541   CalcMissing::iterator last_calc = set_difference(begin(slice_calc),   end(slice_calc),
0542                                                    begin(m_conditions), end(m_conditions),
0543                                                    begin(calc_missing), COMP());
0544   long num_calc_miss = last_calc-begin(calc_missing);
0545   calc_missing.resize(num_calc_miss);
0546   printout((flags&PRINT_COMPUTE) ? INFO : DEBUG,"UserPool",
0547            "%ld derived conditions out of %ld conditions are MISSING.",
0548            num_calc_miss, slice_calc.size());
0549 
0550   result.loaded   = 0;
0551   result.computed = 0;
0552   result.selected = m_conditions.size();
0553   result.missing  = num_cond_miss+num_calc_miss;
0554   //
0555   // Now we load the missing conditions from the conditions loader
0556   //
0557   if ( num_cond_miss > 0 )  {
0558     if ( do_load )  {
0559       ConditionsDataLoader::LoadedItems loaded;
0560       size_t updates = m_loader->load_many(required, cond_missing, loaded, pool_iov);
0561       if ( updates > 0 )  {
0562         // Need to compute the intersection: All missing entries are required....
0563         CondMissing load_missing(cond_missing.size()+loaded.size());
0564         // Note: cond_missing is already sorted (doc of 'set_difference'). No need to re-sort....
0565         CondMissing::iterator load_last = set_difference(begin(cond_missing), last_cond,
0566                                                          begin(loaded), end(loaded),
0567                                                          begin(load_missing), COMP());
0568         long num_load_miss = load_last-begin(load_missing);
0569         printout(num_load_miss==0 ? DEBUG : ERROR,"UserPool",
0570                  "%ld out of %ld conditions CANNOT be loaded...",
0571                  num_load_miss, loaded.size());
0572         if ( do_output_miss )  {
0573           copy(begin(load_missing), load_last, inserter(slice_miss_cond, slice_miss_cond.begin()));
0574           for ( const auto& missing : slice_miss_cond )   {
0575             printout (ERROR, "TEST", "Unloaded: %s",missing.second->toString().c_str());
0576           }
0577         }
0578         for_each(loaded.begin(),loaded.end(),Inserter<MAPPING>(m_conditions,&m_iov));
0579         result.loaded  = slice_cond.size()-num_load_miss;
0580         result.missing = num_load_miss+num_calc_miss;
0581         if ( cond_missing.size() != loaded.size() )  {
0582           // ERROR!
0583           printout(ERROR,"UserPool","Could not load %ld out of %ld conditions. "
0584                    "[Unhandled error]",cond_missing.size(), slice_cond.size());
0585         }
0586       }
0587     }
0588     else if ( do_output_miss )  {
0589       copy(begin(cond_missing), last_cond, inserter(slice_miss_cond, slice_miss_cond.begin()));
0590       for ( const auto& missing : slice_miss_cond )   {
0591         printout (ERROR, "TEST", "Unloaded: %s",missing.second->toString().c_str());
0592       }
0593     }
0594   }
0595   //
0596   // Now we update the already existing dependencies, which have expired
0597   //
0598   if ( num_calc_miss > 0 )  {
0599     if ( do_load )  {
0600       std::map<Condition::key_type,const ConditionDependency*> deps(calc_missing.begin(),last_calc);
0601       ConditionsDependencyHandler handler(m_manager, *this, deps, user_param);
0602       /// 1rst pass: Compute/create the missing condiions
0603       handler.compute();
0604       /// 2nd pass:  Resolve missing dependencies
0605       handler.resolve();
0606       
0607       result.computed = handler.num_callback;
0608       result.missing -= handler.num_callback;
0609       if ( do_output_miss && result.computed < deps.size() )  {
0610         // Is this cheaper than an intersection ?
0611         for( auto i = calc_missing.begin(); i != last_calc; ++i )   {
0612           typename MAPPING::iterator j = m_conditions.find((*i).first);
0613           if ( j == m_conditions.end() )
0614             slice_miss_calc.emplace(*i);
0615         }
0616       }
0617     }
0618     else if ( do_output_miss )  {
0619       copy(begin(calc_missing), last_calc, inserter(slice_miss_calc, slice_miss_calc.begin()));
0620     }
0621   }
0622   slice.status = result;
0623   slice.used_pools.clear();
0624   if ( slice.flags&ConditionsSlice::REF_POOLS )   {
0625     m_iovPool->select(required, slice.used_pools);
0626   }
0627   return result;
0628 }
0629 
0630 template<typename MAPPING> ConditionsManager::Result
0631 ConditionsMappedUserPool<MAPPING>::load(const IOV&                  required, 
0632                                         ConditionsSlice&            slice,
0633                                         ConditionUpdateUserContext* /* user_param */)
0634 {
0635   typedef std::vector<std::pair<Condition::key_type,ConditionsLoadInfo*> >  CondMissing;
0636   const auto& slice_cond = slice.content->conditions();
0637   auto&  slice_miss_cond = slice.missingConditions();
0638   bool   do_load         = m_manager->doLoadConditions();
0639   bool   do_output_miss  = m_manager->doOutputUnloaded();
0640   IOV    pool_iov(required.iovType);
0641   ConditionsManager::Result result;
0642 
0643   // This is a critical operation, because we have to ensure the
0644   // IOV pools are ONLY manipulated by the current thread.
0645   // Otherwise the selection and the population are unsafe!
0646   static std::mutex lock;
0647   std::lock_guard<std::mutex> guard(lock);
0648 
0649   m_conditions.clear();
0650   slice_miss_cond.clear();
0651   pool_iov.reset().invert();
0652   m_iovPool->select(required, Operators::mapConditionsSelect(m_conditions), pool_iov);
0653   m_iov = pool_iov;
0654   CondMissing cond_missing(slice_cond.size()+m_conditions.size());
0655   CondMissing::iterator last_cond = set_difference(begin(slice_cond),   end(slice_cond),
0656                                                    begin(m_conditions), end(m_conditions),
0657                                                    begin(cond_missing), COMP());
0658   long num_cond_miss = last_cond-begin(cond_missing);
0659   cond_missing.resize(num_cond_miss);
0660   printout((flags&PRINT_LOAD) ? INFO : DEBUG,"UserPool",
0661            "Found %ld missing conditions out of %ld conditions.",
0662            num_cond_miss, slice_cond.size());
0663   result.loaded   = 0;
0664   result.computed = 0;
0665   result.missing  = num_cond_miss;
0666   result.selected = m_conditions.size();
0667   //
0668   // Now we load the missing conditions from the conditions loader
0669   //
0670   if ( num_cond_miss > 0 )  {
0671     if ( do_load )  {
0672       ConditionsDataLoader::LoadedItems loaded;
0673       size_t updates = m_loader->load_many(required, cond_missing, loaded, pool_iov);
0674       if ( updates > 0 )  {
0675         // Need to compute the intersection: All missing entries are required....
0676         CondMissing load_missing(cond_missing.size()+loaded.size());
0677         // Note: cond_missing is already sorted (doc of 'set_difference'). No need to re-sort....
0678         CondMissing::iterator load_last = set_difference(begin(cond_missing), last_cond,
0679                                                          begin(loaded), end(loaded),
0680                                                          begin(load_missing), COMP());
0681         long num_load_miss = load_last-begin(load_missing);
0682         printout(num_load_miss==0 ? DEBUG : ERROR,"UserPool",
0683                  "+++ %ld out of %ld conditions CANNOT be loaded... [Not found by loader]",
0684                  num_load_miss, loaded.size());
0685         if ( do_output_miss )  {
0686           copy(begin(load_missing), load_last, inserter(slice_miss_cond, slice_miss_cond.begin()));
0687         }
0688         for_each(loaded.begin(),loaded.end(),Inserter<MAPPING>(m_conditions,&m_iov));
0689         result.loaded  = slice_cond.size()-num_load_miss;
0690         result.missing = num_load_miss;
0691         if ( cond_missing.size() != loaded.size() )  {
0692           // ERROR!
0693         }
0694       }
0695     }
0696     else if ( do_output_miss )  {
0697       copy(begin(cond_missing), last_cond, inserter(slice_miss_cond, slice_miss_cond.begin()));
0698     }
0699   }
0700   slice.status = result;
0701   return result;
0702 }
0703 
0704 template<typename MAPPING> ConditionsManager::Result
0705 ConditionsMappedUserPool<MAPPING>::compute(const IOV&                  required, 
0706                                            ConditionsSlice&            slice,
0707                                            ConditionUpdateUserContext* user_param)
0708 {
0709   typedef std::vector<std::pair<Condition::key_type,ConditionDependency*> > CalcMissing;
0710   const auto& slice_calc = slice.content->derived();
0711   auto&  slice_miss_calc = slice.missingDerivations();
0712   bool   do_load         = m_manager->doLoadConditions();
0713   bool   do_output       = m_manager->doOutputUnloaded();
0714   IOV    pool_iov(required.iovType);
0715   ConditionsManager::Result result;
0716 
0717   // This is a critical operation, because we have to ensure the
0718   // IOV pools are ONLY manipulated by the current thread.
0719   // Otherwise the selection and the population are unsafe!
0720   static std::mutex lock;
0721   std::lock_guard<std::mutex> guard(lock);
0722 
0723   slice_miss_calc.clear();
0724   CalcMissing calc_missing(slice_calc.size()+m_conditions.size());
0725   CalcMissing::iterator last_calc = set_difference(begin(slice_calc),   end(slice_calc),
0726                                                    begin(m_conditions), end(m_conditions),
0727                                                    begin(calc_missing), COMP());
0728   long num_calc_miss = last_calc-begin(calc_missing);
0729   calc_missing.resize(num_calc_miss);
0730   printout((flags&PRINT_COMPUTE) ? INFO : DEBUG,"UserPool",
0731            "Found %ld missing derived conditions out of %ld conditions.",
0732            num_calc_miss, m_conditions.size());
0733 
0734   result.loaded   = 0;
0735   result.computed = 0;
0736   result.missing  = num_calc_miss;
0737   result.selected = m_conditions.size();
0738   //
0739   // Now we update the already existing dependencies, which have expired
0740   //
0741   if ( num_calc_miss > 0 )  {
0742     if ( do_load )  {
0743       std::map<Condition::key_type,const ConditionDependency*> deps(calc_missing.begin(),last_calc);
0744       ConditionsDependencyHandler handler(m_manager, *this, deps, user_param);
0745 
0746       /// 1rst pass: Compute/create the missing condiions
0747       handler.compute();
0748       /// 2nd pass:  Resolve missing dependencies
0749       handler.resolve();
0750 
0751       result.computed = handler.num_callback;
0752       result.missing -= handler.num_callback;
0753       if ( do_output && result.computed < deps.size() )  {
0754         for(auto i=calc_missing.begin(); i != last_calc; ++i)   {
0755           typename MAPPING::iterator j = m_conditions.find((*i).first);
0756           if ( j == m_conditions.end() )
0757             slice_miss_calc.emplace(*i);
0758         }
0759       }
0760     }
0761     else if ( do_output )  {
0762       copy(begin(calc_missing), last_calc, inserter(slice_miss_calc, slice_miss_calc.begin()));
0763     }
0764   }
0765   slice.status += result;
0766   slice.used_pools.clear();
0767   if ( slice.flags&ConditionsSlice::REF_POOLS )   {
0768     m_iovPool->select(required, slice.used_pools);
0769   }
0770   return result;
0771 }
0772 
0773 
0774 /// Namespace for the AIDA detector description toolkit
0775 namespace dd4hep {
0776 
0777   /// Namespace for implementation details of the AIDA detector description toolkit
0778   namespace cond {
0779 
0780     typedef std::unordered_map<Condition::key_type,Condition::Object*> umap_t;
0781 
0782     /// Access all conditions within a given key range
0783     /** Specialization necessary, since unordered maps have no lower bound.
0784      */
0785     template<> void
0786     ConditionsMappedUserPool<umap_t>::scan(Condition::key_type lower,
0787                                            Condition::key_type upper,
0788                                            const Condition::Processor& processor)   const  {
0789       for( const auto& e : m_conditions )
0790         if ( e.second->hash >= lower && e.second->hash <= upper )
0791           processor(e.second);
0792     }
0793     /// Access all conditions within a given key range
0794     /** Specialization necessary, since unordered maps have no lower bound.
0795      */
0796     template<> std::vector<Condition>
0797     ConditionsMappedUserPool<umap_t>::get(Condition::key_type lower, Condition::key_type upper)   const  {
0798       std::vector<Condition> result;
0799       for( const auto& e : m_conditions )  {
0800         if ( e.second->hash >= lower && e.second->hash <= upper )
0801           result.emplace_back(e.second);
0802       }
0803       return result;
0804     }
0805   }    /* End namespace cond               */
0806 }      /* End namespace dd4hep                   */
0807 
0808 namespace {
0809   template <typename MAPPING>
0810   void* create_pool(dd4hep::Detector&, int argc, char** argv)  {
0811     if ( argc > 1 )  {
0812       ConditionsManagerObject* m = (ConditionsManagerObject*)argv[0];
0813       ConditionsIOVPool* p = (ConditionsIOVPool*)argv[1];
0814       UserPool* pool = new ConditionsMappedUserPool<MAPPING>(m, p);
0815       return pool;
0816     }
0817     dd4hep::except("ConditionsMappedUserPool","++ Insufficient arguments: arg[0] = ConditionManager!");
0818     return 0;
0819   }
0820 }
0821 
0822 // Factory for the user pool using a binary tree map
0823 void* create_map_user_pool(dd4hep::Detector& description, int argc, char** argv)
0824 {  return create_pool<std::map<dd4hep::Condition::key_type,dd4hep::Condition::Object*> >(description, argc, argv);  }
0825 DECLARE_DD4HEP_CONSTRUCTOR(DD4hep_ConditionsMapUserPool, create_map_user_pool)
0826 
0827 // Factory for the user pool using a binary tree map
0828 void* create_unordered_map_user_pool(dd4hep::Detector& description, int argc, char** argv)
0829 {  return create_pool<std::unordered_map<dd4hep::Condition::key_type,dd4hep::Condition::Object*> >(description, argc, argv);  }
0830 DECLARE_DD4HEP_CONSTRUCTOR(DD4hep_ConditionsUnorderedMapUserPool, create_map_user_pool)