Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:16:30

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 
0014 // Framework include files
0015 #include <DDCond/ConditionsDependencyHandler.h>
0016 #include <DDCond/ConditionsManagerObject.h>
0017 #include <DD4hep/ConditionsProcessor.h>
0018 #include <DD4hep/Printout.h>
0019 #include <TTimeStamp.h>
0020 
0021 using namespace dd4hep::cond;
0022 
0023 namespace {
0024   std::string dependency_name(const ConditionDependency* d)  {
0025 #if defined(DD4HEP_CONDITIONS_HAVE_NAME)
0026     return d->target.name;
0027 #else
0028     char text[64];
0029     dd4hep::ConditionKey::KeyMaker key(d->target.hash);
0030     ::snprintf(text,sizeof(text),"%08X %08X",key.values.det_key, key.values.item_key);
0031     return text;
0032 #endif
0033   }
0034 }
0035 
0036 void ConditionsDependencyHandler::Work::do_intersection(const IOV* iov_ptr)   {
0037   if ( iov_ptr )   {
0038     if ( !this->iov )   {
0039       this->_iov = *iov_ptr;
0040       this->iov = &this->_iov;
0041     }
0042     else  {
0043       this->_iov.iov_intersection(*iov_ptr);
0044     }
0045   }
0046 }
0047 
0048 dd4hep::Condition
0049 ConditionsDependencyHandler::Work::resolve(Work*& current)   {
0050   Work* previous = current;
0051   current = this;
0052   state = RESOLVED;
0053   if ( !condition )   {
0054     printout(ERROR,"DependencyHandler","ERROR: Cannot resolve not existing conditions.");
0055   }
0056   context.dependency->callback->resolve(condition, context);
0057   previous->do_intersection(iov);
0058   current = previous;
0059   return condition;
0060 }
0061 
0062 /// Default constructor
0063 ConditionsDependencyHandler::ConditionsDependencyHandler(ConditionsManager   mgr,
0064                                                          UserPool&           pool,
0065                                                          const Dependencies& dependencies,
0066                                                          ConditionUpdateUserContext* user_param)
0067   : m_manager(mgr.access()), m_pool(pool), m_dependencies(dependencies),
0068     m_userParam(user_param), num_callback(0)
0069 {
0070   const IOV& iov = m_pool.validity();
0071   unsigned char* p = new unsigned char[dependencies.size()*sizeof(Work)];
0072   m_block = (Work*)p;
0073   for(const auto& d : dependencies)  {
0074     Work* w = new(p) Work(this,d.second,user_param,iov);
0075     m_todo.emplace(d.first,w);
0076     p += sizeof(Work);
0077   }
0078   m_iovType = iov.iovType;
0079 }
0080 
0081 /// Default destructor
0082 ConditionsDependencyHandler::~ConditionsDependencyHandler()   {
0083   m_todo.clear();
0084   if ( m_block ) delete [] m_block;
0085   m_block = 0;
0086 }
0087 
0088 /// ConditionResolver implementation: Access to the detector description instance
0089 dd4hep::Detector& ConditionsDependencyHandler::detectorDescription() const  {
0090   return m_manager->detectorDescription();
0091 }
0092 
0093 /// 1rst pass: Compute/create the missing conditions
0094 void ConditionsDependencyHandler::compute()   {
0095   m_state = CREATED;
0096   for( const auto& i : m_todo )   {
0097     if ( !i.second->condition )  {
0098       do_callback(i.second);
0099       if ( !i.second->condition )  {
0100         except("DependencyHandler",
0101                "Derived condition was not created after calling the creation callback!");
0102       }
0103     }
0104     // printout(INFO,"UserPool","Already calcluated: %s",d->name());
0105   }
0106 }
0107 
0108 /// 2nd pass:  Handler callback for the second turn to resolve missing dependencies
0109 void ConditionsDependencyHandler::resolve()    {
0110   PrintLevel prt_lvl = INFO;
0111   std::vector<Condition> tmp;
0112   std::map<IOV::Key,std::vector<Condition> > work_pools;
0113   Work* w;
0114 
0115   m_state = RESOLVED;
0116   for( const auto& c : m_todo )   {
0117     w = c.second;
0118     m_currentWork = w;
0119     if ( w->state != RESOLVED )   {
0120       w->resolve(m_currentWork);
0121     }
0122     // Fill an empty map of condition vectors for the block inserts
0123     auto ret = work_pools.emplace(w->iov->keyData,tmp);
0124     if ( ret.second )   {
0125       // There is sort of the hope that most conditions go into 1 pool...
0126       ret.first->second.reserve(m_todo.size());
0127     }
0128   }
0129   // Optimize pool interactions: Cache pool in map assuming there are only few pools created
0130   for( const auto& c : m_todo )   {
0131     w = c.second;
0132     auto& section = work_pools[w->iov->keyData];
0133     section.emplace_back(w->condition);
0134 #if 0
0135     printout(prt_lvl,"DependencyHandler","++ Register %s %s %s  [%s]",
0136              w->context.dependency->target.toString().c_str(),
0137              w->context.dependency->detector.path().c_str(),
0138              w->condition->iov->str().c_str(),
0139              typeName(typeid(*w->condition)).c_str());
0140 #endif
0141   }
0142   // Now block register all conditions to the manager AND to the user pool
0143   // In principle at thi stage the conditions manager should be locked
0144   // provided all the work done so far can be undone.....in case of an error
0145   for( const auto& section : work_pools )   {
0146     TTimeStamp start;
0147     IOV iov(m_iovType, section.first);
0148     size_t result = registerMany(iov, section.second);
0149     if ( result != section.second.size() )  {
0150       // 
0151     }
0152     TTimeStamp stop;
0153     printout(prt_lvl,"DependencyHandler","Inserted %ld [%ld] conditions to pool-iov: %s   [%7.5f seconds]",
0154              result, section.second.size(), iov.str().c_str(),
0155              stop.AsDouble()-start.AsDouble());
0156   }
0157 }
0158 
0159 /// Interface to handle multi-condition inserts by callbacks: One single insert
0160 bool ConditionsDependencyHandler::registerOne(const IOV& iov, Condition cond)    {
0161   return m_pool.registerOne(iov, cond);
0162 }
0163 
0164 /// Handle multi-condition inserts by callbacks: block insertions of conditions with identical IOV
0165 std::size_t
0166 ConditionsDependencyHandler::registerMany(const IOV& iov, const std::vector<Condition>& values)   {
0167   return m_pool.registerMany(iov, values);
0168 }
0169 
0170 /// Interface to access conditions by hash value of the DetElement (only valid at resolve!)
0171 std::vector<dd4hep::Condition>
0172 ConditionsDependencyHandler::get(DetElement de)   {
0173   return this->get(de.key());
0174 }
0175 
0176 /// Interface to access conditions by hash value of the item (only valid at resolve!)
0177 std::vector<dd4hep::Condition>
0178 ConditionsDependencyHandler::getByItem(Condition::itemkey_type key)   {
0179   if ( m_state == RESOLVED )   {
0180     struct item_selector {
0181       std::vector<Condition>  conditions;
0182       Condition::itemkey_type key;
0183       item_selector(Condition::itemkey_type k) : key(k) {}
0184       int operator()(Condition cond)   {
0185         ConditionKey::KeyMaker maker(cond->hash);
0186         if ( maker.values.item_key == key ) conditions.emplace_back(cond);
0187         return 1;
0188       }
0189     };
0190     item_selector proc(key);
0191     m_pool.scan(conditionsProcessor(proc));
0192     for (auto c : proc.conditions ) m_currentWork->do_intersection(c->iov);
0193     return proc.conditions;
0194   }
0195   except("DependencyHandler",
0196          "Conditions bulk accesses are only possible during conditions resolution!");
0197   return std::vector<Condition>();
0198 }
0199 
0200 /// Interface to access conditions by hash value of the DetElement (only valid at resolve!)
0201 std::vector<dd4hep::Condition>
0202 ConditionsDependencyHandler::get(Condition::detkey_type det_key)   {
0203   if ( m_state == RESOLVED )   {
0204     ConditionKey::KeyMaker lower(det_key, Condition::FIRST_ITEM_KEY);
0205     ConditionKey::KeyMaker upper(det_key, Condition::LAST_ITEM_KEY);
0206     std::vector<Condition> conditions = m_pool.get(lower.hash, upper.hash);
0207     for (auto c : conditions ) m_currentWork->do_intersection(c->iov);
0208     return conditions;
0209   }
0210   except("DependencyHandler",
0211          "Conditions bulk accesses are only possible during conditions resolution!");
0212   return std::vector<Condition>();
0213 }
0214 
0215 /// ConditionResolver implementation: Interface to access conditions
0216 dd4hep::Condition
0217 ConditionsDependencyHandler::get(Condition::key_type key, bool throw_if_not)  {
0218   return this->get(key, nullptr, throw_if_not);
0219 }
0220 
0221 /// ConditionResolver implementation: Interface to access conditions
0222 dd4hep::Condition
0223 ConditionsDependencyHandler::get(Condition::key_type key,
0224                                  const ConditionDependency* dependency,
0225                                  bool throw_if_not)
0226 {
0227   /// If we are not already resolving here, we follow the normal procedure
0228   Condition c = m_pool.get(key);
0229   if ( c.isValid() )  {
0230     m_currentWork->do_intersection(c->iov);
0231     return c;
0232   }
0233   auto i = m_todo.find(key);
0234   if ( i != m_todo.end() )   {
0235     Work* w = i->second;
0236     if ( w->state == RESOLVED )   {
0237       return w->condition;
0238     }
0239     else if ( w->state == CREATED )   {
0240       return w->resolve(m_currentWork);
0241     }
0242     else if ( w->state == INVALID )  {
0243       do_callback(w);
0244       if ( w->condition && w->state == RESOLVED ) // cross-dependencies...
0245         return w->condition;
0246       else if ( w->condition )
0247         return w->resolve(m_currentWork);
0248     }
0249   }
0250   if ( throw_if_not )  {
0251     if ( dependency )    {
0252       // We need here more elaborate printout to ease debugging capabilities
0253       std::string de_path   = dependency->detector.path();
0254 #if defined(DD4HEP_CONDITIONS_HAVE_NAME)
0255       std::string cond_from = dependency->target.name;
0256       std::string cond_to   = "UNKNOWN";
0257       for(const auto& d : dependency->dependencies)    {
0258         if ( d.hash == key )    {
0259           cond_to = d.name;
0260           break;
0261         }
0262       }
0263       printout(ERROR,"DependencyHandler",
0264                "Failed to resolve conditon:%016lX for DetElement: %s",
0265                key, de_path.c_str());
0266       printout(ERROR,"DependencyHandler",
0267                "Condition: %s dependent on missing condition: %s",
0268                cond_from.c_str(), cond_to.c_str());
0269 #else
0270       if ( detail::have_condition_item_inventory(-1) )   {
0271         std::string item_from = detail::get_condition_item_name(dependency->target.hash);
0272         std::string item_to   = detail::get_condition_item_name(key);
0273         printout(ERROR,"DependencyHandler",
0274                  "Failed to resolve conditon:%016lX for DetElement: %s",
0275                  key, de_path.c_str());
0276         printout(ERROR,"DependencyHandler",
0277                  "Condition: %s#%s dependent on missing condition item: %s",
0278                  de_path.c_str(), item_from.c_str(), item_to.c_str());
0279       }
0280 #endif
0281       except("DependencyHandler",
0282              "Failed to resolve conditon:%016lX for DetElement: %s",
0283              key,de_path.c_str());
0284     }
0285     except("ConditionsDependencyHandler","Failed to resolve conditon:%016lX",key);
0286   }
0287   return Condition();
0288 }
0289 
0290 /// Internal call to trigger update callback
0291 void ConditionsDependencyHandler::do_callback(Work* work)   {
0292   const ConditionDependency* dep = work->context.dependency;
0293   try  {
0294     Work* previous  = m_currentWork;
0295     m_currentWork   = work;
0296     if ( work->callstack > 0 )   {
0297       // if we end up here it means a previous construction call never finished
0298       // because the bugger tried to access another condition, which in turn
0299       // during the construction tries to access this one.
0300       // ---> Classic dead-lock
0301       except("DependencyHandler",
0302              "++ Handler caught in infinite recursion loop. Key:%s %c%s%c",
0303              work->context.dependency->target.toString().c_str(),
0304 #if defined(DD4HEP_CONDITIONS_DEBUG)
0305              '[',work->context.dependency->detector.path().c_str(),']'
0306 #else
0307              ' ',"",' '
0308 #endif
0309              );
0310     }
0311     ++work->callstack;
0312     work->condition = (*dep->callback)(dep->target, work->context).ptr();
0313     --work->callstack;
0314     m_currentWork   = previous;
0315     if ( work->condition )  {
0316       if ( !work->iov )  {
0317         work->_iov = IOV(m_iovType,IOV::Key(IOV::MIN_KEY, IOV::MAX_KEY));
0318         work->iov  = &work->_iov;
0319       }
0320       if ( previous )   {
0321         previous->do_intersection(work->iov);
0322       }
0323       work->condition->iov  = work->iov;
0324       work->condition->hash = dep->target.hash;
0325       work->condition->setFlag(Condition::DERIVED);
0326       work->state = CREATED;
0327       ++num_callback;
0328     }
0329     else   {
0330       printout(ERROR,"DependencyHandler",
0331                "+++ Callback handler returned invalid condition.  Key:%s %c%s%c",
0332                work->context.dependency->target.toString().c_str(),
0333 #if defined(DD4HEP_CONDITIONS_DEBUG)
0334                '[',work->context.dependency->detector.path().c_str(),']'
0335 #else
0336                ' ',"",' '
0337 #endif
0338                );
0339       throw std::runtime_error("Invalid derived condition callback");
0340     }
0341     return;
0342   }
0343   catch(const std::exception& e)   {
0344     printout(ERROR,"DependencyHandler",
0345              "+++ Exception while creating dependent Condition %s:",
0346              dependency_name(dep).c_str());
0347     printout(ERROR,"DependencyHandler","\t\t%s", e.what());
0348   }
0349   catch(...)   {
0350     printout(ERROR,"DependencyHandler",
0351              "+++ UNKNOWN exception while creating dependent Condition %s.",
0352              dependency_name(dep).c_str());
0353   }
0354   m_pool.print("*");
0355   except("DependencyHandler",
0356          "++ Exception while creating dependent Condition %s.",
0357          dependency_name(dep).c_str());
0358 }