first commit
This commit is contained in:
180
utils/vp_pipe_checker.h
Executable file
180
utils/vp_pipe_checker.h
Executable file
@@ -0,0 +1,180 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include "vp_version.h"
|
||||
#include "../nodes/vp_node.h"
|
||||
#include "../excepts/vp_invalid_pipeline_error.h"
|
||||
|
||||
namespace vp_utils {
|
||||
class vp_pipe_checker
|
||||
{
|
||||
private:
|
||||
// we can only handle the pipeline structure like below, totally symmetrical vertically for each layer.
|
||||
/*
|
||||
* |1st layer| |2nd layer| |3rd layer| |4th layer| |5th layer|
|
||||
* node -...- node \ / node -...- node
|
||||
*
|
||||
* node -...- node - -...- node -...- node -...- node
|
||||
*
|
||||
* node -...- node / \ node -...- node
|
||||
*
|
||||
*/
|
||||
void check_layer(std::vector<std::shared_ptr<vp_nodes::vp_node>> nodes_in_layer) {
|
||||
num_layers_in_pipe++;
|
||||
|
||||
int next_nodes_num = -1;
|
||||
std::vector<std::shared_ptr<vp_nodes::vp_node>> all_next_nodes;
|
||||
|
||||
// check for:
|
||||
// 1. node type of start/end point of pipe
|
||||
// 2. node names in pipe
|
||||
// 3. next nodes number
|
||||
for(auto& i : nodes_in_layer) {
|
||||
// check for the first layer, all nodes MUST be vp_nodes::vp_node_type::SRC
|
||||
if (num_layers_in_pipe == 1 &&
|
||||
i->node_type() != vp_nodes::vp_node_type::SRC) {
|
||||
throw vp_excepts::vp_invalid_pipeline_error("pipe MUST starts with SRC nodes!");
|
||||
}
|
||||
|
||||
auto name = i->node_name;
|
||||
// check if node name duplicated
|
||||
if (std::find_if(std::begin(node_names_in_pipe),
|
||||
std::end(node_names_in_pipe),
|
||||
[&](std::pair<int, std::vector<std::string>> p){ return std::find(std::begin(p.second), std::end(p.second), name) != std::end(p.second);})
|
||||
!=
|
||||
std::end(node_names_in_pipe)) {
|
||||
throw vp_excepts::vp_invalid_pipeline_error("node names MUST not be duplicated in pipe!");
|
||||
}
|
||||
node_names_in_pipe[num_layers_in_pipe].push_back(name);
|
||||
|
||||
auto next_nodes = i->next_nodes();
|
||||
auto _num = next_nodes.size();
|
||||
|
||||
// check for the last layer, all nodes MUST be vp_nodes::vp_node_type::DES
|
||||
if (_num == 0 && i->node_type() != vp_nodes::vp_node_type::DES) {
|
||||
throw vp_excepts::vp_invalid_pipeline_error("pipe MUST ends with DES nodes!");
|
||||
}
|
||||
|
||||
// initialize next_nodes_num variable, all nodes in current layer should have the same next_nodes_num.
|
||||
if (next_nodes_num == -1) {
|
||||
next_nodes_num = _num;
|
||||
}
|
||||
|
||||
// the next nodes number of each node in the same layer must be equal (all are 0 for des nodes).
|
||||
if (next_nodes_num != _num) {
|
||||
throw vp_excepts::vp_invalid_pipeline_error("all nodes in the same layer MUST have the same next nodes number!");
|
||||
}
|
||||
|
||||
// merge next nodes of each node into a big vector
|
||||
all_next_nodes.insert(all_next_nodes.end(), next_nodes.begin(), next_nodes.end());
|
||||
}
|
||||
|
||||
// check for 2 conditions:
|
||||
// 1. all next nodes are the same, or
|
||||
// 2. all next nodes are distinc.
|
||||
if (all_next_nodes.size() != 0) {
|
||||
bool all_the_same = true;
|
||||
bool all_distinct = true;
|
||||
// check if all the next nodes are the same
|
||||
for(auto & i: all_next_nodes) {
|
||||
if (i != all_next_nodes[0])
|
||||
{
|
||||
all_the_same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if all next nodes are distinct
|
||||
if (!all_the_same) {
|
||||
std::sort(std::begin(all_next_nodes), std::end(all_next_nodes));
|
||||
auto pos = std::adjacent_find(std::begin(all_next_nodes), std::end(all_next_nodes));
|
||||
if (pos != std::end(all_next_nodes)) {
|
||||
all_distinct = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_the_same && !all_distinct) {
|
||||
throw vp_excepts::vp_invalid_pipeline_error("the next nodes of each node in the same layer MUST be the same or be distinct totally!");
|
||||
}
|
||||
|
||||
// just keep the first one if all the next nodes are the same
|
||||
if (all_the_same) {
|
||||
all_next_nodes.erase(all_next_nodes.begin() + 1, all_next_nodes.end());
|
||||
}
|
||||
|
||||
// recursion for next layer
|
||||
check_layer(all_next_nodes);
|
||||
}
|
||||
}
|
||||
// layer_index -> node_names
|
||||
std::map<int, std::vector<std::string>> node_names_in_pipe;
|
||||
int num_layers_in_pipe = 0;
|
||||
bool summary;
|
||||
public:
|
||||
vp_pipe_checker(bool summary = true) {
|
||||
summary = summary;
|
||||
}
|
||||
|
||||
// total layers
|
||||
int pipe_width() {
|
||||
return num_layers_in_pipe;
|
||||
}
|
||||
|
||||
// max number of nodes in all layers
|
||||
int pipe_height() {
|
||||
int number = 0;
|
||||
for(auto & i : node_names_in_pipe) {
|
||||
if (i.second.size() > number) {
|
||||
number = i.second.size();
|
||||
}
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
void operator()(std::vector<std::shared_ptr<vp_nodes::vp_node>> pipe_src_nodes) {
|
||||
// start check with the 1st layer
|
||||
check_layer(pipe_src_nodes);
|
||||
|
||||
if (summary) {
|
||||
/*
|
||||
std::cout << "############# pipe check summary ##############" << std::endl;
|
||||
std::cout << " total layers: " << num_layers_in_pipe << std::endl;
|
||||
std::cout << " layer index, node names" << std::endl;
|
||||
for(auto & i : node_names_in_pipe) {
|
||||
std::cout << " " << i.first << " ";
|
||||
for(auto & j : i.second) {
|
||||
std::cout << j << ",";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << ############# pipe check summary ############## << std::endl;
|
||||
*/
|
||||
|
||||
std::ostringstream v_stream;
|
||||
v_stream << "\n################ version info #################\n";
|
||||
v_stream << " build_time: " << APP_BUILD_TIME << "\n";
|
||||
v_stream << " commit_hash: " << APP_GIT_COMMIT << "\n";
|
||||
v_stream << " version: " << APP_VERSION << "\n";
|
||||
v_stream << "################ version info ################" << "\n";
|
||||
// to log
|
||||
VP_INFO(v_stream.str());
|
||||
|
||||
std::ostringstream s_stream;
|
||||
s_stream << "\n############# pipe check summary ##############\n";
|
||||
s_stream << " total layers: " << num_layers_in_pipe << "\n";
|
||||
s_stream << " layer index, node names" << "\n";
|
||||
for(auto & i : node_names_in_pipe) {
|
||||
s_stream << " " << i.first << " ";
|
||||
for(auto & j : i.second) {
|
||||
s_stream << j << ",";
|
||||
}
|
||||
s_stream << "\n";
|
||||
}
|
||||
s_stream << "############# pipe check summary ##############" << "\n";
|
||||
|
||||
// to log
|
||||
VP_INFO(s_stream.str());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user