Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions phlex/core/framework_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "phlex/concurrency.hpp"
#include "phlex/core/make_computational_edges.hpp"
#include "phlex/model/product_store.hpp"
#include "phlex/utilities/bulleted_list.hpp"

#include "fmt/format.h"
#include "fmt/ranges.h"
Expand Down Expand Up @@ -69,7 +70,7 @@ namespace phlex::experimental {
std::size_t framework_graph::seen_cell_count(std::string const& layer_name,
bool const missing_ok) const
{
return hierarchy_.count_for(layer_name, missing_ok);
return hierarchy_.count_for(experimental::layer_path(layer_name), missing_ok);
}

std::size_t framework_graph::execution_count(std::string const& node_name) const
Expand Down Expand Up @@ -136,7 +137,7 @@ namespace phlex::experimental {
return;
}
throw std::runtime_error(
fmt::format("\nConfiguration errors:\n - {}", fmt::join(registration_errors_, "\n - ")));
fmt::format("\nConfiguration errors:\n{}", bulleted_list(registration_errors_)));
}

void framework_graph::make_filter_edges()
Expand Down
67 changes: 22 additions & 45 deletions phlex/core/index_router.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "phlex/core/index_router.hpp"

#include "phlex/model/flush_gate.hpp"
#include "phlex/utilities/bulleted_list.hpp"
#include "phlex/utilities/hashing.hpp"

#include "fmt/std.h"
Expand All @@ -14,34 +15,6 @@

using namespace phlex::experimental;

namespace {
using layer_path_t = std::vector<std::string>;

std::size_t layer_hash_for_path(layer_path_t const& layer_path)
{
std::size_t result = "job"_id.hash();
for (auto const& layer_name : layer_path | std::views::drop(1)) {
result = hash(result, identifier{layer_name}.hash());
}
return result;
}

bool is_strict_prefix(layer_path_t const& candidate, layer_path_t const& other)
{
// FIXME: Use std::ranges::starts_with(other, candidate) once the compilers support it (C++23)
return candidate.size() < other.size() and
std::ranges::mismatch(other, candidate).in2 == std::ranges::end(candidate);
}

std::string delimited_layer_path(std::string_view const layer_path)
{
if (not layer_path.starts_with("/")) {
return fmt::format("/{}", layer_path);
}
return std::string{layer_path};
}
}

namespace phlex::experimental {

//========================================================================================
Expand All @@ -57,7 +30,7 @@ namespace phlex::experimental {
void put_message(data_cell_index_ptr const& index, std::size_t message_id);
void put_end_token(data_cell_index_ptr const& index, flush_gate const& fc);

bool matches_exactly(std::string const& layer_path) const;
bool matches_exactly(layer_path const& layer_path) const;
bool is_parent_of(data_cell_index_ptr const& index) const;

private:
Expand Down Expand Up @@ -93,9 +66,9 @@ namespace phlex::experimental {
flusher_.try_put({.index = index, .count = static_cast<int>(fc.committed_total_count())});
}

bool multilayer_slot::matches_exactly(std::string const& layer_path) const
bool multilayer_slot::matches_exactly(layer_path const& layer_path) const
{
return layer_path.ends_with(delimited_layer_path(static_cast<std::string_view>(layer_)));
return layer_path.ends_with(layer_);
}

bool multilayer_slot::is_parent_of(data_cell_index_ptr const& index) const
Expand Down Expand Up @@ -131,16 +104,22 @@ namespace phlex::experimental {
std::vector<identifier> unfold_input_layer_names,
std::vector<identifier> unfold_output_layer_names)
{
auto sorted_layer_paths = layer_paths_from_driver;
auto sorted_layer_paths =
layer_paths_from_driver | std::views::transform([](auto const& lp) {
auto lp_as_ids = lp |
std::views::transform([](auto const& str) { return identifier(str); }) |
std::ranges::to<std::vector>();
return layer_path(std::move(lp_as_ids));
}) |
std::ranges::to<std::vector<layer_path>>();
std::ranges::sort(sorted_layer_paths);

// In sorted order, a path can only be a prefix of paths that follow it.
for (std::size_t i = 0; i < sorted_layer_paths.size(); ++i) {
for (std::size_t i = 0; i + 1 < sorted_layer_paths.size(); ++i) {
bool const is_not_lowest_layer =
i + 1 < sorted_layer_paths.size() and
is_strict_prefix(sorted_layer_paths[i], sorted_layer_paths[i + 1]);
sorted_layer_paths[i].is_strict_prefix_of(sorted_layer_paths[i + 1]);
if (is_not_lowest_layer) {
auto const layer_hash = layer_hash_for_path(sorted_layer_paths[i]);
auto const layer_hash = sorted_layer_paths[i].hash();
is_lowest_layer_hashes_.emplace(layer_hash, false);
}
}
Expand Down Expand Up @@ -252,19 +231,17 @@ namespace phlex::experimental {
return it->second;
}

std::string const layerish_path{static_cast<std::string_view>(index->layer_name())};
layer_path const layerish_path{{index->layer_name()}};
auto broadcaster = index_set_node_for(layerish_path);
index_set_node_cache_.insert({layer_hash, broadcaster});
return broadcaster;
}

auto index_router::index_set_node_for(std::string const& layer_path) -> detail::index_set_node_ptr
auto index_router::index_set_node_for(layer_path const& layer_path) -> detail::index_set_node_ptr
{
std::string const search_token = delimited_layer_path(layer_path);

std::vector<decltype(index_set_nodes_.begin())> candidates;
for (auto it = index_set_nodes_.begin(), e = index_set_nodes_.end(); it != e; ++it) {
if (search_token.ends_with(delimited_layer_path(static_cast<std::string_view>(it->first)))) {
if (layer_path.ends_with(it->first)) {
candidates.push_back(it);
}
}
Expand All @@ -277,10 +254,10 @@ namespace phlex::experimental {
return nullptr;
}

std::string msg = fmt::format("Multiple layers match specification {}:\n", layer_path);
for (auto const& it : candidates) {
msg += fmt::format("\n- {}", it->first);
}
std::string msg = fmt::format(
"Multiple layers match specification {}:\n{}",
layer_path,
bulleted_list(candidates | std::views::transform([](auto const& it) { return it->first; })));
throw std::runtime_error(msg);
}

Expand Down
2 changes: 1 addition & 1 deletion phlex/core/index_router.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ namespace phlex::experimental {
// correct for unfold outputs (the only source of unknown hashes) and consistent with
// index_is_lowest_layer()'s fall-through default.
bool is_lowest_layer_hash(std::size_t layer_hash) const;
detail::index_set_node_ptr index_set_node_for(std::string const& layer);
detail::index_set_node_ptr index_set_node_for(layer_path const& layer);
detail::index_set_node_ptr index_set_node_for(data_cell_index_ptr const& index);
std::pair<detail::multilayer_slots_ptr, detail::multilayer_slots_ptr> multilayer_slots_for(
data_cell_index_ptr const& index);
Expand Down
13 changes: 6 additions & 7 deletions phlex/core/input_arguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "phlex/core/message.hpp"
#include "phlex/core/product_selector.hpp"
#include "phlex/model/handle.hpp"
#include "phlex/utilities/bulleted_list.hpp"

#include "fmt/format.h"

Expand Down Expand Up @@ -32,18 +33,16 @@ namespace phlex::experimental {
std::ranges::to<std::vector>();
if (products.empty()) {
throw std::runtime_error(fmt::format(
"No products found matching the query {}\n Store (id {} from {}) contains:\n - {}",
"No products found matching the query {}\n Store (id {} from {}) contains:\n{}",
query,
store->index()->to_string(),
store->source().to_string(),
fmt::join(all_products | views::transform(&product_specification::to_string),
"\n - ")));
bulleted_list(all_products, /*indent=*/4)));
}
if (products.size() > 1) {
throw std::runtime_error(fmt::format(
"Multiple products found matching the query {}:\n - {}",
query,
fmt::join(products | views::transform(&product_specification::to_string), "\n - ")));
throw std::runtime_error(fmt::format("Multiple products found matching the query {}:\n{}",
query,
bulleted_list(products, /*indent=*/4)));
}
return store->get_handle<handle_arg_t>(products[0]);
}
Expand Down
5 changes: 3 additions & 2 deletions phlex/core/producer_catalog.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "phlex/core/producer_catalog.hpp"
#include "phlex/utilities/bulleted_list.hpp"

#include "fmt/format.h"
#include "fmt/ranges.h"
Expand Down Expand Up @@ -75,9 +76,9 @@ namespace phlex::experimental {
}

if (candidates.size() > 1ull) {
std::string msg = fmt::format("More than one candidate matches the query {}: \n - {}\n",
std::string msg = fmt::format("More than one candidate matches the query {}: \n{}\n",
query.to_string(),
fmt::join(std::views::keys(candidates), "\n - "));
bulleted_list(std::views::keys(candidates), /*indent=*/1));
throw std::runtime_error(msg);
}

Expand Down
2 changes: 2 additions & 0 deletions phlex/model/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cet_make_library(
data_layer_hierarchy.cpp
data_cell_index.cpp
identifier.cpp
layer_path.cpp
product_matcher.cpp
product_store.cpp
products.cpp
Expand Down Expand Up @@ -39,6 +40,7 @@ install(
data_layer_hierarchy.hpp
data_cell_index.hpp
identifier.hpp
layer_path.hpp
product_matcher.hpp
product_specification.hpp
product_store.hpp
Expand Down
15 changes: 8 additions & 7 deletions phlex/model/data_cell_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,16 @@ namespace phlex {
return layer_name_;
}

std::string data_cell_index::layer_path() const
experimental::layer_path data_cell_index::layer_path() const
{
std::vector layers_in_reverse{std::string_view(layer_name_)};
auto next_parent = parent();
while (next_parent) {
layers_in_reverse.push_back(std::string_view(next_parent->layer_name()));
next_parent = next_parent->parent();
// We know how deep we are so we can pre-allocate and fill in reverse
std::vector<experimental::identifier> layers(depth_ + 1);
auto const* ptr = this;
for (auto& layer : std::views::reverse(layers)) {
layer = ptr->layer_name();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add an assert(ptr); before this to indicate that it is a precondition for the pointer to be valid.

ptr = ptr->parent_.get();
}
return fmt::format("/{}", fmt::join(std::views::reverse(layers_in_reverse), "/"));
return experimental::layer_path{std::move(layers)};
}

std::size_t data_cell_index::depth() const noexcept { return depth_; }
Expand Down
3 changes: 2 additions & 1 deletion phlex/model/data_cell_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "phlex/model/fwd.hpp"
#include "phlex/model/identifier.hpp"
#include "phlex/model/layer_path.hpp"

#include <cstddef>
#include <initializer_list>
Expand All @@ -23,7 +24,7 @@ namespace phlex {
using hash_type = std::size_t;
data_cell_index_ptr make_child(std::string layer_name, std::size_t data_cell_number) const;
experimental::identifier const& layer_name() const noexcept;
std::string layer_path() const;
experimental::layer_path layer_path() const;
std::size_t depth() const noexcept;
data_cell_index_ptr parent(experimental::identifier const& layer_name) const;
data_cell_index_ptr parent() const noexcept;
Expand Down
30 changes: 16 additions & 14 deletions phlex/model/data_layer_hierarchy.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "phlex/model/data_layer_hierarchy.hpp"
#include "phlex/model/data_cell_index.hpp"

#include "phlex/utilities/bulleted_list.hpp"

#include "fmt/format.h"
#include "fmt/std.h"
#include "spdlog/spdlog.h"
Expand Down Expand Up @@ -35,32 +37,32 @@ namespace phlex::experimental {
++it->second->count;
}

std::size_t data_layer_hierarchy::count_for(std::string const& layer, bool const missing_ok) const
std::size_t data_layer_hierarchy::count_for(layer_path const& layer, bool const missing_ok) const
{
// The assumption is that specified layer is the component of a layer path
std::string search_token = layer;
if (not layer.starts_with("/")) {
search_token = '/' + layer;
}

// The assumption is that specified layer is a portion of a layer path
// sufficient to uniquely identify a layer
std::vector<layer_entry const*> candidates;
for (auto const& [_, entry] : layers_) {
if (entry->layer_path.ends_with(search_token)) {
if (entry->layer_path.ends_with(layer)) {
candidates.push_back(entry.get());
}
}

if (candidates.empty()) {
return missing_ok ? 0ull
: throw std::runtime_error("No layers match the specification " + layer);
: throw std::runtime_error(
fmt::format("No layers match the specification {}", layer));
}

if (candidates.size() > 1ull) {
std::string msg{"The following data layers match the specification " + layer + ":\n"};
for (auto const* entry : candidates) {
msg += "\n- " + entry->layer_path;
}
msg += "\n\nPlease specify the full layer path to disambiguate between them.";
std::string msg =
fmt::format("The following data layers match the specification {}:\n\n{}"
"\n\nPlease specify the full layer path to disambiguate between them.",
layer,
bulleted_list(candidates | std::views::transform([](auto const* entry) {
return entry->layer_path;
}),
/*indent=*/0));
throw std::runtime_error(msg);
}

Expand Down
7 changes: 4 additions & 3 deletions phlex/model/data_layer_hierarchy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "phlex/model/data_cell_index.hpp"
#include "phlex/model/fwd.hpp"
#include "phlex/model/layer_path.hpp"

#include "oneapi/tbb/concurrent_unordered_map.h"

Expand All @@ -25,7 +26,7 @@ namespace phlex::experimental {
data_layer_hierarchy& operator=(data_layer_hierarchy&&) = delete;

void increment_count(data_cell_index_ptr const& id);
std::size_t count_for(std::string const& layer, bool missing_ok = false) const;
std::size_t count_for(layer_path const& layer, bool missing_ok = false) const;

void print() const;

Expand All @@ -39,13 +40,13 @@ namespace phlex::experimental {
std::string indent = {}) const;

struct layer_entry {
layer_entry(identifier n, std::string path, std::size_t par_hash) :
layer_entry(identifier n, experimental::layer_path path, std::size_t par_hash) :

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

experimental:: qualifier not needed here.

name{std::move(n)}, layer_path{std::move(path)}, parent_hash{par_hash}
{
}

identifier name;
std::string layer_path;
experimental::layer_path layer_path;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

experimental:: qualifier not needed here.

std::size_t parent_hash;
std::atomic<std::size_t> count{};
};
Expand Down
2 changes: 1 addition & 1 deletion phlex/model/fixed_hierarchy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace phlex {
return data_cell_cursor{child, hierarchy_, driver_};
}

std::string data_cell_cursor::layer_path() const { return index_->layer_path(); }
experimental::layer_path data_cell_cursor::layer_path() const { return index_->layer_path(); }

// ================================================================================
// data_cell_yielder implementation
Expand Down
3 changes: 2 additions & 1 deletion phlex/model/fixed_hierarchy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "phlex/phlex_model_export.hpp"

#include "phlex/model/fwd.hpp"
#include "phlex/model/layer_path.hpp"

#include <cstddef>
#include <initializer_list>
Expand All @@ -25,7 +26,7 @@ namespace phlex {
// data-cell index to the underlying driver, returning a data_cell_cursor for the child.
data_cell_cursor yield_child(std::string const& layer_name, std::size_t number) const;

std::string layer_path() const;
experimental::layer_path layer_path() const;

private:
friend class fixed_hierarchy;
Expand Down
2 changes: 1 addition & 1 deletion phlex/model/handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ namespace phlex {
}
std::string_view suffix() const noexcept { return std::string_view(suffix_); }
std::string_view layer() const noexcept { return std::string_view(id_->layer_name()); }
std::string layer_path() const { return id_->layer_path(); }
std::string layer_path() const { return id_->layer_path().to_string(); }

template <typename U>
friend class handle;
Expand Down
Loading
Loading