ATLAS Offline Software
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
Ath::DynamicDataHelper Class Reference

Helper class to gather all declared data IDs and propagate them to components which declare data dependencies dynamically. More...

#include <DynamicDataHelper.h>

Collaboration diagram for Ath::DynamicDataHelper:

Public Member Functions

void gatherDataHandlesAndDynamicConsumers (const std::string &parent_name, Gaudi::Algorithm *theAlgorithm)
 Gather the input and output data declared by the given algorithm, its child algorithms and their tools. More...
 
StatusCode addExtraDependencies (IClassIDSvc &clid_svc, std::vector< std::string > &undeclared_output_data, MsgStream &out)
 Add extra output data which is not declared by any of the gathered components. More...
 
void updateDataNeeds (unsigned int max_pass, MsgStream &out)
 Update the data dependencies of all components which dynamically declare tehm. More...
 

Protected Member Functions

bool updateDataNeeds (const std::vector< const DataObjID * > &input_data_in, const std::vector< const DataObjID * > &output_data_in, std::vector< const DataObjID * > &input_data_out, std::vector< const DataObjID * > &output_data_out, MsgStream &out)
 Update the data dependencies of all components once. More...
 

Protected Attributes

std::vector< DataObjID > m_extraOutputIDs
 
DataObjIDPtrColl m_inputHandles
 
DataObjIDPtrColl m_outputHandles
 
std::unordered_map< IDynamicDataConsumer *, std::vector< Gaudi::Algorithm * > > m_dynDataConsumer
 

Detailed Description

Helper class to gather all declared data IDs and propagate them to components which declare data dependencies dynamically.

Definition at line 25 of file DynamicDataHelper.h.

Member Function Documentation

◆ addExtraDependencies()

StatusCode Ath::DynamicDataHelper::addExtraDependencies ( IClassIDSvc &  clid_svc,
std::vector< std::string > &  undeclared_output_data,
MsgStream &  out 
)

Add extra output data which is not declared by any of the gathered components.

Parameters
clid_svcthe ClassIDSvc needed to translate the type name into a CLID.
undeclared_output_datastrings which are composed of the type and variable name separated by "/".
outthe message output stream used for error messages.

Definition at line 26 of file DynamicDataHelper.cxx.

26  {
27  std::stringstream error;
28  if (!m_extraOutputIDs.empty()) {
29  out << MSG::FATAL << "Logic erroor. Already added some extra output data IDs. This method can only be called once." << endmsg;
30  return StatusCode::FAILURE;
31  }
32  m_extraOutputIDs.reserve( undeclared_output_data.size() );
33  for(const std::string &type_and_name : undeclared_output_data) {
34  std::string::size_type pos = type_and_name.find('/');
35  if (pos == std::string::npos) {
36  error << " " << type_and_name;
37  }
38  else {
39  std::string_view type_name(type_and_name.data(), pos);
40  std::string_view var_name(&(type_and_name.data()[pos+1]), type_and_name.size()-pos-1);
41  CLID clid;
42  if (clid_svc.getIDOfTypeName(std::string(type_name), clid).isFailure() ) {
43  // out << MSG::FATAL << " Failed to get CLID for " << type_name << endmsg;
44  // return StatusCode::FAILURE;
45  error << " no clid: " << type_name;
46  }
47  else {
48  m_extraOutputIDs.push_back( DataObjID(clid, std::string(var_name)) );
49  if (msgLvl(out,MSG::VERBOSE)) {
50  out << MSG::VERBOSE << "DEBUG add extra dependency " << type_name << " / " << var_name << " -> " << clid << endmsg;
51  }
52  }
53  }
54  }
55  if (!error.str().empty()) {
56  out << MSG::FATAL << "Invaid alements in property " << error.str().c_str() << endmsg;
57  return StatusCode::FAILURE;
58  }
59  for (const DataObjID &id : m_extraOutputIDs ) {
60  m_outputHandles.insert( &id );
61  }
62  return StatusCode::SUCCESS;
63  }

◆ gatherDataHandlesAndDynamicConsumers()

void Ath::DynamicDataHelper::gatherDataHandlesAndDynamicConsumers ( const std::string &  parent_name,
Gaudi::Algorithm *  theAlgorithm 
)

Gather the input and output data declared by the given algorithm, its child algorithms and their tools.

Parameters
parent_namethe name of the parent component used in messsages
theAlgorithmthe top algorithm to start the collection Additionally also all components are collected which dynamically declare their data dependencies.

Definition at line 65 of file DynamicDataHelper.cxx.

65  {
66  // |> debugging
67  auto algorithm_visitor =
68  [this](Gaudi::Algorithm *an_alg) {
69  IDynamicDataConsumer *a_dyn_data_consumer=dynamic_cast<IDynamicDataConsumer *>(an_alg);
70  if (a_dyn_data_consumer) {
71  std::vector<Gaudi::Algorithm *> &alg_list = m_dynDataConsumer[a_dyn_data_consumer];
72  if (std::find(alg_list.begin(),alg_list.end(),an_alg)==alg_list.end()) {
73  alg_list.push_back(an_alg);
74  }
75  }
76  // have to collect input and output handles because the sequence will only collect them after initialize
77  insertHandles(m_inputHandles, an_alg->inputHandles());
78  insertHandles(m_outputHandles, an_alg->outputHandles());
79  std::vector<IAlgTool *> &tools ATLAS_THREAD_SAFE
80  = const_cast< std::vector<IAlgTool *> &>(const_cast<const Gaudi::Algorithm *>(an_alg)->tools());
81  // |> debugging
82  auto tool_visitor = [this, an_alg](IAlgTool *alg_tool) {
83  IDynamicDataConsumer *a_dyn_data_consumer=dynamic_cast<IDynamicDataConsumer *>(alg_tool);
84  if (a_dyn_data_consumer) {
85  std::vector<Gaudi::Algorithm *> &alg_list = m_dynDataConsumer[a_dyn_data_consumer];
86  if (std::find(alg_list.begin(),alg_list.end(),an_alg)==alg_list.end()) {
87  alg_list.push_back(an_alg);
88  }
89  }
90  if (auto* tool_impl = dynamic_cast<AlgTool*>( alg_tool ); tool_impl) {
91  insertHandles(m_inputHandles, tool_impl->inputHandles());
92  insertHandles(m_outputHandles, tool_impl->outputHandles());
93  }
94  };
95  xGaudi::ToolVisitor::visit( tools,tool_visitor);
96  };
97  xGaudi::AlgorithmVisitor::visit({theAlgorithm},algorithm_visitor);
98  }

◆ updateDataNeeds() [1/2]

bool Ath::DynamicDataHelper::updateDataNeeds ( const std::vector< const DataObjID * > &  input_data_in,
const std::vector< const DataObjID * > &  output_data_in,
std::vector< const DataObjID * > &  input_data_out,
std::vector< const DataObjID * > &  output_data_out,
MsgStream &  out 
)
protected

Update the data dependencies of all components once.

Parameters
input_data_inIDs of all declared input data
output_data_inIDs of all declared output data
input_data_outIDs of newly declared input data in this iteration
output_data_outIDs of newly declared input data in this iteration
Returns
true if new input or output data was declared.

Definition at line 121 of file DynamicDataHelper.cxx.

125  {
126  bool updated=false;
127  if (msgLvl(out,MSG::VERBOSE)) {
128  out<< MSG::VERBOSE << " inputs:";
129  for (const DataObjID *id : input_data_in) {
130  out << " " << *id ;
131  }
132  out << endmsg;
133  out << MSG::VERBOSE << " outputs:";
134  for (const DataObjID *id : output_data_in) {
135  out << " " << *id ;
136  }
137  out << endmsg;
138  }
139  for (std::pair<IDynamicDataConsumer * const,std::vector<Gaudi::Algorithm *> > &dyn_data_consumer : m_dynDataConsumer ) {
140  std::vector<Gaudi::DataHandle *> tmp_new_input_handles;
141  std::vector<Gaudi::DataHandle *> tmp_new_output_handles;
142  bool ret = dyn_data_consumer.first->updateDataNeeds(input_data_in, output_data_in, tmp_new_input_handles, tmp_new_output_handles);
143  if (msgLvl(out,MSG::VERBOSE)) {
144  out << MSG::VERBOSE << " new data for";
145  for (const Gaudi::Algorithm *parent_alg : dyn_data_consumer.second) {
146  out << " " << parent_alg->name();
147  }
148  out << " i:" << tmp_new_input_handles.size()
149  << " o:" << tmp_new_output_handles.size()
150  << endmsg;
151  }
152  updated |= ret;
153  if (ret) {
154  if (msgLvl(out,MSG::DEBUG)) {
155  if (Gaudi::Algorithm * const an_alg = dynamic_cast<Gaudi::Algorithm * const>(dyn_data_consumer.first); an_alg) {
156  out << MSG::DEBUG << an_alg->name() << " updated its data needs." << endmsg;
157  // DEBUG:
158  out << MSG::DEBUG << an_alg->name() << " inputs:";
159  for (const Gaudi::DataHandle *handle : an_alg->inputHandles()) {
160  out << " " << handle->fullKey();
161  }
162  out << endmsg;
163  }
164  else if (AlgTool *alg_tool = dynamic_cast<AlgTool * const>(dyn_data_consumer.first); alg_tool) {
165  out << MSG::DEBUG << alg_tool->name() << " updated its data needs." << endmsg;
166  // DEBUG:
167  out << MSG::DEBUG << alg_tool->name() << " inputs:";
168  for (const Gaudi::DataHandle *handle : alg_tool->inputHandles()) {
169  out << " " << handle->fullKey();
170  }
171  out << endmsg;
172  }
173  else {
174  out << MSG::WARNING << "Unknown dynamic data consumer type " << typeid(dyn_data_consumer.first).name() << endmsg;
175  }
176  }
177  }
178  for (Gaudi::Algorithm *parent_alg : dyn_data_consumer.second) {
179  input_data_out.reserve(input_data_out.size()+tmp_new_input_handles.size());
180  for (Gaudi::DataHandle *a_handle : tmp_new_input_handles) {
181  parent_alg->addDependency(a_handle->fullKey(), Gaudi::DataHandle::Reader);
182  input_data_out.push_back(&(a_handle->fullKey()));
183  if (msgLvl(out,MSG::DEBUG)) out << MSG::DEBUG << " addDependency new input for " << parent_alg->name() << " "
184  << a_handle->fullKey().className() << " / " << a_handle->objKey() << endmsg;
185  }
186  output_data_out.reserve(output_data_out.size()+tmp_new_output_handles.size());
187  for (Gaudi::DataHandle *a_handle : tmp_new_output_handles) {
188  parent_alg->addDependency(a_handle->fullKey(), Gaudi::DataHandle::Writer);
189  output_data_out.push_back(&(a_handle->fullKey()));
190  if (msgLvl(out,MSG::DEBUG)) out << MSG::DEBUG << " addDependency new output for " << parent_alg->name() << " "
191  << a_handle->fullKey().className() << " / " << a_handle->objKey() << endmsg;
192  }
193  }
194  }
195  return updated;
196  }

◆ updateDataNeeds() [2/2]

void Ath::DynamicDataHelper::updateDataNeeds ( unsigned int  max_pass,
MsgStream &  out 
)

Update the data dependencies of all components which dynamically declare tehm.

Parameters
max_passmaximum number of iterations
outthe message stream of the parent component The update happens iteratively until non of the components declares new output data, but at most max_pass times.

Definition at line 100 of file DynamicDataHelper.cxx.

101  {
102  if (msgLvl(out,MSG::VERBOSE)) out << MSG::VERBOSE << "Allow dynamic data consumers to update their data dependencies." << endmsg;
103  std::vector<const DataObjID *> all_input_data;
104  std::vector<const DataObjID *> all_output_data;
105  all_input_data.insert( all_input_data.end(), m_inputHandles.begin(), m_inputHandles.end());
106  all_output_data.insert( all_output_data.end(), m_outputHandles.begin(), m_outputHandles.end());
107 
108  std::vector<const DataObjID *> new_input_data;
109  std::vector<const DataObjID *> new_output_data;
110  unsigned int pass_i=max_pass;
111  unsigned last_out_size=new_output_data.size();
112  for (; --pass_i>0 && updateDataNeeds(all_input_data, all_output_data, new_input_data, new_output_data,out); ) {
113  if (last_out_size == new_output_data.size() ) break;
114  last_out_size=new_output_data.size();
115  };
116  if (last_out_size != new_output_data.size()) {
117  out << MSG::WARNING << "Not iterating any further, although after " << max_pass << " iterations there are still algorithms which updated their data needs. " << endmsg;
118  }
119  }

Member Data Documentation

◆ m_dynDataConsumer

std::unordered_map< IDynamicDataConsumer *,std::vector<Gaudi::Algorithm *> > Ath::DynamicDataHelper::m_dynDataConsumer
protected

Definition at line 69 of file DynamicDataHelper.h.

◆ m_extraOutputIDs

std::vector<DataObjID> Ath::DynamicDataHelper::m_extraOutputIDs
protected

Definition at line 65 of file DynamicDataHelper.h.

◆ m_inputHandles

DataObjIDPtrColl Ath::DynamicDataHelper::m_inputHandles
protected

Definition at line 66 of file DynamicDataHelper.h.

◆ m_outputHandles

DataObjIDPtrColl Ath::DynamicDataHelper::m_outputHandles
protected

Definition at line 67 of file DynamicDataHelper.h.


The documentation for this class was generated from the following files:
python.Constants.FATAL
int FATAL
Definition: Control/AthenaCommon/python/Constants.py:19
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
CheckAppliedSFs.var_name
var_name
Definition: CheckAppliedSFs.py:241
IDynamicDataConsumer
Definition: IDynamicDataConsumer.h:15
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
Ath::DynamicDataHelper::m_extraOutputIDs
std::vector< DataObjID > m_extraOutputIDs
Definition: DynamicDataHelper.h:65
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
LHEF::Reader
Pythia8::Reader Reader
Definition: Prophecy4fMerger.cxx:11
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
Ath::DynamicDataHelper::m_outputHandles
DataObjIDPtrColl m_outputHandles
Definition: DynamicDataHelper.h:67
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:227
tools
Definition: DataQuality/ZLumiScripts/python/tools/__init__.py:1
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Ath::DynamicDataHelper::m_inputHandles
DataObjIDPtrColl m_inputHandles
Definition: DynamicDataHelper.h:66
DEBUG
#define DEBUG
Definition: page_access.h:11
Ath::DynamicDataHelper::updateDataNeeds
void updateDataNeeds(unsigned int max_pass, MsgStream &out)
Update the data dependencies of all components which dynamically declare tehm.
Definition: DynamicDataHelper.cxx:100
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
LHEF::Writer
Pythia8::Writer Writer
Definition: Prophecy4fMerger.cxx:12
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
get_generator_info.error
error
Definition: get_generator_info.py:40
error
Definition: IImpactPoint3dEstimator.h:70
Ath::DynamicDataHelper::m_dynDataConsumer
std::unordered_map< IDynamicDataConsumer *, std::vector< Gaudi::Algorithm * > > m_dynDataConsumer
Definition: DynamicDataHelper.h:69