20 #include <boost/lexical_cast.hpp>
21 #include <boost/tokenizer.hpp>
28 using extends::extends;
31 const std::vector<std::string>& stoppers = {} )
const override;
33 const std::vector<std::string>& stoppers = {} )
const override;
42 "Attribute any unmet input dependencies to this Algorithm" };
44 this,
"DataProducers", {},
"List of algorithms to be used to resolve data dependencies" };
47 this,
"DataDepsGraphFile",
"",
48 "Name of the output file (.dot or .md extensions allowed) containing the data dependency graph. If empty, no "
63 if ( !
alg )
throw std::runtime_error(
"algorithm pointer == nullptr???" );
67 std::map<std::string, AlgEntry>
80 void visit(
AlgEntry const&
alg, std::vector<std::string>
const& stoppers, std::vector<Gaudi::Algorithm*>& sorted,
81 std::vector<bool>& visited, std::vector<bool>& visiting )
const;
89 struct AlgorithmRepr {
92 friend std::ostream&
operator<<( std::ostream&
s,
const AlgorithmRepr& a ) {
95 if ( a.parent.name() != typ )
s <<
"/" << a.parent.name();
102 std::vector<const DataObjID*> sorted_(
const DataObjIDColl& coll ) {
103 std::vector<const DataObjID*>
v;
104 v.reserve( coll.size() );
105 for (
const DataObjID&
id : coll )
v.push_back( &
id );
106 std::sort(
v.begin(),
v.end(),
107 [](
const DataObjID* a,
const DataObjID* b ) { return a->fullKey() < b->fullKey(); } );
111 template <
typename T>
112 std::vector<const T*> sorted_(
const std::set<T*>&
s ) {
113 std::vector<const T*>
v{
s.begin(),
s.end() };
114 std::sort(
v.begin(),
v.end(), [](
const auto* lhs,
const auto* rhs ) { return *lhs < *rhs; } );
133 std::ranges::views::transform( [](
const auto& entry ) {
return entry.second.alg; } ) |
134 std::ranges::views::filter( [](
const auto*
alg ) {
return alg->cardinality() > 0; } ),
136 this->warning() <<
"non-reentrant algorithm: " << AlgorithmRepr{ *
alg } <<
endmsg;
141 msg <<
"Available DataProducers: ";
143 msg,
m_algorithms,
", ", [](
auto& os,
const std::pair<std::string, AlgEntry>& e ) -> decltype(
auto ) {
144 return os << AlgorithmRepr{ *e.second.alg };
161 ss = algEntry.alg->sysStart();
163 error() <<
"Unable to start Algorithm: " <<
name <<
endmsg;
176 ss = algEntry.alg->sysStop();
178 error() <<
"Unable to stop Algorithm: " <<
name <<
endmsg;
187 algEntry.alg->sysFinalize().
ignore( );
193 std::map<std::string, HiveDataBrokerSvc::AlgEntry>
198 auto appMgr = service<IAlgManager>(
"ApplicationMgr" );
200 for (
const std::string& item : names ) {
214 throw GaudiException{
"Failed to create " + boost::lexical_cast<std::string>( item ), __func__,
221 throw GaudiException{
"Failed to initialize " + boost::lexical_cast<std::string>( item ), __func__,
231 std::map<DataObjID, HiveDataBrokerSvc::AlgEntry const*>
234 debug() <<
"Data Dependencies for Algorithms:";
236 debug() <<
"\n " <<
name <<
" :";
237 for (
const auto*
id : sorted_( entry.alg->inputDataObjs() ) ) { debug() <<
"\n o INPUT " <<
id->key(); }
238 for (
const auto*
id : sorted_( entry.alg->outputDataObjs() ) ) { debug() <<
"\n o OUTPUT " <<
id->key(); }
247 std::map<DataObjID, const AlgEntry*> producers;
249 const auto&
output =
alg.alg->outputDataObjs();
250 if (
output.empty() ) {
continue; }
251 for (
auto id :
output ) {
252 auto r = producers.emplace(
id, &
alg );
255 producers[
id]->
alg->name() +
" at least). This is not allowed",
263 auto input = sorted_( algEntry.alg->inputDataObjs() );
266 auto iproducer = producers.find(
id );
267 if ( iproducer != producers.end() ) {
268 algEntry.dependsOn.insert( iproducer->second );
270 std::ostringstream error_message;
271 error_message <<
"\nUnknown requested input by " << AlgorithmRepr{ *( algEntry.alg ) } <<
" : "
272 << std::quoted(
id.
key(),
'\'' ) <<
".\n";
273 error_message <<
"You can set the OutputLevel of HiveDataBrokerSvc to DEBUG to get a list of inputs and "
274 "outputs of every registered algorithm.\n";
288 std::vector<Gaudi::Algorithm*>& sorted, std::vector<bool>& visited,
289 std::vector<bool>& visiting )
const {
292 if ( visited[
alg.index] ) {
return; }
296 [
alg](
auto& stopper ) {
return alg.alg->name() == stopper; } ) ) {
297 visiting[
alg.index] =
true;
298 for (
auto* dep : sorted_(
alg.dependsOn ) ) {
visit( *dep, stoppers, sorted, visited, visiting ); }
299 visiting[
alg.index] =
false;
302 visited[
alg.index] =
true;
303 sorted.push_back(
alg.alg );
306 std::vector<Gaudi::Algorithm*>
308 const std::vector<std::string>& stoppers )
const {
309 std::vector<Gaudi::Algorithm*> result;
311 std::vector<const AlgEntry*> deps;
312 deps.reserve( requested.size() );
315 for (
const auto&
id : requested ) {
319 deps.push_back( i->second );
322 std::sort( deps.begin(), deps.end(), [](
auto const* lhs,
auto const* rhs ) { return *lhs < *rhs; } );
323 deps.erase( std::unique( deps.begin(), deps.end(), [](
auto const& lhs,
auto const& rhs ) { return *lhs == *rhs; } ),
328 for (
auto*
alg : deps ) {
visit( *
alg, stoppers, result, visited, visiting ); }
332 std::vector<Gaudi::Algorithm*>
334 const std::vector<std::string>& stoppers )
const {
335 std::vector<Gaudi::Algorithm*> result;
339 throw GaudiException{
"No algorithm with name " + requested.
name() +
" in DataProducers. Type is " +
340 ( requested.
haveType() ? requested.
type() :
"not specified" ),
343 auto const&
alg = it->second;
345 error() <<
"requested " << requested <<
" but have matching name with different type: " <<
alg.alg->type()
348 assert(
alg.alg !=
nullptr );
352 visit(
alg, stoppers, result, visited, visiting );
355 debug() << std::endl <<
"requested " << requested <<
" returning " << std::endl <<
" ";
357 debug(), result,
",\n ",
358 [](
auto& os,
const Gaudi::Algorithm* a ) -> decltype(
auto ) {
return os << AlgorithmRepr{ *a }; } );
359 debug() << std::endl <<
endmsg;
366 info() <<
"Dumping data dependencies graph to file: " <<
g.fileName() <<
endmsg;
369 std::set<std::size_t> definedObjects;
372 for (
const auto& [
name, entry] :
m_algorithms ) {
g.addNode( entry.alg->name(), std::to_string( entry.index ) ); }
375 std::unordered_map<std::string, size_t> output2Idx;
377 for (
const auto*
id : sorted_( entry.alg->outputDataObjs() ) ) { output2Idx[
id->key()] = entry.index; }
382 for (
const auto*
id : sorted_( entry.alg->inputDataObjs() ) ) {
383 g.addEdge( entry.alg->name(), std::to_string( entry.index ),
id->key(), std::to_string( output2Idx[
id->key()] ),