3 #include "boost/graph/graph_traits.hpp" 4 #include "boost/graph/graph_utility.hpp" 30 for (
auto i = std::next(cb),
e =
cend(names); i !=
e; ++i) {
44 std::pair<ModuleGraph, std::string>
49 auto const nmodules = modInfos.
size();
64 return std::make_pair(module_graph,
err);
73 std::map<path_name_t, ModuleGraph*> path_graphs;
74 auto const source_index = modInfos.
vertex_index(
"input_source");
75 for (
auto const& path : trigger_paths) {
76 auto& path_graph = module_graph.create_subgraph();
78 add_vertex(source_index, path_graph);
79 path_graphs[path.first.name] = &path_graph;
82 auto vertex_names =
get(boost::vertex_name_t{}, module_graph);
83 for (
auto const& pr : modInfos) {
84 auto const& module_name = pr.first;
85 auto const&
info = pr.second;
88 auto const index = modInfos.vertex_index(pr.first);
89 for (
auto const& path :
info.paths) {
90 add_vertex(
index, *path_graphs.at(path));
92 vertex_names[
index] = module_name;
100 auto edge_label =
get(boost::edge_name,
graph);
102 auto const& modu = modInfos.
info(u);
103 for (
auto const& dep : modu.consumed_products) {
105 auto const edge = add_edge(u, v, graph);
106 edge_label[edge.first] =
"prod";
117 auto path_label =
get(boost::edge_name,
graph);
118 for (
auto const& path : trigger_paths) {
119 auto const& modules = path.second;
122 auto prev =
cbegin(modules);
123 auto curr = prev + 1;
124 auto const end =
cend(modules);
125 while (curr !=
end) {
127 auto const ci = modInfos.
vertex_index(module_label(*curr));
128 auto const edge = add_edge(ci,
pi, graph);
129 path_label[edge.first] =
"path:" + path.first.name;
142 auto const source_index = modInfos.
vertex_index(
"input_source");
143 auto sync_label =
get(boost::edge_name,
graph);
144 if (!trigger_paths.empty()) {
145 auto const tr_index = modInfos.
vertex_index(
"TriggerResults");
146 for (
auto const& path : trigger_paths) {
147 auto const& modules = path.second;
148 if (modules.empty()) {
151 auto const front_index =
153 auto const back_index =
155 auto const edge1 = add_edge(front_index, source_index, graph);
156 sync_label[edge1.first] =
"source:" + path.first.name;
157 auto const edge2 = add_edge(tr_index, back_index, graph);
158 sync_label[edge2.first] =
"sync";
160 for (
auto const&
module : end_path) {
162 auto const edge = add_edge(
index, tr_index, graph);
163 sync_label[edge.first] =
"sync";
165 }
else if (!end_path.empty()) {
166 for (
auto const&
module : end_path) {
168 auto const edge = add_edge(
index, source_index, graph);
169 sync_label[edge.first] =
"sync";
176 for (
auto const& path : trigger_paths) {
177 auto preceding_filter_index = invalid;
178 for (
auto const&
module : path.second) {
181 if (preceding_filter_index != invalid) {
182 auto const edge = add_edge(
index, preceding_filter_index, graph);
183 sync_label[edge.first] =
"filter:" + path.first.name;
186 preceding_filter_index =
index;
191 if (trigger_paths.empty()) {
197 auto const tr_index = modInfos.
vertex_index(
"TriggerResults");
198 for (
auto const&
module : end_path) {
201 for (
auto const& path :
info.select_events) {
202 auto const edge = add_edge(
index, tr_index, graph);
203 sync_label[edge.first] =
"filter:" + path;
213 std::map<Vertex, std::set<Vertex>> illegal_dependencies;
214 auto const children_iters = graph.children();
215 for (
auto ci = children_iters.first, ci_end = children_iters.second;
218 auto const& path_graph = *ci;
219 auto const vertex_iters = vertices(path_graph);
220 for (
auto i = vertex_iters.first,
end = vertex_iters.second; i !=
end;
222 auto const gv = path_graph.local_to_global(*i);
223 auto const out_edge_iters = out_edges(gv, graph);
227 for (
auto ei = out_edge_iters.first, edge_end = out_edge_iters.second;
230 auto const tv =
target(*ei, graph);
231 if (path_graph.find_vertex(tv).second) {
234 illegal_dependencies[gv].insert(tv);
239 if (illegal_dependencies.empty()) {
243 std::ostringstream oss;
244 oss <<
"\nThe following represent cross-path data-dependency errors:\n" 246 for (
auto const& mod : illegal_dependencies) {
247 auto const mod_index = mod.first;
248 auto const& module_name = modInfos.
name(mod_index);
249 auto const& mod_paths = modInfos.
info(mod_index).paths;
250 oss <<
" Module " << module_name <<
" on path" 251 << (mod_paths.size() == 1ull ?
" " :
"s ")
252 << comma_separated_list(mod_paths) <<
" depends on\n";
253 for (
auto const& dep : mod.second) {
254 auto const& dep_name = modInfos.
name(dep);
255 auto const& on_paths = modInfos.
info(dep).paths;
256 oss <<
" Module " << dep_name <<
" on path" 257 << (on_paths.size() == 1ull ?
" " :
"s ")
258 << comma_separated_list(on_paths) <<
'\n';
261 oss <<
"\nSuch errors occur whenever a module on one path depends on the " 263 <<
"from another. Such dependencies can be subtle--for example, a " 265 <<
"uses an event.getManyByType call cannot be shared across paths if " 267 <<
"that precede it in the paths do not give consistent result. Please " 269 <<
"configuration, or email artists@fnal.gov for assistance.\n";
274 struct path_matches {
278 operator()(paths_to_modules_t::value_type
const& pr)
const 280 return pr.first.name == path_name;
284 struct module_matches {
286 explicit module_matches(
std::string const&
name) : module_name{name} {}
290 return module_label(info) == module_name;
301 std::map<module_name_t, name_set_t> illegal_module_orderings;
302 for (
auto const&
module : modInfos) {
303 auto const& module_name =
module.first;
305 auto const& module_paths =
module.second.paths;
309 if (module_paths.empty()) {
315 auto const& first_path_for_module = *
cbegin(module_paths);
316 auto const& path_it = std::find_if(trigger_paths.cbegin(),
317 trigger_paths.cend(),
318 path_matches{first_path_for_module});
319 assert(path_it != trigger_paths.cend());
321 auto const end =
cend(path_it->second);
322 auto const module_position =
323 std::find_if(begin,
end, module_matches{module_name});
324 assert(module_position !=
end);
326 for (
auto const& dep :
module.second.consumed_products) {
327 if (dep.label ==
"input_source") {
330 auto const dep_position =
331 std::find_if(begin,
end, module_matches{dep.label});
332 assert(dep_position !=
end);
333 if (dep_position < module_position) {
336 illegal_module_orderings[module_name].insert(dep.label);
340 if (illegal_module_orderings.empty()) {
344 std::ostringstream oss;
345 oss <<
"\nThe following are module-ordering errors due to declared " 346 "data-product dependencies:\n";
347 for (
auto const& mod : illegal_module_orderings) {
348 auto const& module_name = mod.first;
349 auto const mod_index = modInfos.vertex_index(module_name);
350 auto const& module_paths = modInfos.info(mod_index).paths;
351 oss <<
" Module " << module_name <<
" on path" 352 << (module_paths.size() == 1ull ?
" " :
"s ")
353 << comma_separated_list(module_paths)
354 <<
" depends on either itself or modules that follow it:\n";
355 for (
auto const& dep_name : mod.second) {
356 auto const dep_index = modInfos.vertex_index(dep_name);
357 auto const& on_paths = modInfos.info(dep_index).paths;
358 oss <<
" Module " << dep_name <<
" on path" 359 << (on_paths.size() == 1ull ?
" " :
"s ")
360 << comma_separated_list(on_paths)
361 << (module_name == dep_name ?
" (self circularity)" :
"") <<
'\n';
370 class graph_printer :
public boost::dfs_visitor<> {
372 explicit graph_printer(
374 std::set<Vertex>& vertices,
375 std::map<
path_name_t, std::set<EdgePair>>& path_edges,
376 std::map<
path_name_t, std::set<EdgePair>>& filter_edges,
377 std::set<EdgePair>& trigger_path_edges,
378 std::map<EdgePair, unsigned>& product_edges)
380 , vertices_{vertices}
381 , path_edges_{path_edges}
382 , filter_edges_{filter_edges}
383 , trigger_path_edges_{trigger_path_edges}
384 , product_edges_{product_edges}
412 enum class arrow_style { path, sync, source,
filter, prod };
417 auto pos = edge_name.find(
"path:");
419 return arrow_style::path;
421 pos = edge_name.find(
"sync");
423 return arrow_style::sync;
425 pos = edge_name.find(
"source:");
427 return arrow_style::source;
429 pos = edge_name.find(
"filter:");
433 if (edge_name ==
"prod") {
434 return arrow_style::prod;
438 "An occurred while printing the DOT file for this process.\n"}
439 <<
"The edge name '" << edge_name <<
"' is not recognized.";
445 auto const u = source(e, g);
446 auto const v =
target(e, g);
447 auto const vertex_pair = std::make_pair(u, v);
448 auto const& edge_name =
get(boost::edge_name,
g,
e);
449 switch (arrow_style_for(edge_name)) {
450 case arrow_style::path: {
451 auto path_name = edge_name.substr(5);
452 path_edges_[path_name].insert(vertex_pair);
455 case arrow_style::sync: {
456 trigger_path_edges_.insert(vertex_pair);
459 case arrow_style::source: {
460 auto path_name = edge_name.substr(7);
461 path_edges_[path_name].insert(vertex_pair);
465 auto path_name = edge_name.substr(7);
466 filter_edges_[path_name].insert(vertex_pair);
469 case arrow_style::prod:
470 ++product_edges_[vertex_pair];
475 std::set<Vertex>& vertices_;
476 std::map<path_name_t, std::set<EdgePair>>& path_edges_;
477 std::map<path_name_t, std::set<EdgePair>>& filter_edges_;
478 std::set<EdgePair>& trigger_path_edges_;
479 std::map<EdgePair, unsigned>& product_edges_;
488 std::set<Vertex> vertices;
489 std::map<path_name_t, std::set<EdgePair>> path_edges;
490 std::map<path_name_t, std::set<EdgePair>> filter_edges;
491 std::set<EdgePair> trigger_path_edges;
492 std::map<EdgePair, unsigned> product_edges;
493 graph_printer printer{info_map,
499 boost::depth_first_search(graph, visitor(printer));
503 for (
auto const& v : vertices) {
504 auto const&
name = info_map.
name(v);
505 auto const&
info = info_map.
info(v);
506 if (
name ==
"input_source") {
507 os <<
" \"input_source\"[shape=box label=source]";
508 }
else if (
name ==
"TriggerResults") {
509 os <<
" \"" <<
name <<
'\"';
510 os <<
"[shape=box style=filled fillcolor=black label=\"\" height=0.1 " 513 os <<
" \"" <<
name <<
'\"';
515 os <<
"[style=filled fillcolor=pink]";
522 for (
auto const& pr : path_edges) {
523 auto const& path_name = pr.first;
524 for (
auto const& edge_pair : pr.second) {
525 os <<
" \"" << info_map.
name(edge_pair.first) <<
"\" -> \"" 526 << info_map.
name(edge_pair.second) <<
'\"' <<
"[label=\"" << path_name
527 <<
"\" color=gray];\n";
532 for (
auto const& pr : filter_edges) {
533 auto const& path_name = pr.first;
534 for (
auto const& edge_pair : pr.second) {
535 os <<
" \"" << info_map.
name(edge_pair.first) <<
"\" -> \"" 536 << info_map.
name(edge_pair.second) <<
'\"' <<
"[label=\"" << path_name
537 <<
"\" color=red];\n";
542 for (
auto const& edge_pair : trigger_path_edges) {
543 os <<
" \"" << info_map.
name(edge_pair.first) <<
"\" -> \"" 544 << info_map.
name(edge_pair.second) <<
'\"' 545 <<
"[style=invisible arrowhead=none];\n";
549 for (
auto const& pr : product_edges) {
550 auto const& edge_pair = pr.first;
551 auto const multiplicity = pr.second;
552 os <<
" \"" << info_map.
name(edge_pair.first) <<
"\" -> \"" 553 << info_map.
name(edge_pair.second) <<
'\"';
554 if (multiplicity > 1) {
555 os <<
"[label=\"" << multiplicity <<
"\" color=black]";
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
static constexpr double g
def graph(desc, maker=maker)
boost::graph_traits< ModuleGraph >::edge_descriptor Edge
ModuleType module_type(std::string const &full_key)
#define UNUSED_PRIVATE_FIELD
std::string verify_in_order_dependencies(ModuleGraphInfoMap const &modules, paths_to_modules_t const &trigger_paths)
std::set< std::string > name_set_t
std::vector< WorkerInPath::ConfigInfo > configs_t
cet::exempt_ptr< detail::ModuleConfigInfo const > moduleConfigInfo
void print_module_graph(std::ostream &os, ModuleGraphInfoMap const &modInfos, ModuleGraph const &graph)
std::vector< std::pair< PathSpec, configs_t >> paths_to_modules_t
static int max(int a, int b)
void err(const char *fmt,...)
auto vertex_index(module_name_t const &name) const -> distance_t
bool is_modifier(ModuleType const mt)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
auto const & info(std::size_t const i) const
void make_synchronization_edges(ModuleGraphInfoMap const &modInfos, paths_to_modules_t const &trigger_paths, configs_t const &end_path, ModuleGraph &graph)
void make_trigger_path_subgraphs(ModuleGraphInfoMap const &modInfos, paths_to_modules_t const &trigger_paths, ModuleGraph &graph)
std::pair< Vertex, Vertex > EdgePair
auto const & name(std::size_t const i) const
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
boost::subgraph< Graph > ModuleGraph
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
static unsigned filter(unsigned char *out, const unsigned char *in, unsigned w, unsigned h, const LodePNG_InfoColor *info)
std::string verify_no_interpath_dependencies(ModuleGraphInfoMap const &modInfos, ModuleGraph const &graph)
static std::vector< std::string > const names
std::string module_name_t
void make_path_ordering_edges(ModuleGraphInfoMap const &modInfos, paths_to_modules_t const &paths, ModuleGraph &graph)
std::pair< ModuleGraph, std::string > make_module_graph(ModuleGraphInfoMap const &modInfos, paths_to_modules_t const &trigger_paths, configs_t const &end_path)
void make_product_dependency_edges(ModuleGraphInfoMap const &modInfos, ModuleGraph &graph)