Newer
Older
//==========================================================================
//--------------------------------------------------------------------------
// 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/ConditionsDependencyHandler.h"
#include "DDCond/ConditionsManagerObject.h"
#include "DD4hep/Printout.h"
using namespace dd4hep;
using namespace dd4hep::cond;
namespace {
std::string dependency_name(const ConditionDependency* d) {
#ifdef DD4HEP_CONDITIONS_DEBUG
return d->target.name;
#else
char text[64];
ConditionKey::KeyMaker key(d->target.hash);
::snprintf(text,sizeof(text),"%08X %08X",key.values.det_key, key.values.item_key);
return text;
#endif
}
}
ConditionsDependencyHandler::ConditionsDependencyHandler(ConditionsManager mgr,
const Dependencies& dependencies,
Markus Frank
committed
ConditionUpdateUserContext* user_param)
: m_manager(mgr.access()), m_pool(pool), m_dependencies(dependencies),
m_userParam(user_param), num_callback(0)
Markus Frank
committed
//IOV full_iov(iov.iovType,IOV::Key(IOV::MIN_KEY,IOV::MAX_KEY));
IOV full_iov(iov.iovType,IOV::Key(0,detail::makeTime(2099,12,31)));
m_iovPool = m_manager->registerIOV(*iov.iovType, iov.keyData);
Markus Frank
committed
unsigned char* p = new unsigned char[dependencies.size()*sizeof(Work)];
Dependencies::const_iterator idep = dependencies.begin();
m_block = (Work*)p;
for(size_t i=0; i<dependencies.size(); ++i, ++idep, p+=sizeof(Work)) {
Work* w = new(p) Work(this,(*idep).second,user_param,full_iov);
m_todo.insert(std::make_pair((*idep).first,w));
}
}
/// Default destructor
ConditionsDependencyHandler::~ConditionsDependencyHandler() {
Markus Frank
committed
m_todo.clear();
m_created.clear();
if ( m_block ) delete [] m_block;
m_block = 0;
/// ConditionResolver implementation: Access to the detector description instance
Detector& ConditionsDependencyHandler::detectorDescription() const {
return m_manager->detectorDescription();
Markus Frank
committed
/// 1rst pass: Compute/create the missing conditions
void ConditionsDependencyHandler::compute() {
m_state = CREATED;
Markus Frank
committed
for( const auto& i : m_todo ) {
if ( !i.second->condition ) {
do_callback(i.second);
Markus Frank
committed
continue;
}
// printout(INFO,"UserPool","Already calcluated: %s",d->name());
continue;
}
}
/// 2nd pass: Handler callback for the second turn to resolve missing dependencies
void ConditionsDependencyHandler::resolve() {
Markus Frank
committed
size_t num_resolved = 0;
std::map<IOV::Key,ConditionsPool*> pools;
Markus Frank
committed
m_state = RESOLVED;
for( auto& c : m_created ) {
Markus Frank
committed
Work* w = c.second;
if ( w->state == RESOLVED ) continue;
w->state = RESOLVED;
w->context.dependency->callback->resolve(w->condition, w->context);
++num_resolved;
}
// Optimize pool interactions: Cache pool in map assuming there are only few pools created
for( auto& c : m_created ) {
Work* w = c.second;
ConditionsPool* p = 0;
auto res = pools.insert(make_pair(w->iov.keyData,p));
if ( res.second ) {
p = m_manager->registerIOV(*w->iov.iovType, w->iov.keyData);
(*res.first).second = p;
}
p = (*res.first).second;
w->condition->iov = p->iov;
m_manager->registerUnlocked(*p, w->condition);
Markus Frank
committed
}
}
/// Interface to access conditions by hash value of the DetElement (only valid at resolve!)
std::vector<Condition> ConditionsDependencyHandler::get(DetElement de) {
return this->get(de.key());
}
/// Interface to access conditions by hash value of the DetElement (only valid at resolve!)
std::vector<Condition> ConditionsDependencyHandler::get(Condition::detkey_type det_key) {
if ( m_state == RESOLVED ) {
ConditionKey::KeyMaker lower(det_key, 0);
ConditionKey::KeyMaker upper(det_key, ~0x0);
return m_pool.get(lower.hash, upper.hash);
}
except("ConditionsDependencyHandler",
"Conditions bulk accesses are only possible during conditions resolution!");
return std::vector<Condition>();
}
/// ConditionResolver implementation: Interface to access conditions
Markus Frank
committed
Condition ConditionsDependencyHandler::get(Condition::key_type key, bool throw_if_not) {
Markus Frank
committed
/// Check if the required condition is one of the newly created ones:
auto e = m_created.find(key);
if ( e != m_created.end() ) {
Markus Frank
committed
Work* w = (*e).second;
if ( w->state == CREATED ) {
w->state = RESOLVED;
w->context.dependency->callback->resolve(w->condition, w->context);
return w->condition;
Markus Frank
committed
}
}
/// If we are not already resolving here, we follow the normal procedure
Condition c = m_pool.get(key);
if ( c.isValid() ) {
Markus Frank
committed
return c;
}
auto i = m_todo.find(key);
if ( i != m_todo.end() ) {
c = do_callback((*i).second);
if ( c.isValid() ) {
Markus Frank
committed
if ( throw_if_not ) {
except("ConditionsDependencyHandler","Failed to resolve conditon:%16lX",key);
return Condition();
}
Markus Frank
committed
ConditionsDependencyHandler::do_callback(Work* work) {
const ConditionDependency* dep = work->context.dependency;
Markus Frank
committed
work->condition = (*dep->callback)(dep->target, work->context).ptr();
if ( work->condition ) {
work->condition->iov = &work->iov;
work->condition->hash = dep->target.hash;
work->condition->setFlag(Condition::DERIVED);
work->state = CREATED;
//TEST cond->iov = m_pool.validityPtr();
// Must IMMEDIATELY insert to handle inter-dependencies.
Markus Frank
committed
m_created[dep->target.hash] = work;
//TEST m_manager->registerUnlocked(*m_iovPool, work.condition);
m_pool.insert(work->condition);
Markus Frank
committed
return work->condition;
}
catch(const std::exception& e) {
printout(ERROR,"ConditionDependency",
"+++ Exception while creating dependent Condition %s:",
dependency_name(dep).c_str());
printout(ERROR,"ConditionDependency","\t\t%s", e.what());
}
catch(...) {
printout(ERROR,"ConditionDependency",
"+++ UNKNOWN exception while creating dependent Condition %s.",
dependency_name(dep).c_str());
}
m_pool.print("*");
except("ConditionDependency",
"++ Exception while creating dependent Condition %s.",
dependency_name(dep).c_str());