18 #include <boost/lexical_cast.hpp>
19 #include <boost/tokenizer.hpp>
22 #ifdef __cpp_lib_ranges
24 namespace ranges = std::ranges;
26 # include <range/v3/algorithm/for_each.hpp>
27 # include <range/v3/view/filter.hpp>
28 # include <range/v3/view/reverse.hpp>
29 # include <range/v3/view/transform.hpp>
31 # if RANGE_V3_VERSION < 900
33 using namespace ranges::view;
40 using extends::extends;
42 std::vector<Gaudi::Algorithm*> algorithmsRequiredFor(
const DataObjIDColl& requested,
43 const std::vector<std::string>& stoppers = {} )
const override;
45 const std::vector<std::string>& stoppers = {} )
const override;
54 "Attribute any unmet input dependencies to this Algorithm" };
56 this,
"DataProducers", {},
"List of algorithms to be used to resolve data dependencies" };
70 if ( !
alg )
throw std::runtime_error(
"algorithm pointer == nullptr???" );
74 std::map<std::string, AlgEntry>
75 instantiateAndInitializeAlgorithms(
const std::vector<std::string>& names )
const;
83 std::map<DataObjID, AlgEntry const*> mapProducers( std::map<std::string, AlgEntry>&
algorithms )
const;
87 void visit(
AlgEntry const&
alg, std::vector<std::string>
const& stoppers, std::vector<Gaudi::Algorithm*>& sorted,
88 std::vector<bool>& visited, std::vector<bool>& visiting )
const;
94 struct AlgorithmRepr {
97 friend std::ostream&
operator<<( std::ostream&
s,
const AlgorithmRepr& a ) {
100 if ( a.parent.name() != typ )
s <<
"/" << a.parent.name();
107 std::vector<const DataObjID*> sorted_(
const DataObjIDColl& coll ) {
108 std::vector<const DataObjID*>
v;
109 v.reserve( coll.size() );
110 for (
const DataObjID&
id : coll )
v.push_back( &
id );
111 std::sort(
v.begin(),
v.end(),
112 [](
const DataObjID* a,
const DataObjID* b ) { return a->fullKey() < b->fullKey(); } );
116 template <
typename T>
117 std::vector<const T*> sorted_(
const std::set<T*>&
s ) {
118 std::vector<const T*>
v{
s.begin(),
s.end() };
119 std::sort(
v.begin(),
v.end(), [](
const auto* lhs,
const auto* rhs ) { return *lhs < *rhs; } );
134 m_algorithms = instantiateAndInitializeAlgorithms( m_producers );
137 ranges::for_each( m_algorithms | ranges::views::transform( [](
const auto& entry ) {
return entry.second.alg; } ) |
138 ranges::views::filter( [](
const auto*
alg ) {
return alg->cardinality() > 0; } ),
140 this->warning() <<
"non-reentrant algorithm: " << AlgorithmRepr{ *
alg } <<
endmsg;
145 msg <<
"Available DataProducers: ";
147 msg, m_algorithms,
", ", [](
auto& os,
const std::pair<std::string, AlgEntry>& e ) -> decltype(
auto ) {
148 return os << AlgorithmRepr{ *e.second.alg };
154 m_dependencies = mapProducers( m_algorithms );
164 for (
auto& [
name, algEntry] : m_algorithms ) {
165 ss = algEntry.alg->sysStart();
167 error() <<
"Unable to start Algorithm: " <<
name <<
endmsg;
179 for (
auto& [
name, algEntry] : m_algorithms ) {
180 ss = algEntry.alg->sysStop();
182 error() <<
"Unable to stop Algorithm: " <<
name <<
endmsg;
190 for (
auto& [
name, algEntry] : m_algorithms ) {
191 algEntry.alg->sysFinalize().
ignore( );
193 m_algorithms.clear();
197 std::map<std::string, HiveDataBrokerSvc::AlgEntry>
202 auto appMgr = service<IAlgManager>(
"ApplicationMgr" );
204 for (
const std::string& item : names ) {
218 throw GaudiException{
"Failed to create " + boost::lexical_cast<std::string>( item ), __func__,
225 throw GaudiException{
"Failed to initialize " + boost::lexical_cast<std::string>( item ), __func__,
235 std::map<DataObjID, HiveDataBrokerSvc::AlgEntry const*>
238 debug() <<
"Data Dependencies for Algorithms:";
239 for (
const auto& [
name, entry] : m_algorithms ) {
240 debug() <<
"\n " <<
name <<
" :";
241 for (
const auto*
id : sorted_( entry.alg->inputDataObjs() ) ) { debug() <<
"\n o INPUT " <<
id->key(); }
242 for (
const auto*
id : sorted_( entry.alg->outputDataObjs() ) ) { debug() <<
"\n o OUTPUT " <<
id->key(); }
248 std::map<DataObjID, const AlgEntry*> producers;
250 const auto&
output =
alg.alg->outputDataObjs();
251 if (
output.empty() ) {
continue; }
252 for (
auto id :
output ) {
253 auto r = producers.emplace(
id, &
alg );
256 producers[
id]->
alg->name() +
" at least). This is not allowed",
264 auto input = sorted_( algEntry.alg->inputDataObjs() );
267 auto iproducer = producers.find(
id );
268 if ( iproducer != producers.end() ) {
269 algEntry.dependsOn.insert( iproducer->second );
271 std::ostringstream error_message;
272 error_message <<
"\nUnknown requested input by " << AlgorithmRepr{ *( algEntry.alg ) } <<
" : "
273 << std::quoted(
id.
key(),
'\'' ) <<
".\n";
274 error_message <<
"You can set the OutputLevel of HiveDataBrokerSvc to DEBUG to get a list of inputs and "
275 "outputs of every registered algorithm.\n";
289 std::vector<Gaudi::Algorithm*>& sorted, std::vector<bool>& visited,
290 std::vector<bool>& visiting )
const {
291 assert( visited.size() == m_algorithms.size() );
292 assert( visiting.size() == m_algorithms.size() );
293 if ( visited[
alg.index] ) {
return; }
297 [
alg](
auto& stopper ) {
return alg.alg->name() == stopper; } ) ) {
298 visiting[
alg.index] =
true;
299 for (
auto* dep : sorted_(
alg.dependsOn ) ) { visit( *dep, stoppers, sorted, visited, visiting ); }
300 visiting[
alg.index] =
false;
303 visited[
alg.index] =
true;
304 sorted.push_back(
alg.alg );
307 std::vector<Gaudi::Algorithm*>
309 const std::vector<std::string>& stoppers )
const {
310 std::vector<Gaudi::Algorithm*> result;
312 std::vector<const AlgEntry*> deps;
313 deps.reserve( requested.size() );
316 for (
const auto&
id : requested ) {
317 auto i = m_dependencies.find(
id );
318 if ( i == m_dependencies.end() )
320 deps.push_back( i->second );
323 std::sort( deps.begin(), deps.end(), [](
auto const* lhs,
auto const* rhs ) { return *lhs < *rhs; } );
324 deps.erase( std::unique( deps.begin(), deps.end(), [](
auto const& lhs,
auto const& rhs ) { return *lhs == *rhs; } ),
327 std::vector<bool> visited( m_algorithms.size() );
328 std::vector<bool> visiting( m_algorithms.size() );
329 for (
auto*
alg : deps ) { visit( *
alg, stoppers, result, visited, visiting ); }
333 std::vector<Gaudi::Algorithm*>
335 const std::vector<std::string>& stoppers )
const {
336 std::vector<Gaudi::Algorithm*> result;
338 auto it = m_algorithms.find( requested.
name() );
339 if ( it ==
end( m_algorithms ) ) {
340 throw GaudiException{
"No algorithm with name " + requested.
name() +
" in DataProducers. Type is " +
341 ( requested.
haveType() ? requested.
type() :
"not specified" ),
344 auto const&
alg = it->second;
346 error() <<
"requested " << requested <<
" but have matching name with different type: " <<
alg.alg->type()
349 assert(
alg.alg !=
nullptr );
351 std::vector<bool> visited( m_algorithms.size() );
352 std::vector<bool> visiting( m_algorithms.size() );
353 visit(
alg, stoppers, result, visited, visiting );
356 debug() << std::endl <<
"requested " << requested <<
" returning " << std::endl <<
" ";
358 debug(), result,
",\n ",
359 [](
auto& os,
const Gaudi::Algorithm* a ) -> decltype(
auto ) {
return os << AlgorithmRepr{ *a }; } );
360 debug() << std::endl <<
endmsg;